Proof
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…5092dcaeNo key needed- Output hash
0x97d47018e45e19e1…83c557d9No key needed- Previous receipt
0xbfafe10889982fd2…09fe0579No key needed- Merkle root
0x6e00080f64cff7d5…07658346In development- Authentication code
0xfd73071e00fa7837…415b54aaTenant 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
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
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
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
Walk up
Repeat for each remaining entry in merkle.path, one level at a time, until a single value is left.
- 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.
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.
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 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.
- Receipt explorer
Walk the worked example field by field.
- Sample receipt (JSON)
Fictional parties, real arithmetic: three values recompute from the file alone, and the fourth folds up to the Merkle root printed in the same file.
- Sample receipt (PDF)
The same record in a form a data protection officer can read.
- Evidence Vault API
How receipts are written and fetched.
- How to recompute it — the exact form
The canonical form, which block feeds which value, and four test vectors to tune against. No code of ours.
Evidence chain
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.
