Audit — ADR-009 Authorship Binding
Step 1 of the 5-step chain. This task is doc-only: a single ADR file plus the four chain artefacts. Source code is not changed.
Trigger
A whole-system code review surfaced Finding #2: the ζ Decision Trail’s SHA-256 chain proves what was recorded in what order but does not cryptographically bind who authored each record. The ADR documents the gap and recommends one of three paths.
Surface inventory (read-only)
Source-of-truth files (the gap lives here)
| File | Lines | Role |
|---|---|---|
src/domains/trail/schema.ts |
188 | THOUGHT_TYPES, ZERO_HASH, ThoughtRecordSchema, canonicalize, computeHash (lines 170–188 — the 6-field subset). The docstring at lines 153–159 explicitly excludes agent_id from the hash input. |
src/domains/trail/repository.ts |
401 | createThoughtRecord (lines 205–267) — stores agent_id in column 4 of the INSERT (line 247) but never feeds it into computeHash (lines 235–242). |
src/domains/trail/verifier.ts |
203 | verifyChain (lines 119–153) — recomputes computeHash(record) and compares to stored record.hash. Has no concept of agent_id. |
src/db/migrations/003_thought_records.sql |
43 | Defines thought_records table. agent_id is column 4 (line 33), declared TEXT NOT NULL. There is no signature column, no per-agent key material table. |
ADR artefacts to create / touch
| File | Status | Action |
|---|---|---|
docs/architecture/decisions/ADR-009-authorship-binding.md |
absent | Create as Status: Proposed, Date: 2026-05-06. |
docs/architecture/decisions/index.md |
exists, lists 6 ADRs | Append one row linking ADR-009. |
docs/architecture/decisions/README.md |
exists, lists ADR-001/002/003 in its index table | Do not touch — it’s already stale (lists 3 of 6 ADRs); reconciling it is out of scope. |
docs/audits/adr-009-authorship-binding-audit.md |
absent | This file. |
docs/contracts/adr-009-authorship-binding-contract.md |
absent | Step 2. |
docs/packets/adr-009-authorship-binding-packet.md |
absent | Step 3. |
docs/verification/adr-009-authorship-binding-verification.md |
absent | Step 5. |
Cross-references the ADR will cite
| Reference | Location | Why |
|---|---|---|
| Legitimacy promise | CLAUDE.md §10 |
“execution of work + management of intelligence + legitimacy of action” — frames why the gap is structural. |
| Executable-meaning contract | docs/architecture/decisions/ADR-006-executable-meaning.md |
The colibri_code field’s invariants. ADR-009 references it because authorship binding affects what “complete” means for ζ. |
| Multi-model defer | docs/architecture/decisions/ADR-005-multi-model-defer.md |
Context for “library-only stub vs. full feature” precedent — Option A’s migration uses the same staging logic. |
| Hash-input docstring | src/domains/trail/schema.ts:153-159 |
The deliberate exclusion of agent_id. |
computeHash signature |
src/domains/trail/schema.ts:170-188 |
The 6-field subset. |
| INSERT call | src/domains/trail/repository.ts:243-253 |
Where agent_id is written to the row. |
| Hash-recomputation in verifier | src/domains/trail/verifier.ts:131-132 |
Where the integrity check runs. |
| λ Reputation phase note | implicit in CLAUDE.md §10 |
Phase 2 will read agent_id as truth — Option C’s documented risk. |
Existing ADR format conventions (observed)
From the 6 existing ADRs:
- ADR-005 / ADR-006 use the cleanest modern format: frontmatter (title, description, tags, type, round, status, parent, updated, nav_order) + H1 heading + status block + horizontal rules between sections.
- Sections in canonical order: Context → Decision → Consequences → Implementation → Alternatives Considered → Verification → References.
- Some ADRs reorder Alternatives before Consequences (ADR-002, ADR-003) — both are accepted. This task’s prompt names the order “Decision → Alternatives Considered → Consequences → Implementation → Verification”, which I will follow.
- ADR-002 and ADR-003 are still PROPOSED; ADR-005 and ADR-006 are ACCEPTED. ADR-009 must ship as PROPOSED per the task’s explicit instruction.
- Frontmatter
nav_orderincrements by 10 (10/20/30/40/50/60). Next free slot for ADR-009 is 90.
Database state to consider
Two databases hold ζ chains today:
data/colibri.db— Phase 0 production target. Created at runtime; not committed. Contains real Phase 0 chains from R75 Wave G onward.data/ams.db— donor-era task store, retained per CLAUDE.md §1 through R78. Thethought_recordstable schema is the same migration. Contains chains older thancolibri.db.
The ADR’s Consequences §chain-validity table must address both.
Out of scope
Per the task prompt:
- No source code changes. Forbidden in this round.
- No migrations. Forbidden in this round.
- No test updates. Forbidden in this round.
- No edits to existing ADRs to mark superseded. Forbidden in this round (deferred to a follow-up if Option A or B is accepted).
- The
README.mdADR index table that already lists only ADR-001/002/003 is pre-existing drift. Reconciling it is its own hygiene task.
Test gate posture
Because this round produces zero source changes:
npm run build— must pass (no TS source change).npm run lint— must pass (no TS / no JS changed; markdown only).npm test— must pass (no test files touched).
The verification doc records the green-on-all-three result.
Risk assessment
- Risk: ADR mis-recommends. The legitimacy axis is small enough today that the wrong recommendation can be reversed in a follow-up ADR before λ Reputation lands. Mitigation: lay out all three honestly, recommend only when the cross-axis evidence is decisive.
- Risk: ADR undersells the gap. Finding #2 is real; an ADR that softens it would be worse than no ADR. Mitigation: the Context section names the practical attack (DB-level write, audit-sink replacement) explicitly.
- Risk: word-count blow-up. ADR-005 is ~750 words pre-postscript, ~1.4k with the Wave I postscript. ADR-006 is ~1.2k. ADR-009 should target the ADR-006 size band (1k–1.5k words excluding tables).