evidence.v1 · ed25519
The receipt, explained
Every governed change produces one signed receipt: evidence.v1. This page is the full detail: what it contains, why it is signed the way it is, and how anyone verifies it without trusting us.
The receipt, annotated
// evidence.v1, one governed merge
{
"schema": "evidence.v1",
"operationType": "code.merge",
"actor": { "agent": "claude-code", "session": "7f3a" },
"provenance": { "decision": "DEC-214", "pr": 477 },
"checks": { "typecheck": "pass", "test": "pass:142", "scope": "src/payments/*" },
"redaction": "none",
"sig": "ed25519:46367c53", "keyId": "sha256:", "ledger": "#9f2a"
}
Verify a receipt offline, with only the public key:
$ rootblocks verify receipt.json --key rootblocks.pub
✓ signature valid · ledger #9f2a · not tampered
Hand this file to anyone. They do not need us to verify it.
- operationType the governed event: a merge, a run, a release.
- actor.agent which agent produced the change, and its session.
- provenance.decision the human decision this change was authorized by. The anchor of the trace.
- checks gates and the enforced path scope, as they actually ran.
- redaction what was withheld from the receipt, declared, so absence is auditable too.
- sig / keyId / ledger ed25519 over canonical bytes, the signing key, the append-only position.
Why ed25519
Signatures are made over the canonical bytes of the receipt, so any change to any field breaks the signature. There is no room for a receipt that says one thing and proves another.
ed25519 is a modern, widely audited signature scheme: small keys, small signatures, deterministic signing, and no certificate authority required. Verification is a single public-key operation that runs anywhere, including air-gapped machines.
The private key is generated per install and never leaves the daemon host. Every receipt carries its keyId, so rotation and revocation are part of the evidence format, not an afterthought.
Why offline verification matters
An auditor, a customer, or a regulator should not have to trust RootBlocks to check your evidence. rootblocks verify takes a receipt and the public key, and answers with mathematics, not with our word.
That is the difference between a log and evidence. A log lives inside a system that can edit it. A receipt is signed into an append-only ledger and verifies anywhere, on any machine, with no account and no network.
A policy, in full
policy: payments-tier
scope:
allow: ["src/payments/**", "test/payments/**"]
deny: ["**/secrets/**", "infra/**"]
gates: [ typecheck, test, lint ] # all required
allowedTools: [ Edit, Read, "Bash(npm *)" ]
limits: { maxFiles: 40, maxRuntime: "20m" }
onGateFail: block # no commit, no receipt
Failure modes
Daemon down configurable per policy: fail-closed (agents cannot merge un-proven) or fail-open (run, mark observed, reconcile later).
Control plane down receipts are written locally first, into the append-only ledger, which is what runs today. Cloud sync (rolling out with design partners) resumes on reconnect.
Gate fails no commit, no receipt. The attempt itself is logged as evidence.
What leaves your infra
Leaves
Never leaves
content hashes
source code
ed25519 signatures
diffs
check metadata (pass/fail)
agent prompts
decision and PR IDs
file contents
Keys, and what the signature proves
Generated per install, on first run. The private key never leaves the daemon host.
Rotation every receipt carries its keyId, so rotation and revocation are built into the evidence format. The re-anchoring procedure ships with the enterprise program.
We prove that this execution, under this policy, was bound to this ratified human decision. We do not certify the agent internal reasoning, which is exactly why we anchor evidence in the human decision, not in the model narrative.
checks.* + provenance.decision maps to ISO 42001 Clause 8 (operational control) and SOC 2 CC8.1 (change management).