Verify the receipt yourself — offline, no live CodeRifts API call needed
An authorization proof, not a receipt#
A CodeRifts chain_receipt is a portable, verifiable proof that a specific contract-changing action was authorized, bound to a signed fingerprint of that decision, and checkable by anyone — another agent, CI, a merge gate, a deployment system — before the action runs.
The chain is simple: Intent → Authorize → Proof → Verify → Execute → Evidence
Inside a wired boundary: no verified receipt, no contract mutation. CodeRifts gates merge, deploy, publish, and schema registration wherever enforcement is installed and required.
Check a receipt in one command#
The open-source verifier fetches the public key from the published attestation endpoint (or uses a pinned key / key registry) and checks the Ed25519 signature over the receipt's own signed bytes. If it passes, the verdict provably came from the holder of the CodeRifts signing key.
Node (zero dependencies, Node ≥ 20)#
# Get a receipt (action-verdict needs no API key), then verify.
RECEIPT=$(curl -s -X POST https://app.coderifts.com/api/v1/action-verdict \
-H 'Content-Type: application/json' \
-d '{"action_type":"tool_call","provenance":{"channel":"ci_manifest","issuer_trust":"trusted"},"tool":{"name":"get_customer","capabilities":["read"]},"memory":{"op":"read","namespace":"working","staleness_hours":1}}' \
| node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>process.stdout.write(JSON.parse(s).chain_receipt))")
node verify.js "$RECEIPT"
# Offline (no network): pin a PEM, or resolve by kid from the key registry
node verify.js "$RECEIPT" --key pub.pem --kid 2026-07-k1
node verify.js "$RECEIPT" --keys https://app.coderifts.com/.well-known/coderifts-keys.jsonExit codes: 0 valid, 1 invalid, 2 usage error. Default key discovery URL: https://app.coderifts.com/api/v1/attestation/public-key.
What the proof guarantees#
- What it proves. The Ed25519 signature covers a frozen, pipe-delimited byte string: key id, verdict fingerprint (
fp), previous-link hash, caller, and issuance time. Envelope v2+ also signs an evidence-registry field; v3+ a Change-IR hash; v4 addsexpires_atand a decision body hash (bh). The verifier treatsfpas an opaque binding — it does not recompute the fingerprint from a verdict payload. Full decision-envelope rebind is available on v4 via--envelope. - Who can verify. Anyone with the public key (or the append-only key registry). No API key, no CodeRifts account. A successful signature check proves authenticity of the signed binding — it is not, by itself, a gate saying "execute this action now"; merge, deploy, and runtime gates still compose the receipt with operation match, fingerprint match, and allow-class
execution_action. - What it's bound to. Every envelope version binds the opaque verdict fingerprint
fpinside the signed bytes. v4 also binds the RFC 8785-canonical decision envelope viabh(re-checkable with--envelope; mismatch →body_hash_mismatch). A proof for one signed fingerprint does not authorize a different change. - How long it is valid. On v4 envelopes, expiry is signed into the proof as
expires_at; authentic but past expiry returnsVERIFIED_EXPIRED(not a green pass). v1–v3 do not carry a signed expiry field — freshness is judged by the gate that consumes the receipt. - How it is invalidated. Key rotation is append-only: retired keys stay in
/.well-known/coderifts-keys.json. A receipt signed while a key was live remains trustworthy after retirement (RETIRED_KEY_VALID_AT_ISSUE); a receipt timed at or afterretired_atis rejected. If the key registry cannot be reached when discovery is required, the status isREGISTRY_UNREACHABLE(fail closed on discovery, not a silent pass). - Replay-resistant binding. The signature covers the exact reconstructed signed bytes. Altering any signed field invalidates the signature. Chain mode additionally requires each non-genesis
prevto equalsha256:of the previous token string.
Honest limit: a valid signature is authenticity of the signed binding, not a complete authorization decision. CodeRifts states this explicitly — the independent verifier is designed to prove only what the frozen format actually signs.
A frozen, public contract#
The byte format is frozen. For a given envelope version the field order and separators of the signed byte-string never change. New fields are only ever appended under a new envelope version. The chain lives in the request/response; nothing is stored server-side for independent verification.
- Format spec:
RECEIPT_FORMAT.mdingithub.com/coderifts/receipt-verifier(public, frozen) - Reference verifier:
github.com/coderifts/receipt-verifier(Node + Python) - Discovery:
/.well-known/coderifts.json→portable_verification - Live keys:
/.well-known/coderifts-keys.jsonand/api/v1/attestation/public-key
Why portable proof matters for AI agents#
When an agent changes a contract, "it said it checked" is not evidence. A portable proof is — it binds authorization material to a signed fingerprint of the exact change, survives handoff between agents and systems, and is verifiable independently before execution.
That is the difference between a tool that reports and a layer that authorizes.