TECHNICAL NOTE: WHAT A DECISION LEDGER HAS TO REFUSE
A short note for technical reviewers, written because the question is fair and the answer is checkable.
THE QUESTION
Enterprise platforms describe audit trails, decision intelligence and immutable records. Most of them mean a database table with a timestamp column. From the outside those two things look identical, and a reviewer has no way to tell them apart from a product page.
So here is the code.
WHAT ENTERS THE LEDGER, AND WHAT DOES NOT
A decision is rejected before it is written unless it carries all of the following. This is the validator, unedited:
if (!d.decidedBy) errs.push('decidedBy is required: an anonymous decision is not a decision');
if (!d.rationale || String(d.rationale).trim().length < 10) {
errs.push('rationale is required and must be substantive: "approved" is not a rationale');
}
if (!Array.isArray(d.alternativesConsidered) || d.alternativesConsidered.length === 0) {
errs.push(
'alternativesConsidered is required and must be non-empty. This is the field an auditor ' +
'asks for and the field every vendor omits. A decision with no alternatives recorded is ' +
'an acceptance, and it should say so explicitly: [{ option: "do nothing", why_not: "..." }]'
);
} else {
d.alternativesConsidered.forEach((a, i) => {
if (!a.option) errs.push(`alternativesConsidered[${i}].option is required`);
if (!a.whyNot) errs.push(`alternativesConsidered[${i}].whyNot is required: an alternative with no reason for rejection is decoration`);
});
}
if (!d.findingSnapshot || typeof d.findingSnapshot !== 'object') {
errs.push('findingSnapshot is required: the ledger freezes what the screen said, it does not point at a mutable row');
}
Three of those refusals are the whole design.
The rationale must be substantive. The literal string "approved" is rejected. A ledger that accepts it produces an audit trail that cannot be defended, which is worse than no audit trail because it carries the appearance of rigour.
Alternatives are required, each with a reason for rejection. This is the field that separates a decision from an acceptance. It is what an auditor asks for two years later, and it is the only evidence that a choice was made rather than a default accepted. If nothing else was considered, the record must say so explicitly, as an alternative called "do nothing" with a reason.
The finding is frozen, not referenced. The entry stores a copy of what the finding said at the moment a person decided, not a pointer to a row that keeps changing. A decision record that mutates when its underlying data mutates is not a record. It is a view, and it is worthless in an audit.
VERIFYING THE CHAIN WITHOUT TRUSTING THE VENDOR
Each entry commits to the previous one. This is what a customer runs, unedited:
async verify(tid) {
const entries = await store.listDecisions(tid, { limit: 100000, order: 'asc' });
let prevHash = GENESIS;
for (let i = 0; i < entries.length; i++) {
const e = entries[i];
if (e.seq !== i) {
return { ok: false, brokenAt: i, reason: `sequence gap: expected ${i}, found ${e.seq}` };
}
if (e.prevHash !== prevHash) {
return { ok: false, brokenAt: i, reason: 'prevHash does not match the previous entry' };
}
const recomputed = chainHash(prevHash, e);
if (recomputed !== e.chainHash) {
return { ok: false, brokenAt: i, reason: 'entry content does not match its hash: this entry was altered after it was written' };
}
prevHash = e.chainHash;
}
return { ok: true, entries: entries.length, head: prevHash };
}
Every input to that function is in the export the customer holds. It names the index where the chain broke and why, rather than returning a boolean, because "invalid" tells an operator nothing about whether to investigate a key rotation or a rewrite.
WHAT THIS DOES NOT DO, WHICH IS THE PART WORTH READING
A hash chain does not make history immutable. It makes an entry altered in place detectable. An operator with write access who alters an entry and recomputes every subsequent hash produces a chain that verifies cleanly, because nothing binds an entry to the identity that wrote it and nothing outside the store remembers what the head used to be.
Two mechanisms close that, and both are shipped:
Signing. Each chain head is signed with an Ed25519 key, and the customer may countersign. A rewrite then requires both keys, and the vendor cannot produce one alone.
Anchoring. Entries and their hashes are streamed to the customer's own audit collector, and the forwarder refuses to send across a discontinuity rather than papering over it. A customer holding a prior head can compare, and the comparison returns DIVERGED with the sequence number where the history changed.
So the accurate sentence, and the one that ships:
Decision history is hash-chained, each head is signed, and heads are streamed to the customer's own audit infrastructure. A rewrite is detectable by comparison against any head the customer already retained.
Not "immutable." Signing makes a rewrite detectable, not impossible. Those are different claims and only the second one survives a security review.
WHY WRITE THIS DOWN AT ALL
Because the difference between a decision ledger and a logging table is entirely in what each one refuses, and refusals are invisible from the outside. A reviewer can read a feature list for an hour and learn nothing about whether "approved" is an acceptable rationale.
The same discipline runs elsewhere in the platform, and it is worth naming two more:
- The outcome record refuses a measured value attached to a pending verdict, on the grounds that
value is measured at settlement rather than predicted at recording.
- Evidence packs that re-derive against live data cannot support a commercial measurement. Only
a pack pinned at the moment of the finding is eligible, and that is enforced in code rather than in a policy nobody reads at invoice time.
A system that refuses in the right direction was built by someone who had thought about the failure mode. That is the only thing this note is trying to demonstrate, and the code above is the whole argument.
EOS, delivered under the AssetShop brand by Web3 Ventures Enterprise. Read-only toward every system of record.