Packet — ADR-009 Authorship Binding
Step 3 of the 5-step chain. This packet is the gate to implementation: it records the writing plan for the ADR file itself. The ADR is a deliverable artefact, not a code change, so this packet specifies the writing plan rather than a code-edit plan.
Plan summary
Write docs/architecture/decisions/ADR-009-authorship-binding.md from scratch, then add one bullet to docs/architecture/decisions/index.md. Every other artefact in the 5-step chain (audit, contract, verification) is its own commit.
Recommendation choice — committed in this packet
Recommend Option A — include agent_id in the hash (breaking change).
Rationale:
- Cost is bounded and one-shot. Option A is a 1-line change to
computeHashplus a migration script that walks the table once. The schema migration counter advances by one (007_authorship_binding.sql). The total LOC impact is small. - Migration is feasible because the chain is small. At round R83 close, the largest task chain in
data/colibri.dbis in the low hundreds of records.data/ams.dbis heritage; its chain is frozen and can be archived rather than migrated. - Authorship correction has a sound replacement pattern. Per ADR-006 §”Demotion rules” and the canonical
thought_type="decision"slot, correction-by-append (insert a new record stating “Record X was authored by Y, not Z”) is the existing pattern. Edit-in-place is already disallowed by the chain. - Option B (HMAC signing) defers a key-management decision Phase 0 cannot make. Per CLAUDE.md and ADR-005 the runtime is single-host single-process; per-agent key material has no delivery story until Phase 1.5+ multi-model. Option B could land later, layered on Option A’s binding.
- Option C (document the gap) violates the legitimacy promise. CLAUDE.md §10 names legitimacy as one of three axes. Phase 2 λ Reputation will read
agent_idas truth. Documenting the gap as acceptable hard-codes a Phase 2 redesign cost.
This recommendation is locked in this packet so the ADR’s §Decision and §Alternatives align without contradiction. Step 4 must not silently reverse it.
Step 4 writing plan
Section-by-section content map
| § | Heading | Approx words | Content |
|---|---|---|---|
| 1 | Context | 250 | Finding #2 verbatim. Cite schema.ts:170-188 (subset hashing) and :153-159 (deliberate-exclusion docstring). Practical-attack paragraph. CLAUDE.md §10 sentence. ADR-006 cross-reference one-liner. |
| 2 | Decision | 150 | Option A is the recommendation. λ Reputation timing argument. The 1-line schema-change + migration scope. |
| 3 | Alternatives Considered | 600 | Option A (200 words: cost, security property, key material, λ fit). Option B (220 words). Option C (180 words). Each option’s negatives are at least as long as its positives. |
| 4 | Consequences | 250 | Positive (3 bullets), Negative (3 bullets), Neutral (2 bullets). Plus the chain-validity table (3 rows). |
| 5 | Implementation | 200 | For Option A: file change list + migration script outline + test rewrite list. For Options B/C: one-line “if reversed” pointer. |
| 6 | Verification | 100 | How to confirm Option A landed. Specifies npm test filter, hash regression test, migration smoke test. |
| 7 | References | n/a | Bulleted list, ≥6 entries, all clickable. |
Total target: ~1.55k words excluding frontmatter / tables / status block. Within the 1.0k–1.6k contract band.
Chain-validity table — pre-written here for Step 4 transcription
| Option | Invalidates data/colibri.db chains? |
Invalidates data/ams.db chains? |
Migration approach |
|---|---|---|---|
A — include agent_id in hash |
Yes. Every existing record’s stored hash becomes wrong relative to the new function. audit_verify_chain would report all chains broken. |
Yes, same reason. | One-shot recomputation pass: walk every task_id, recompute hash and prev_hash chain in insertion order, write back. Bumps user_version to 7. ams.db chains may be archived (frozen) instead. |
| B — HMAC signature column | No. Hash inputs unchanged; existing rows pass audit_verify_chain as-is. Signature column is NULL for legacy rows; new rows fill it. |
No, same reason. | Schema migration adds signature TEXT NULL column. Verifier check is gated on signature IS NOT NULL; legacy rows skip the signature check with a logged warning. Per-agent key material lands in agent_keys table. |
| C — document the gap, no code change | No. Zero code change. | No, same reason. | None. The legitimacy story narrows to chain-content integrity only. |
Recommendation justification block — pre-written here
The recommendation is Option A. The migration cost is bounded by the size of
thought_records(low hundreds of rows indata/colibri.dbat R83 close); the security property gained is the strongest of the three for the cost (chain-integrity now binds authorship); and the recommendation defers no decision Phase 1.5+ would need to undo. Option B’s per-agent key management is a Phase 1.5+ decision and Option B’s signature mechanism can layer on top of Option A later if cross-agent verifiability is ever required externally. Option C is rejected because it documents acceptance of a hole the legitimacy axis cannot tolerate by Phase 2 λ Reputation.
File list (Step 4 commit will touch)
| File | Action | Lines |
|---|---|---|
docs/architecture/decisions/ADR-009-authorship-binding.md |
Create | ~250 |
docs/architecture/decisions/index.md |
Edit (add 1 bullet) | +1 |
Commit template
feat(adr-009-authorship-binding): propose ζ chain authorship binding ADR
Adds ADR-009 (Status: Proposed) covering Finding #2 from the
whole-system code review: agent_id is excluded from computeHash
and the chain therefore proves WHAT/ORDER but not WHO authored.
Three options evaluated (include agent_id in hash, HMAC signing,
document the gap). Recommendation: Option A.
Step 5 (verification) plan — pre-staged for transparency
The verification doc records:
- The commit SHA + branch.
npm run build && npm run lint && npm testexit code (must be 0).- The 7-section sanity grep result (Context / Decision / Alternatives Considered / Consequences / Implementation / Verification / References).
- Chain-validity table presence grep.
- Word-count audit using
wc -wminus the frontmatter / tables. - Confirmation that no source files were changed:
git diff --stat origin/main -- src/ data/returns zero lines.
Risk gates
| Risk | Trip | Mitigation |
|---|---|---|
| ADR softens the gap | Context section uses “documentation gap” or “naming issue” instead of “cryptographic gap”. | Step 4 must include the words “asserted but not cryptographically bound” verbatim. The contract C4 invariant is the gate. |
| Recommendation silently flips | Step 4 author rewrites the §Decision in favor of B or C. | This packet locks Option A. Any reversal requires rewriting this packet first (a 5-step gate violation). |
| Word count blows up | Step 4 over-elaborates Options B / C. | Target word counts are pre-allocated in the section table above. Step 4 monitors wc -w after each section. |
| index.md gets reformatted | Step 4 reformats the existing 6 ADR rows. | The contract I4 invariant prohibits non-additive edits. |
Implementation order
- Write the ADR body (Step 4 part 1).
- Verify against contract A1–A7 acceptance criteria.
- Add the one-line index.md update (Step 4 part 2).
- Single
git commitper the template. - Run
npm run build && npm run lint && npm test. Record results in Step 5. - Write the verification doc (Step 5).
- Commit verification doc separately.
Approval
This packet is self-approved by the executor per CLAUDE.md §6 (Gate rule: “the packet gates implementation — it must be approved before Step 4”). For T3 round-internal approval, the contract’s acceptance criteria (A1–A7) are the binding gate.