Evidence receipt
An evidence receipt is a versioned proof bundle for one audit-log entry, raw material a verifier recomputes, never a verdict it's asked to trust. Caisson's kernel builds one per row from the entry's hash-chain link and its per-length WORM anchor behind the admin proof endpoint, classifying the row into one of six fail-closed verification states.
In code
export function buildRowReceipt(input: {
entry: AuditChainEntry;
anchorForRow: AuditChainAnchor;
redacted: boolean;
checks: VerifyLegs;
verifiedAt: string;
includeAnchorProvenance?: boolean;
}): RowReceipt {
const { entry, anchorForRow, redacted, checks, verifiedAt, includeAnchorProvenance } = input;
const anchor: {
length: number;
tipHash: string;
genesisHash?: string;
sig?: string;
keyId?: string;
} = { length: anchorForRow.length, tipHash: anchorForRow.tipHash };
if (includeAnchorProvenance === true) {
if (anchorForRow.genesisHash !== undefined) anchor.genesisHash = anchorForRow.genesisHash;
if (anchorForRow.sig !== undefined) anchor.sig = anchorForRow.sig;
if (anchorForRow.keyId !== undefined) anchor.keyId = anchorForRow.keyId;
}
return {
v: ROW_RECEIPT_VERSION,
seq: entry.seq,
hash: entry.hash,
prevHash: entry.prevHash,
anchor,
raw: { prevHash: entry.prevHash, payload: entry.payload },
redacted,
checks,
verifiedAt,
};
}How it holds
Raw material, not a verdict
The receipt's checks and verifiedAt fields are derived, untrusted display material, a standalone verifier ignores them and recomputes both legs itself from raw.prevHash and raw.payload, the only fields it actually trusts.
Six fail-closed states, never a false 'verified'
classifyRowState maps the recompute legs to one of verified, anchor-confirmed-original-not-disclosed, tampered, unverifiable, pending, or genesis; any leg that's inconclusive for a reason other than redaction resolves to unverifiable, never to verified.
Redaction is marked, not hidden
For a row with a secret-bearing payload, the admin proof endpoint masks the field server-side before the receipt is built, so raw.payload can never recompute the original hash, the receipt sets redacted: true and the row can only earn anchor-confirmed-original-not-disclosed, never verified.
Versioned so the shape can change safely
Every receipt carries v: ROW_RECEIPT_VERSION (currently 1), the schema version the kernel bumps on any change to the raw proof material's shape, so the proof-material layout a verifier reads is explicitly declared rather than assumed.