Skip to content

fix(comply): verify the tamper-evidence chain instead of asserting it - #227

Open
rylinjames wants to merge 1 commit into
mainfrom
fix/comply-verify-record-chain
Open

fix(comply): verify the tamper-evidence chain instead of asserting it#227
rylinjames wants to merge 1 commit into
mainfrom
fix/comply-verify-record-chain

Conversation

@rylinjames

Copy link
Copy Markdown
Collaborator

Audit §3.10 / Part 1 #17 — the comply module's flagship integrity claim.

Problem

summarize_audit_log computed its own rolling hash and reported it as the "tamper-evidence head". The technical file and the EU AI Act Art-12 mapping then cited "tamper-evidence hash-chain" as evidence — but nothing was ever verified. An edited / reordered / truncated audit log produced a clean summary and a signed conformity bundle. Meanwhile the runtime recorder already writes a real prev_record_hash/record_hash chain and ships a tested verifier (record.verify_record_chain) that comply never called.

Fix

  • summarize_audit_log now verifies each file's chain with verify_record_chain (per-file — the recorder resets the chain per session). Adds chain_verified (True / False / None), chained/unchained file counts, and the first broken file+index.
  • _iter_records counts skipped lines (parse_error_count, non_dict_count, unreadable_file_count) instead of silently dropping them. A broken chain or any dropped line flips the summary status to "tampered".
  • The technical file renders the verdict (PASS / FAIL — chain broken at <file> #<idx> / n/a), not just an opaque head hash.
  • Art-12 record-keeping flips to gap when the chain is broken or lines were dropped — tampered logs no longer count as covered evidence.

Tests

tests/test_comply_chain_verification.py (6 cases, all pass): valid chain verifies; edit / reorder / mid-file drop each break it with location; corrupt line counted + status flip; unchained ActionGuard logs report None (no false claim).

Existing test_comply.py (signed-bundle export + CLI export→verify round-trip) still passes. ruff clean.

🤖 Generated with Claude Code

Audit §3.10 / Part 1 #17 — the comply flagship integrity claim.

summarize_audit_log computed its own rolling hash and reported it as the
"tamper-evidence head", and the technical file + EU AI Act Art-12 mapping
cited "tamper-evidence hash-chain" as evidence — but the code never verified
anything. An edited / reordered / truncated audit log produced a clean
summary and a signed conformity bundle. Meanwhile the runtime recorder writes
a real prev_record_hash/record_hash chain and ships a tested verifier,
record.verify_record_chain, that comply never called.

Now:
- summarize_audit_log verifies each file's chain with verify_record_chain
  (per-file, since the recorder resets the chain per session). Adds
  chain_verified (True/False/None), chained/unchained file counts, and the
  first broken file+index to tamper_evidence; adds an `integrity` block.
- _iter_records now counts skipped lines (parse_error_count, non_dict_count,
  unreadable_file_count) instead of silently dropping them — a vanished line
  is an integrity signal, not noise. A broken chain OR any dropped line flips
  the summary status to "tampered".
- Technical file renders the verification verdict (PASS / FAIL+location / n/a),
  not just an opaque head hash.
- Art-12 record-keeping control flips to "gap" when the chain is broken or
  lines were dropped — tampered logs no longer count as covered evidence.

Tests (tests/test_comply_chain_verification.py, 6 cases): valid chain verifies;
edit / reorder / mid-file drop each break it with location; corrupt line is
counted and flips status; unchained ActionGuard logs report None (no false
claim). Existing comply export + CLI round-trip tests still pass; ruff clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant