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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant