Problem
The content-addressed decision record is persisted but never published. A contributor is shown a
12-character prefix of a SHA-256 over a document they cannot obtain, cannot recompute, and cannot dispute.
grep -rln "decision_records" src/ returns exactly three files — decision-record.ts,
risk-control-wire.ts, salvageability-wire.ts. No API route, no MCP tool, and no export path ever
returns record_json. The only published artifact is renderDecisionRecordSection
(src/review/decision-record.ts:148-159), which truncates everything it shows:
149: const short = (digest: string): string => digest.slice(0, 12);
156: `- **record**: \`${short(recordDigest)}\` (schema v${record.schemaVersion}, head \`${record.headSha.slice(0, 7)}\`)`
and omits decidedAt, baseSha, salvageability, repoFullName, and pullNumber entirely.
The module's own stated purpose (:6-9) is that "'the bot closed me' becomes 'clause X of ruleset
abc123 closed me' — inspectable, arguable, and stable under challenge." The human-readable clause is
delivered. The cryptographic half is decorative: there is nothing to fetch, nothing to recompute, and
therefore nothing to argue with.
Compounding — the preimage is destroyed on re-gate. persistDecisionRecord upserts:
121: ON CONFLICT(id) DO UPDATE SET action = excluded.action, ..., record_json = excluded.record_json
id is keyed on head SHA, so a re-gate at the same head (sweep re-gate, CI-completion re-review)
overwrites the earlier record body while appendDecisionLedger appends a second chain row for the old
digest. The comment claims supersessions are "visible history, not silent replacement" — but only the
digest survives; the superseded content is gone. Measured on the live instance (edge-nl-01,
2026-07-26): 51 of 184 chain rows already reference a digest that no longer matches the current record
body. Those 51 are permanently unreconcilable against any content — a correct fix for #9078 would be
structurally unable to check them.
Trigger
A contributor is auto-closed, reads **record**: a1b2c3d4e5f6 in the panel, and asks to see the record
behind that digest. There is no endpoint. If the PR was re-gated at the same SHA, the row no longer holds
what was decided the first time.
Impact
The SLSA-VSA framing (verifier + policy digest + result) collapses to an unverifiable string. An external
evaluator checking "every verdict is published with a record" finds that the record is not published at
all. This is the accountability claim the product is named around.
Requirements
Test Coverage Requirements
99%+ patch coverage, branch-counted. Route test asserting an anonymous fetch succeeds and that the
returned body hashes to the published digest; regression test proving a re-gate at the same head no
longer destroys the prior record.
Links & Resources
Boundaries
Publication + supersession semantics. No change to what goes into the record (sibling issue) and no
change to the chain algorithm.
maintainer-only — public trust-surface authority.
Problem
The content-addressed decision record is persisted but never published. A contributor is shown a
12-character prefix of a SHA-256 over a document they cannot obtain, cannot recompute, and cannot dispute.
grep -rln "decision_records" src/returns exactly three files —decision-record.ts,risk-control-wire.ts,salvageability-wire.ts. No API route, no MCP tool, and no export path everreturns
record_json. The only published artifact isrenderDecisionRecordSection(
src/review/decision-record.ts:148-159), which truncates everything it shows:and omits
decidedAt,baseSha,salvageability,repoFullName, andpullNumberentirely.The module's own stated purpose (
:6-9) is that "'the bot closed me' becomes 'clause X of rulesetabc123 closed me' — inspectable, arguable, and stable under challenge." The human-readable clause is
delivered. The cryptographic half is decorative: there is nothing to fetch, nothing to recompute, and
therefore nothing to argue with.
Compounding — the preimage is destroyed on re-gate.
persistDecisionRecordupserts:idis keyed on head SHA, so a re-gate at the same head (sweep re-gate, CI-completion re-review)overwrites the earlier record body while
appendDecisionLedgerappends a second chain row for the olddigest. The comment claims supersessions are "visible history, not silent replacement" — but only the
digest survives; the superseded content is gone. Measured on the live instance (
edge-nl-01,2026-07-26): 51 of 184 chain rows already reference a digest that no longer matches the current record
body. Those 51 are permanently unreconcilable against any content — a correct fix for #9078 would be
structurally unable to check them.
Trigger
A contributor is auto-closed, reads
**record**: a1b2c3d4e5f6in the panel, and asks to see the recordbehind that digest. There is no endpoint. If the PR was re-gated at the same SHA, the row no longer holds
what was decided the first time.
Impact
The SLSA-VSA framing (verifier + policy digest + result) collapses to an unverifiable string. An external
evaluator checking "every verdict is published with a record" finds that the record is not published at
all. This is the accountability claim the product is named around.
Requirements
GET /v1/public/decision-records/:owner/:repo/:pullreturningrecord_jsonverbatim plusrecord_digest, so the published digest is checkable. TheDecisionRecordtype is already declaredpublic-safe; confirm that against its current fields (including
salvageability) before exposing.Add it to the
requiresApiTokenexemption list — see orb(trust): the 'public' decision-ledger verify endpoint requires an API token — 401 in prod, so the chain is verifiable by nobody #9120 for the failure mode when that step ismissed.
commitment.
idrather than an UPDATE, so everychained digest retains its preimage. (orb(integrity): the decision-ledger verify endpoint never reconciles record_json against record_digest — the check its own comment promises does not exist #9078 requests the same change from the integrity side; whichever
lands first should satisfy both.)
implying full history.
Test Coverage Requirements
99%+ patch coverage, branch-counted. Route test asserting an anonymous fetch succeeds and that the
returned body hashes to the published digest; regression test proving a re-gate at the same head no
longer destroys the prior record.
Links & Resources
src/review/decision-record.ts~116-159;src/queue/processors.ts~11782 (the only surface)orb(trust): the 'public' decision-ledger verify endpoint requires an API token — 401 in prod, so the chain is verifiable by nobody #9120 (public-route exemption), orb(trust): the decision ledger has no external anchor and verify returns no hash — wholesale re-chaining and tail truncation both pass clean #9122 (anchoring)
Boundaries
Publication + supersession semantics. No change to what goes into the record (sibling issue) and no
change to the chain algorithm.
maintainer-only — public trust-surface authority.