Infyrence

What a hash chain actually proves

Audit logs are easy to oversell. A hash chain is a real integrity property, and it is also narrower than the marketing around it usually implies. Being precise about the narrow version is what makes the strong version credible.

The mechanism

Each entry commits to the one before it: the record's hash covers its own fields plus the previous entry's hash. Verification walks the chain from genesis and recomputes every hash.

Edit a past decision from deny to allow and that entry's hash changes. The next entry still carries the old previous-hash, so the link breaks and verification fails. The same applies to deleting an entry or reordering two of them.

This is an integrity guarantee that database permissions cannot give you. Permissions control who may edit. A chain makes an edit detectable regardless of who made it or what authority they had.

The honest limitation

An unkeyed chain is self-anchored. Everything needed to recompute it is in the process that writes it.

So an attacker who controls that process does not need to break SHA-256. They edit the entry they care about, recompute every hash from there to the head, and the chain verifies perfectly. What an unkeyed chain detects is accidental corruption, a partial write, a well-meaning cleanup script, and casual tampering by someone who didn't think about it. That is genuinely useful. It is not protection against a determined insider, and claiming otherwise would be the kind of thing that falls apart in the one conversation where it matters.

What closes the gap

Pass a key, and the chain becomes HMAC-SHA256. Now recomputation requires the key, so forging the record requires stealing it.

The whole value of that rests on one condition: the key must live outside the agent process. A key in the same memory as the thing it constrains proves nothing — it is one os.environ read away from the attacker who already has the process. Put it in a KMS, a secrets manager, or hand it to the auditor. Whoever holds the key is who the record is credible to.

The remaining hardening is anchoring the head hash externally — a notary or a WORM sink — so that even the key holder cannot rewrite history silently. That is deferred in the open library, and it is what a durable managed sink is actually for.

Record first, then ship

One detail that matters more than it looks. When a run is connected to a control plane, the local record is written first, then shipped.

Two reasons. An offline run and a connected run produce an identical chain, so connecting doesn't change your evidence — it only makes a copy durable somewhere you don't control. And the network path cannot suppress a local record: if shipping fails, the local chain is already complete. A sink must never break the agent, and it must never be able to quietly erase the thing it was supposed to preserve.

Why we write this down

SOC 2 (CC6/CC7/CC8) and EU AI Act Article 12 both want evidence that actions were controlled and that the record of them is trustworthy. An auditor's first question about any log is what stops you editing this. "It's hash-chained" is a good answer only if you can also say precisely what that does and does not cover — and who holds the key.