The Receipt Chain

Every word AI writes. On the record.

A tamper-evident receipt for every AI action. Verifiable by anyone.

The check that was missing.

AI is being used in hospitals to write directly into medical charts.

Until now, no one was checking what it wrote.

When the AI gets something wrong, the clinician’s name is on the chart. Not the AI company’s. Not the EHR vendor’s. The person at the bedside.

is the check. Every time an AI tries to put something in a chart, we look at it first. If it’s wrong, we stop it. If it’s fine, we let it through. Either way, we write down what happened. And that record can’t be changed or deleted.

The rest of this page shows how.

What every receipt holds

Three commitments, one record.

Every C_Verified receipt is a single signed object that binds an AI's input, the policy decision, and the canonical content forwarded to the EHR, in a way anyone with the public key can verify and no one can quietly alter.

Bound to both bytes.

The hash of what the AI tried to write and the hash of what was actually forwarded to the chart are both inside the signed receipt. You can prove what was caught, not just what was sent.

Linked to its past.

Each receipt carries the hash of the receipt before it. The chain is per-tenant, monotonic, and tamper-evident. A deleted receipt breaks the chain visibly.

Signed by the tenant key.

Ed25519. The hospital's policy decision, signed by the hospital's key, on the hospital's own audit chain. The public key is enough to verify; the private key never leaves the boundary.

For technical reviewers: show the code
Rust · The signer

One receipt, signed at the boundary.

When an AI agent attempts to write to the record, the policy engine emits a receipt and signs it before any byte reaches the EHR. This is the minimal version of that move.

sign_receipt.rs Rust
// Minimal demonstration of the C_Verified receipt-signing pattern. // Real production code adds: HSM-backed keys, RFC 3161 anchoring, // per-tenant chain isolation, and FIPS 140-3 cryptography. use ed25519_dalek::{Signer, SigningKey, Signature}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use chrono::Utc; #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Receipt { pub tenant_id: String, pub request_id: String, pub agent_id: String, pub decision: String, // ALLOW_LOG | ALLOW_ALERT | HOLD_REVIEW | DENY_LOG | DENY_REPORT pub original_hash: String, // SHA-256 of raw bytes from the AI pub sanitized_hash: String, // SHA-256 of canonical content forwarded to EHR pub prev_receipt_hash:String, // SHA-256 of the previous receipt in this chain pub monotonic_seq: u64, pub timestamp_utc: String, pub key_id: String, pub signature: Option<String>, } impl Receipt { fn canonical_bytes(&self) -> Vec<u8> { // Signature is computed over every field except `signature` itself. let mut clone = self.clone(); clone.signature = None; serde_json::to_vec(&clone).unwrap() } pub fn sign(mut self, key: &SigningKey) -> Receipt { let sig: Signature = key.sign(&self.canonical_bytes()); self.signature = Some(hex::encode(sig.to_bytes())); self } } fn hash_hex(bytes: &[u8]) -> String { hex::encode(Sha256::digest(bytes)) } fn main() { let key = SigningKey::generate(&mut rand::rngs::OsRng); let original = b"AI proposes: amoxicillin 500mg PO TID for 7d"; let sanitized = b"amoxicillin 500mg PO TID x 7d"; let receipt = Receipt { tenant_id: "demo-hospital".into(), request_id: "req-7f3a".into(), agent_id: "scribe-1.0".into(), decision: "HOLD_REVIEW".into(), original_hash: hash_hex(original), sanitized_hash: hash_hex(sanitized), prev_receipt_hash: "0".repeat(64), // genesis receipt monotonic_seq: 1, timestamp_utc: Utc::now().to_rfc3339(), key_id: "tenant-key-2026-05".into(), signature: None, }.sign(&key); println!("{}", serde_json::to_string_pretty(&receipt).unwrap()); }
1.
The signature covers every field except the signature itself. That's the discipline. Once written, the receipt cannot be edited (not the decision, not the hashes, not the sequence number) without invalidating the signature. The hospital’s key signs the hospital’s policy decision on the hospital’s chain.
Python · The verifier

Anyone with the public key can prove it.

A regulator, an auditor, a compliance officer, a malpractice insurer’s expert: anyone holding the tenant’s public key can verify a receipt and check its position in the chain. No special tooling. Standard Ed25519, standard SHA-256.

