Open verification

Verify any Runback record.
Without Runback installed.

Every Runback audit export is a hash-chained JSON record signed by Runback's Ed25519 key. You can verify the chain right here — or with the open-source CLI — with no account, no SDK, and no dependency on Runback's servers. If the chain verifies, the record is exactly what the agent produced. If it doesn't, you'll see exactly which entry was altered.

This is what “tamper-evident” actually means: the proof is in the chain, not in trusting the vendor.

Try it now

Paste an export. Watch the chain verify. No signup.

The demo record below is a real audit export from the loan-approval incident on the proof page. Click Verify chainand watch each entry's hash check against the one before it — then see the Merkle root match the sealed checkpoint.

{
  "runback_export": "1.0",
  "run_id": "run_a3f1b90c",
  "agent": "loan-approval-agent",
  "captured_at": "2026-06-14T02:47:11Z",
  "entries": [
    {
      "seq": 0,
      "kind": "llm",
      "summary": "agent thinks · 612 tok · gpt-4o",
      "hash": "a3f1b90c",
      "prev": "genesis"
    },
    {
      "seq": 1,
      "kind": "tool",
      "summary": "check_credit_file · 218ms · ok",
      "hash": "e7c241af",
      "prev": "a3f1b90c"
    },
    {
      "seq": 2,
      "kind": "llm",
      "summary": "agent decides · 418 tok · finish=tool-call",
      "hash": "9d4412be",
      "prev": "e7c241af"
    },
    {
      "seq": 3,
      "kind": "tool",
      "summary": "issue_approval · ✗ policy gate blocked",
      "hash": "5b08ccd1",
      "prev": "9d4412be"
    }
  ],
  "checkpoint": {
    "head_hash": "5b08ccd1",
    "merkle_root": "3e68df98",
    "signed_by": "runback-v1",
    "signature": "ed25519:4f9cf97c5cfc7c5cfc4f9cf97c5cfc7c5cfc4f9cf97c5cfc7c5cfc4f9cf9…"
  }
}
The algorithm, open

Exact algorithm — the same one in @runback/verify

CASSETTE CHAIN
  entry_hash[0] = SHA256("" + canonical({kind, key, output}))
  entry_hash[n] = SHA256(entry_hash[n-1] + canonical({kind, key, output}))
  algorithm: oracle-chain/sha256

LEDGER CHAIN
  leaf[run]     = SHA256("leaf:" + canonical({run_id, name, status, digest, ended_at, steps}))
  entry[n]      = SHA256(entry[n-1] + leaf[n])
  node(a, b)    = SHA256("node:" + a + b)
  merkle_root   = balanced binary tree over leaves

CHECKPOINT SIGNATURE
  payload       = "ledger:{orgId}:{seq}:{head_hash}:{merkle_root}"
  signature     = HMAC-SHA256(AUDIT_SIGNING_KEY, payload)
  fail-closed   = key configured → signature required to pass verification
What this actually proves

Five things a log can't give you.

Nothing deleted

The ledger is append-only — enforced by pg_advisory_xact_lock per org. Remove any entry and the chain breaks at exactly that point. A gap in the sequence is detectable, not concealable.

Nothing altered

Change any field in any past entry — the decision text, a tool output, a timestamp — and its SHA-256 hash no longer matches what the next entry was sealed against. The failure cascades forward: every downstream hash is invalidated.

Dual-chain seal

The checkpoint HMAC-SHA256 covers both the event chain digest and the cassette digest: the record is re-executable. Possession of the signed checkpoint means the full runtime — every non-deterministic input — is accounted for.

Domain-separated Merkle

Leaf nodes are prefixed "leaf:", internal nodes "node:". Domain separation prevents second-preimage attacks — a leaf value cannot be confused with a node value at any tree depth.

Fail-closed

When a signing key is configured, a missing or invalid signature fails verification — it does not pass. DB write access alone cannot forge a valid checkpoint. The system defaults to rejection, not trust.

The open-source CLI

Run it locally. Source is public.

The same verification algorithm is available as a standalone CLI — install it anywhere, pipe in any export, get a machine-readable verdict. No Runback account. No network call.

Install
npm install -g @runback/verify
Verify a file
runback-verify audit-export.json
Verify from stdin
cat audit-export.json | runback-verify --stdin
Machine-readable output
{
  "schema": "runback.cassette/v1",
  "algorithm": "oracle-chain/sha256",
  "cassette_digest": "verified",
  "ledger_chain": "verified",
  "merkle_proof": "verified",
  "checkpoint_signature": "valid",
  "entry_count": 5,
  "entries_verified": 5
}

Source is published at github.com/letsRunback/runback-verify — the public key is embedded in the binary. The algorithm is the standard; anyone can implement it.

Why this matters for governance

A signed record an auditor can check themselves.

When a regulator or auditor asks for evidence of a past agent decision, “trust the vendor” isn't an answer. A Runback export is self-verifying: you hand the auditor the export and the CLI, and they check it themselves. The chain either verifies or it doesn't — no intermediary required. That's the difference between a log and a proof.

This is what EU AI Act Art. 12 logging and APRA CPS 230 incident management look like in practice — not a screenshot, but a record with verifiable integrity.

See how it maps to your compliance framework →

Start capturing records you can verify.

The free Community edition captures every agent run with a signed, verifiable audit record — self-hosted, in your own cloud, forever.