Overview

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.json

Exit 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#

  1. 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 adds expires_at and a decision body hash (bh). The verifier treats fp as an opaque binding — it does not recompute the fingerprint from a verdict payload. Full decision-envelope rebind is available on v4 via --envelope.
  2. 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.
  3. What it's bound to. Every envelope version binds the opaque verdict fingerprint fp inside the signed bytes. v4 also binds the RFC 8785-canonical decision envelope via bh (re-checkable with --envelope; mismatch → body_hash_mismatch). A proof for one signed fingerprint does not authorize a different change.
  4. How long it is valid. On v4 envelopes, expiry is signed into the proof as expires_at; authentic but past expiry returns VERIFIED_EXPIRED (not a green pass). v1–v3 do not carry a signed expiry field — freshness is judged by the gate that consumes the receipt.
  5. 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 after retired_at is rejected. If the key registry cannot be reached when discovery is required, the status is REGISTRY_UNREACHABLE (fail closed on discovery, not a silent pass).
  6. 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 prev to equal sha256: 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.md in github.com/coderifts/receipt-verifier (public, frozen)
  • Reference verifier: github.com/coderifts/receipt-verifier (Node + Python)
  • Discovery: /.well-known/coderifts.jsonportable_verification
  • Live keys: /.well-known/coderifts-keys.json and /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.

Updated

Was this page helpful?