verify_receipt.py Python
"""Verify a C_Verified receipt and one step of its chain. Run: python verify_receipt.py receipt.json prev_receipt.json public_key.hex Real production verification additionally checks: - the RFC 3161 timestamp authority anchor - the IGS countersignature subchain - kill-switch state and time-integrity at the moment of decision """ import json, hashlib, sys from nacl.signing import VerifyKey from nacl.exceptions import BadSignatureError def canonical_bytes(receipt: dict) -> bytes: """Reproduce the exact bytes the Rust signer hashed.""" clone = {k: v for k, v in receipt.items() if k != "signature"} return json.dumps(clone, separators=(",", ":"), sort_keys=False).encode() def verify_signature(receipt: dict, public_key_hex: str) -> bool: vk = VerifyKey(bytes.fromhex(public_key_hex)) sig = bytes.fromhex(receipt["signature"]) try: vk.verify(canonical_bytes(receipt), sig) return True except BadSignatureError: return False def receipt_hash(receipt: dict) -> str: return hashlib.sha256(canonical_bytes(receipt)).hexdigest() def verify_chain_link(current: dict, previous: dict) -> bool: """Current.prev_receipt_hash must equal hash(previous).""" return current["prev_receipt_hash"] == receipt_hash(previous) if __name__ == "__main__": receipt = json.load(open(sys.argv[1])) prev = json.load(open(sys.argv[2])) pubkey = open(sys.argv[3]).read().strip() sig_ok = verify_signature(receipt, pubkey) chain_ok = verify_chain_link(receipt, prev) print(f"signature: {'VALID' if sig_ok else 'INVALID'}") print(f"chain: {'INTACT' if chain_ok else 'BROKEN'}") print(f"decision: {receipt['decision']}") sys.exit(0 if (sig_ok and chain_ok) else 1)
2.
Two truths in one pass. Signature valid means the receipt has not been altered since the boundary signed it. Chain intact means the receipt sits exactly where it was placed in the per-tenant log, with nothing removed before it. A failure of either means the audit record cannot be trusted, and the verifier’s exit code says so.
JSON Schema · The contract

The receipt format, declared once.

JSON Schema 2020-12. Every receipt that crosses any C_Verified boundary (in test, in production, in audit export, in a regulator’s portal) validates against this exact contract.

receipt.schema.json JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://openc.health/schemas/receipt.schema.json", "title": "C_Verified Receipt", "description": "A tamper-evident record of one AI record-write decision at the AI-to-EHR boundary.", "type": "object", "required": [ "tenant_id", "request_id", "agent_id", "decision", "original_hash", "sanitized_hash", "prev_receipt_hash", "monotonic_seq", "timestamp_utc", "key_id", "signature" ], "properties": { "tenant_id": { "type": "string", "description": "The covered entity under whose adopted AI Governance Policy this record write was evaluated." }, "request_id": { "type": "string", "description": "Stable identifier for this single record-write request." }, "agent_id": { "type": "string", "description": "The AI agent attempting the record write. Externally attested per request, not cached." }, "decision": { "type": "string", "enum": ["ALLOW_LOG", "ALLOW_ALERT", "HOLD_REVIEW", "DENY_LOG", "DENY_REPORT"], "description": "One of the 5-tier decisions specified in the C_Verified policy engine." }, "original_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "SHA-256 of the raw bytes the AI agent attempted to write." }, "sanitized_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "SHA-256 of the canonical content produced by the multimodal CDR pipeline. Only this canonical form is forwarded to the EHR." }, "prev_receipt_hash": { "type": "string", "pattern": "^[0-9a-f]{64}$", "description": "SHA-256 of the previous receipt in this tenant’s chain. Genesis receipt uses 64 zeros." }, "monotonic_seq": { "type": "integer", "minimum": 0, "description": "Per-tenant monotonically increasing sequence number. Halts on regression." }, "timestamp_utc": { "type": "string", "format": "date-time", "description": "ISO 8601 timestamp from authenticated NTP. Halts on time-integrity failure." }, "key_id": { "type": "string", "description": "Identifier of the tenant signing key used. Rotated per tenant policy." }, "signature": { "type": "string", "pattern": "^[0-9a-f]{128}$", "description": "Ed25519 signature over the canonical receipt bytes (all fields except ‘signature’ itself)." } } }
3.
Every field is named, typed, and described. A regulator with no prior context can read the schema and understand what each receipt holds; an integrator can validate every incoming receipt before trusting it. The schema is the contract between the boundary and everyone who will ever look at the audit trail.

The chain is the boundary.

If you build clinical AI, or integrate it, or audit it, or insure it: the receipt chain is the thing you ask for. Talk to us.

Email the founder