ADR-0008: Tamper-evident audit and evidence¶
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-06-07 |
| Authors | Roman Mednitzer |
Context¶
An audit trail that can be silently edited is worse than none: it manufactures false confidence (loss L-3). The trail is also the evidence base for the compliance mapping (EU AI Act Art. 12, ISO 27001). It must be append-only, verifiable after the fact, and resistant to a compromised host clock or a tampered file.
Decision¶
- Each audit record stores
output_sha256andoutput_len, never the output body. Bodies can carry secrets and unbounded attacker-influenced content; the hash proves what ran without retaining it (invariant 3). - The log is append-only JSONL with a per-entry hash chain: each record commits to the previous record's hash, so any insertion, deletion, or edit breaks the chain at a detectable point.
- The audit writer is a separate concern from the audited process (a supervisor writer), so a crash in tool execution cannot truncate a half-written record, and the writer's failure modes are isolated.
- Construction of the logger never raises. If the configured sink is unavailable it degrades to stderr; an audit subsystem that fails to start must not take the server down or, worse, allow execution to proceed unaudited.
- Periodically the chain is committed to a Merkle root (RFC 6962 domain separation: leaf prefix 0x00, node prefix 0x01), the root is stamped with an RFC 3161 timestamp (verification is fail-closed), and optionally anchored in a transparency log (Rekor). The server-binary hash is bound into the session header so the evidence ties output to the exact build that produced it.
- Parameters are logged redacted (ADR cross-ref to redaction); secret values are never written.
Consequences¶
Positive: tampering is detectable, not merely discouraged; evidence survives a hostile host; no secret or unbounded body is retained; verification is offline and reproducible.
Negative: the hash chain must be written in order and verified end to end; out-of-order or parallel writers need the supervisor to serialize them.
Neutral: Rekor anchoring is optional and network-dependent; the Merkle + RFC 3161 layer works offline.
Alternatives considered and rejected¶
- Store output bodies for completeness. Rejected: bodies carry secrets and attacker content; the hash is sufficient proof and far safer.
- A plain append-only file without a chain. Rejected: append-only by convention is not tamper-evident; an editor can still rewrite history undetectably.
- Sign every record individually. Rejected for v0: a hash chain plus periodic Merkle + RFC 3161 gives tamper evidence at far lower key-management cost; the binary hash binds provenance.
Revisit triggers¶
- A regulator requires per-record qualified signatures.
- Multi-writer concurrency outgrows the single supervisor.
Audit note (2026-06-08, ADR-0015)¶
Decision 5 describes the evidence design (a periodic Merkle root, an RFC 3161
timestamp, and an optional transparency-log anchor). In v0 the running server does
not invoke checkpointing, so no Merkle root or timestamp token is produced at
runtime; the default LocalStamper is keyless self-attestation and Rfc3161Stamper
raises NotImplementedError. The live trail is the per-entry hash chain (Decision 2)
plus, when PRAXIS_AUDIT_PATH is set, the owner-only O_APPEND file and any
operating-system append-only control (chattr +a or WORM); with no path configured,
or if the file sink cannot be opened, the logger writes to stderr. Decision 3's separate supervisor writer is also not yet a
distinct process. Wiring runtime checkpointing and a non-forgeable stamper is tracked
as BL-076, with BL-050 for tail-truncation detection. This note records the v0 gap;
it does not amend the decision.