Summary
Strengthen the audit trail from "recorded" to "cryptographically verifiable": each persisted ActionTrace carries an HMAC over its own content plus the previous record's signature (a hash chain), and a verify_chain() API detects any insertion, deletion, or mutation in the log.
Why this matters
The project's headline value is authorization plus auditable proof of what ran. A hash-chained log upgrades that proof from "we wrote it down" to "any tampering is detectable on replay" — the property compliance reviews increasingly look for (EU AI Act Article 12 guidance converges on append-only, hash-chained logs as the technical standard). It also differentiates the kernel from gateway-style tools whose audit logs are plain database rows.
Proposed scope
- Add
record_hash and prev_hash fields to the persisted trace record envelope (not to ActionTrace semantics).
- Chain via HMAC-SHA256 keyed by
WEAVER_KERNEL_SECRET (consistent with the existing token signing approach), with a documented genesis record.
TraceStore.verify_chain() -> ChainVerificationResult reporting first divergent record on failure.
- Deterministic canonical serialization for hashing (sorted keys, explicit encoding) so verification is reproducible across processes.
- Retention helper:
prune(before=...) that preserves verifiability of the remaining suffix (records a checkpoint of the pruned head).
- Document the integrity model and its limits honestly in
docs/security.md (a host that controls the secret can forge a chain; this is tamper-evidence against post-hoc edits, not non-repudiation).
Implementation notes
- Builds on the persistent trace store work (pluggable backends); chain logic should live in one module, applied by any backend.
- Reuse the HMAC secret-loading path from
tokens.py (WEAVER_KERNEL_SECRET, dev-secret fallback with warning) — never log key material (see docs/agent-context/invariants.md).
- Canonicalization: follow the existing deterministic-output rule (no randomness) —
json.dumps(..., sort_keys=True, separators=(",", ":")).
- Tests must cover: valid chain verifies; mutated record detected; deleted record detected; reordered records detected; prune-then-verify succeeds; wrong secret fails verification with a clear error from
errors.py (no bare ValueError).
Acceptance criteria
Out of scope
References
- EU AI Act Article 12 logging guidance (append-only, SHA-256 hash-chained logs as common practice).
- RFC 6962 (Certificate Transparency) for the verifiable-log mental model.
- Existing HMAC envelope signing in
federation_discovery.py (sign_manifest/verify_manifest) as in-repo precedent.
Priority: P0 · Effort: M · Impact: Transformational
Summary
Strengthen the audit trail from "recorded" to "cryptographically verifiable": each persisted
ActionTracecarries an HMAC over its own content plus the previous record's signature (a hash chain), and averify_chain()API detects any insertion, deletion, or mutation in the log.Why this matters
The project's headline value is authorization plus auditable proof of what ran. A hash-chained log upgrades that proof from "we wrote it down" to "any tampering is detectable on replay" — the property compliance reviews increasingly look for (EU AI Act Article 12 guidance converges on append-only, hash-chained logs as the technical standard). It also differentiates the kernel from gateway-style tools whose audit logs are plain database rows.
Proposed scope
record_hashandprev_hashfields to the persisted trace record envelope (not toActionTracesemantics).WEAVER_KERNEL_SECRET(consistent with the existing token signing approach), with a documented genesis record.TraceStore.verify_chain() -> ChainVerificationResultreporting first divergent record on failure.prune(before=...)that preserves verifiability of the remaining suffix (records a checkpoint of the pruned head).docs/security.md(a host that controls the secret can forge a chain; this is tamper-evidence against post-hoc edits, not non-repudiation).Implementation notes
tokens.py(WEAVER_KERNEL_SECRET, dev-secret fallback with warning) — never log key material (seedocs/agent-context/invariants.md).json.dumps(..., sort_keys=True, separators=(",", ":")).errors.py(no bareValueError).Acceptance criteria
prev_hash/record_hash; chain verifies end-to-end.verify_chain()detects mutation, insertion, deletion, and reordering, identifying the first bad record.docs/security.mddocuments the integrity model, the threat it does and does not cover, and key-management caveats.Out of scope
References
federation_discovery.py(sign_manifest/verify_manifest) as in-repo precedent.Priority: P0 · Effort: M · Impact: Transformational