Skip to main content
Audact
See the offer

Show what followed, line by line.

For governed interactions a compliance receipt is visible in the product. It records what the system received, what it decided and what it sent — as hashes, chained to the receipt before it and gathered into a Merkle root. Three of those elements can be recomputed today by anyone holding the receipt: no key, no account, no access to our database.

Compliance receipt

Worked example
Input hash
0xfeb0ca5b0546ad8c…5092dcae
No key needed
Output hash
0x97d47018e45e19e1…83c557d9
No key needed
Previous receipt
0xbfafe10889982fd2…09fe0579
No key needed
Merkle root
0x6e00080f64cff7d5…07658346
In development
Authentication code
0xfd73071e00fa7837…415b54aa
Tenant key needed

Worked example. Acme GmbH and Nova Industries are fictional; no customer data appears here. These are the values of the receipt at /sample-receipt.json. /receipt-explorer recomputes the three key-free values in your own browser, and folds the leaf up to the Merkle root printed in that same file — which is not the same as setting it against a root published outside our systems.

Current evidence state

  • Receipt in the productVisible
  • Production exportWorking today
  • Three hash checksPublic
  • External root publicationIn development
  • Public issuer verificationNot available

Five states, not one. Each is set out below, with what it rests on.

Field by field

What a receipt holds

A receipt is one object per governed interaction. Most of it is a record: you can read it, and reading it tells you what the system believed at the time. Four fields behave differently: they can be recomputed, and a recomputation either matches or does not. Three of those need nothing but the receipt; the fourth folds up to the Merkle root the receipt carries, and setting that against a root published outside our systems has to wait until we publish the roots.

  • Field
    receipt_id
    What it records
    The receipt's own identifier.
    Check
    Read
  • Field
    issued_at
    What it records
    When the receipt was written, by our clock.
    Check
    Read
  • Field
    input
    What it records
    What the agent proposed: principal, counterparty, agent, mandate and version, channel, jurisdiction and amount.
    Check
    Read
  • Field
    input_hash
    What it records
    SHA-256 over the input block, as the system received it.
    Check
    Recompute
  • Field
    output
    What it records
    What was decided: the authority position, the excess, the decision and the clearance reference.
    Check
    Read
  • Field
    output_hash
    What it records
    SHA-256 over the output block, as the system recorded it.
    Check
    Recompute
  • Field
    previous
    What it records
    The receipt written before this one, in its five core fields: receipt_id, issued_at, input_hash, output_hash, previous_receipt_hash.
    Check
    Read
  • Field
    previous_receipt_hash
    What it records
    SHA-256 over exactly those five fields. This is what makes it a chain.
    Check
    Recompute
  • Field
    receipt_hash
    What it records
    The same five fields of this receipt, hashed. That value is the leaf the inclusion check starts from.
    Check
    Read
  • Field
    merkle.root · merkle.path · merkle.leaf_index
    What it records
    The root this receipt carries, the sibling hashes on the way up to it, and this receipt's position in the batch. Setting it against a root published outside our systems waits for that publication.
    Check
    In development
  • Field
    auth.alg · auth.key_ref · auth.mac
    What it records
    HMAC-SHA256 over the canonical receipt, under a symmetric key held per tenant, and which key made it.
    Check
    Key needed
  • Field
    _sample · _disclaimer · _generated
    What it records
    The three lines at the top of the file: what this sample is, what it does not establish, and which script wrote it.
    Check
    Read

Every name in this column is a field of the illustrative sample at /sample-receipt.json, spelled the way the file spells it: open the file and each one is there. Where naming something would mean inventing a field path, the row is not in this table.

The chain

Each receipt names the one before it.

A receipt does not stand on its own. Before it is written, the hash of the preceding receipt is folded into it, so the receipts of one tenant form a single ordered chain.

That is what makes an edit show. Change a value in one receipt and its hash changes; the receipt after it still carries the old hash, and the two stop matching. Nothing here prevents a change; it makes a change visible to anyone who walks the chain.

Receipt RCP-899

Carries the hash of
0xc15f…df07
Its own hash
0xe48f…5a07

Receipt RCP-900

Carries the hash of
0xe48f…5a07
Its own hash
0xbfaf…0579

Receipt RCP-901

Carries the hash of
0xbfaf…0579
Its own hash
0xc5a5…4b00
Three receipts in sequence. Each one carries the hash of the receipt before it and produces a hash of its own, which the next receipt carries in turn.

If one changes

Every receipt after it stops matching, and the first mismatch names the position where the chain broke. Append-only is how we write. Detectable is what you can check.

Audit log

Append-only event chain. Any later edit or reordering is detectable by recomputing the chain against the commitment we kept.

Inclusion

Recompute the root yourself.

Receipts are gathered into batches, and a batch is reduced to a single root by hashing pairs until one value is left. The receipt carries its position in that batch and the sibling hashes on the way up. With those two, the root can be recomputed from the receipt alone.

  • Path from this receipt
  • Sibling hashes it uses
  • Other receipts in the batch

