Skip to main content
A customer asks whether your agent really approved that refund, and “trust our logs” is a weak answer. Giving them database access is worse. A signed checkpoint and a receipt let them check one decision themselves, offline, with a public key. This tutorial signs a checkpoint of an audit log, mints a receipt that reveals four fields and hides the rest, verifies it the way a counterparty would, and then proves a later checkpoint extends the first. It runs in memory with no model and no API key. Terminal output of the audit receipts example verifying a receipt and a consistency proof

Prerequisites

  • Node 20 or newer and TypeScript
  • A scratch project with "type": "module" in package.json
The code below is from the audit receipts example. Put it in one index.ts. It needs a release that includes the checkpoint exports.

Step 1: Turn on a tamper evident audit log

The hmacKey here is for the demo. Use a real secret in production.

Step 2: Record three decisions

In a real deployment the engine writes these rows for you. The helper is here so the demo is self contained.

Step 3: Sign a checkpoint and mint a receipt

You, the operator, generate a key pair, sign the head of the log, and cut a receipt for decision-2 that reveals only the action, resource, result and timestamp.
Keep the private key in your secret store and publish keys.publicKey.

Step 4: Verify as the counterparty

This is all the other side needs: the receipt JSON and your public key.

Step 5: Prove the log only grew

Later the log gets a fourth row. A consistency proof shows the new checkpoint extends the old one without changing any earlier row.
Run it with npx tsx index.ts.

What the output means

Real output from the example. Your root hash and receipt size will differ, because the rows carry timestamps from your run.
Size 3 is the three recorded decisions. The receipt is about 2 KB of JSON, and the order ID and amount stay hidden as commitments. receipt verifies: true means the operator’s key signed a log head that contains that row with those revealed values. The last line means no earlier row was altered between the two checkpoints.

Limits

A receipt proves less than it might seem to.
  • It does not prove the log is complete. A row never written, or left out of a checkpoint, is invisible.
  • It does not prove you showed everyone the same log. Catching a split view needs checkpoints published where several parties read them, and someone comparing.
  • A hidden field is a commitment. To prove it, reveal it with its salt.
  • It proves the record, not that the decision was right.
  • The timestamp is the signer’s clock, not an independent time stamp.

Where to go next

Last modified on October 16, 2026