A record that can't be quietly edited.

Every decision the policy engine makes — not just the payments that succeeded — becomes a durable, append-only entry. Each one records a hash of the entry before it, so altering or removing anything in the past breaks every hash that follows it.

What a receipt holds

decision
allow, requiresApproval, or deny — the exact outcome the policy engine returned.
reason
Present on a deny. One of a fixed set of codes — see /policy — never free text.
amount, token, payee
What was requested, exactly as the agent submitted it.
signature
The on-chain transaction signature, once one exists — absent for anything denied or still held.
prevHash
A hash of the receipt immediately before this one, linking it into the chain.

If a payment happened, there's a receipt. If it didn't, there's a reason.

Why hash-chaining, not just a database row

A plain row can be edited in place with nothing left to show it happened. Chaining each entry to the one before it means an edit, a deletion, or a reordering anywhere in the history is visible — every hash computed after that point stops matching. Tamper-evidence here comes from the structure itself, not from trusting whoever has database access.

Every outcome, not just the wins

A deny is recorded exactly like an allow — same durability, same position in the chain. That matters for the same reason the reason codes matter: the point of this system is to show what the policy refused and why, not just what it paid.