Audit — P0.7.3 ζ Chain Verification Tool

1. Scope

Inventory the existing ζ Decision Trail surface in preparation for implementing audit_verify_chain — the final tool that closes the ζ axis.

2. Existing surface (ζ axis files)

Path Purpose Phase
src/domains/trail/schema.ts Hash primitives: computeHash, canonicalize, ZERO_HASH, ThoughtRecordSchema P0.7.1
src/domains/trail/repository.ts CRUD: createThoughtRecord, getThoughtRecord, listThoughtRecords + thought_record / thought_record_list MCP tools P0.7.2
src/db/migrations/003_thought_records.sql thought_records table DDL P0.7.2
src/__tests__/domains/trail/repository.test.ts ~835 baseline tests (partial count) P0.7.2

Not yet created (this task’s outputs):

  • src/domains/trail/verifier.ts
  • src/__tests__/domains/trail/verifier.test.ts

3. Schema.ts — relevant primitives

computeHash(record) hashes the 6-field subset: {id, type, task_id, content, timestamp, prev_hash}.

  • agent_id is excluded (author metadata, not chain-integrity).
  • hash is excluded (it is the output).
  • Output: 64-char lowercase hex SHA-256.
  • ZERO_HASH = "0".repeat(64) — the genesis prev_hash.

Hash algorithm (canonical from P0.7.1 schema.ts):

canonical_input = canonicalize({id, type, task_id, content, timestamp, prev_hash})
hash = SHA-256(canonical_input, utf8)

Chain invariant: record.prev_hash === previous_record.hash for all non-genesis records.

4. Repository.ts — relevant functions

listThoughtRecords(db, filters) returns records ORDER BY rowid ASC — true insertion order.

  • Optional task_id filter (string).
  • Optional limit filter (positive int).

Both task_id and session_id are relevant for filtering. However, the current schema has task_id (not session_id) as the scope column. The zeta extraction doc’s Python pseudocode uses session_id, but the Phase 0 implementation uses task_id. The audit_verify_chain tool should filter by task_id.

The audit_session_start tool (P0.8.3 / src/tools/merkle.ts) uses a separate audit_sessions table with task_id. The session context is preserved there. For audit_verify_chain, filtering by task_id is the correct Colibri Phase 0 scoping.

5. Server.ts registration pattern

Tools are registered via registerColibriTool(ctx, name, config, handler) where:

  • config.inputSchema is a Zod object schema.
  • handler(input) returns the data payload (middleware wraps in {ok, data} envelope).

Existing tool registrations (P0.7.2 and P0.8.3) are loaded by src/server.ts at import time via named registration functions. The audit_verify_chain tool follows the same pattern:

  • A new registerVerifyChainTool(ctx) exported from verifier.ts.
  • Imported and called from server.ts alongside registerThoughtTools.

6. Migration status

NO migration required. audit_verify_chain is read-only against thought_records. No new tables, no new columns, no user_version bump.

7. Dependencies

  • src/domains/trail/schema.tscomputeHash, ZERO_HASH, ThoughtRecord
  • src/domains/trail/repository.tslistThoughtRecords
  • src/db/index.tsgetDb()
  • src/server.tsregisterColibriTool, ColibriServerContext

All are existing; no new packages.

8. Acceptance criteria (from spec)

  1. verifyChain(records[]) — iterates chain, recomputes each hash, checks prev_hash linking.
  2. Returns { valid: boolean, first_broken_at?: string, broken_count: number }.
  3. audit_verify_chain MCP tool — calls verifyChain on DB chain; optional task_id filter.
  4. Test: tamper one record’s content → valid: false at correct position.
  5. Test: intact 100-record chain → valid: true in < 500ms.

9. Risks and mitigations

Risk Mitigation
Hash input mismatch (verifier uses different fields than creator) Use computeHash from schema.ts — same function the creator uses
Session-vs-task filter confusion (extraction doc says session_id) Phase 0 table has task_id; use task_id; note in contract
Empty chain edge case Return { valid: true, broken_count: 0 }
Performance for large chains O(n) walk is sufficient; 100 records « 500ms threshold

Back to top

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

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