Four steps

  1. 1

    Hash the five core fields

    Take receipt_id, issued_at, input_hash, output_hash and previous_receipt_hash, write them in one fixed form (keys in alphabetical order, no whitespace) and take the SHA-256. That value is the leaf, and the receipt carries it as receipt_hash. It is not a hash over the whole receipt.

  2. 2

    Fold in the first sibling

    Decode the leaf and the first hash in merkle.path back to bytes, put the sibling on the side its side field names, join the two and take the SHA-256 of the pair.

  3. 3

    Walk up

    Repeat for each remaining entry in merkle.path, one level at a time, until a single value is left.

  4. 4

    Compare

    Set that value against merkle.root. Equal means this receipt matches the root the file itself carries. To mean that the receipt was in the batch at the time, that root has to be set against a commitment published outside our systems — and that publication is in development.

None of those four steps uses a key: the receipt and its path are enough. What they establish is that the receipt fits the root it carries. A fifth check — that root against a commitment published outside our systems — is in development.

From the illustrative sample

  • Field
    receipt_hash
    As published
    0xc5a5788a435ffee6…fe3a4b00
  • Field
    merkle.leaf_index
    As published
    2
  • Field
    merkle.path
    As published
    right · left · right
  • Field
    merkle.root
    As published
    0x6e00080f64cff7d5…07658346

Check by check

Seven checks, and they are not equally available.

Recomputing the Merkle path up to the root a receipt carries is not the same check as confirming that root was published outside our systems before a given moment. The first you can do today, in the worked example. The second nobody can, because the roots are not published yet. Each row below says what the check rests on and where it stands.

  • Check
    Recompute the input hash
    What it rests on
    SHA-256 over the input block of the receipt in your hand. Nothing else is needed.
    State
    Available
  • Check
    Recompute the output hash
    What it rests on
    SHA-256 over the output block of the same file.
    State
    Available
  • Check
    Recompute the link to the preceding receipt
    What it rests on
    SHA-256 over the five core fields of the receipt before it, which this receipt carries in full.
    State
    Available
  • Check
    Recompute the Merkle path to the root the receipt carries
    What it rests on
    Fold the leaf up through merkle.path and set it against merkle.root — the root printed in the same file, not one found elsewhere. The steps run on /sample-receipt.json today; production export works today.
    State
    Available in the worked example
  • Check
    Set that root against a commitment published outside our systems
    What it rests on
    Publication of the roots, and the open endpoint that serves them, is in development; the fourth check follows once they are published.
    State
    In development
  • Check
    Establish who issued the receipt using public cryptography alone
    What it rests on
    The receipt carries HMAC-SHA256 under a symmetric key issued per tenant. There is no freely available key to check it with, so there is nothing for a third party to check against.
    State
    Not available
  • Check
    Hold the issuer to it if they deny writing it
    What it rests on
    A message authentication code under a shared key provides no non-repudiation: whoever can check it can also produce it, and we hold the same key. It is not a signature.
    State
    Not provided by the current HMAC design

/receipt-explorer performs the first four of these on the worked example, in your browser. No public service checks a receipt on behalf of a third party today.

Check it yourself

Three values, recomputable by anyone.

Start on the left: three values anyone holding a receipt can recompute today, without a key and without us. A fourth, inclusion in the Merkle root, follows once we publish the roots. Beside it stands what the tenant key is for and what a receipt is a record of. So the first column can be taken literally instead of on trust.

Anyone can check

Three values, recomputable by anyone

The input hash, the output hash, the link to the receipt before it. Inclusion in the Merkle root is the fourth check, and it follows once we publish the roots; that publication and the open endpoint for it are in development.

No key, no account and no access to our database: the arithmetic runs on the receipt in your hand.

Key needed

What the tenant key is for

The code is HMAC-SHA256 over the canonical receipt, under a symmetric key issued per tenant. It is a message authentication code and not a public-key scheme; there is no freely available key to check it with.

Whoever can check the code can also produce it, and we hold the same key. It evidences that the record is intact, not who wrote it.

What it records

What a receipt is about, and what it is not

A receipt is a faithful record of what the system received, decided and sent. That is what it establishes, not whether the world matched it.

If a caller gave a wrong name, the receipt records the wrong name faithfully. Proof of process is not proof of fact, and no cryptography closes that gap.

Do it yourself

Take a receipt apart.

The explorer walks the worked example field by field, with the sample files next to it. None of it needs an account.

Evidence chain

Merkle publication in development

Three of those elements can be recomputed today by anyone holding the receipt: no key, no account, no access to our database.

Checking the authentication code uses the symmetric key we issue to your tenant.

Control what AI can cause. Prove what follows.

Where a receipt comes from

A receipt is what a governed call leaves behind.

Voice is the application it comes out of: telephony, the Article 50 disclosure and country policy in one place, with a receipt visible in the product for governed interactions. The receipt taken apart on this page carries the same fields and the same arithmetic.