An audit log that cannot be recomputed is a story. Klevar Docs needed proof.
Every issued document already has storage metadata, a document row, and an event trail. That is useful, but it does not prove that the sequence was not edited later. The hash chain adds a stricter property: every finalized document links to the previous chain entry for the same entity.
The chain is per entity. FZE documents do not link into LLC documents. Nigerian Ltd documents do not share sequence with FZE. That separation matches the legal boundary and keeps verification narrow.
Insertion happens inside the document transaction. The chain row records the document hash, previous hash, chain index, entity id, and derived link hash. If a previous row changes later, verification can recalculate the break.
The verifier is intentionally independent:
for (const entry of entries) {
if (entry.previous_hash !== previousHash) {
breaks.push({
chainIndex: entry.chain_index,
reason: "previous_hash_mismatch",
});
}
const expected = computeChainLinkHash({
entityId: entry.entity_id,
documentId: entry.document_id,
documentHash: entry.document_hash,
previousHash: entry.previous_hash,
chainIndex: entry.chain_index,
});
if (entry.chain_link_hash !== expected) {
breaks.push({
chainIndex: entry.chain_index,
reason: "chain_link_hash_mismatch",
});
}
previousHash = entry.chain_link_hash;
}
That loop is the point. The database stores the claim. The verifier recomputes it.
The project also includes anchoring. Chain heads can be anchored through timestamp authority flow and published externally through GitHub anchor artifacts. The local chain proves internal continuity. The external anchor makes silent retroactive edits harder to hide.
The CLI closes the operator loop. An operator can run hash-chain verification without writing SQL or reading service internals. During validation, Brain runs exercised hash-chain commands and verified multiple paths. That matters because audit tools that only developers can run tend to become rituals instead of controls.
There is a deeper design choice here: the chain uses document content and ordering, not just events. Events say something happened. The document hash says what was locked. The previous hash says where it sat in the entity sequence.
That means the proof survives ordinary operational noise. Notifications can retry. Webhooks can fail and replay. Reports can be regenerated. The chain remains the narrow artifact that says: this entity finalized this document in this order with this content.
For a compliance document substrate, that is the difference between an audit trail and an audit claim.