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:

  1. Cost is bounded and one-shot. Option A is a 1-line change to computeHash plus 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.
  2. Migration is feasible because the chain is small. At round R83 close, the largest task chain in data/colibri.db is in the low hundreds of records. data/ams.db is heritage; its chain is frozen and can be archived rather than migrated.
  3. 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.
  4. 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.
  5. 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_id as 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 in data/colibri.db at 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 test exit 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 -w minus 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

  1. Write the ADR body (Step 4 part 1).
  2. Verify against contract A1–A7 acceptance criteria.
  3. Add the one-line index.md update (Step 4 part 2).
  4. Single git commit per the template.
  5. Run npm run build && npm run lint && npm test. Record results in Step 5.
  6. Write the verification doc (Step 5).
  7. 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.


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.