feat(integrity): tamper-evident hash chain for event audit log (#2200)#2210
Merged
Merged
Conversation
Adds a SHA-256 per-node hash chain over the immutable identity fields of every event (`id`, `agent_type`, `node_id`, `agent_id`, `session_id`, `workspace_id`, `event_type`, `ts`). Cost backfills and other post-hoc writes touch only mutable columns and do not break the chain. - `clawmetry/local_store.py`: new `chain_prev_hash`/`chain_hash` columns (DDL + migration for existing stores), `chain_heads` tracking table, `_stamp_integrity()` called inside the flush transaction, and `verify_integrity()` reader method. - `clawmetry/cli.py`: `clawmetry verify-integrity [--node-id ID]` subcommand that opens the store read-only and reports VALID or the first broken link. - `tests/test_integrity_hash_chain.py`: 10 unit tests covering genesis hash, sequential links, cost-backfill safety, tamper detection, per-node filter, and pre-chain event counting. Off by default. Set `CLAWMETRY_INTEGRITY=1` to enable stamping. Closes #2200 Co-Authored-By: Claude <noreply@anthropic.com>
5 tasks
vivekchand
added a commit
that referenced
this pull request
May 28, 2026
This was referenced May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2200
What
Adds a per-node SHA-256 hash chain over the immutable identity fields of every event stored in the local DuckDB store. Each event gets
chain_prev_hashandchain_hashstamped atomically with the insert; a newchain_headstable tracks the current head per node.Changes
clawmetry/local_store.py— newchain_prev_hash/chain_hashcolumns added to theeventsDDL and via_MIGRATIONS_V2(safe for existing stores);chain_headstracking table;_stamp_integrity()called inside the flush transaction so hashes land atomically;verify_integrity(node_id=None)reader method that walks the chain and returnsVALIDor the first broken link.clawmetry/cli.py—clawmetry verify-integrity [--node-id ID]subcommand opens the store read-only and prints the result.tests/test_integrity_hash_chain.py— 10 unit tests covering: genesis hash (prev_hash = "0"*64), sequential chain links, cost-backfill safety (the critical acceptance criterion), tamper detection on immutable fields, per-node scoping, and pre-chain event counting.Key design choices
id,agent_type,node_id,agent_id,session_id,workspace_id,event_type,ts) so cost backfills writingcost_usd/token_count/modeldon't invalidate the chain.CLAWMETRY_INTEGRITY=1to enable stamping. Zero overhead when disabled;verify-integrityworks on any store regardless._integrity_hashapplies the same field defaults as_event_to_row(agent_type → 'openclaw',agent_id → 'main') so stamp-time and verify-time hashes always agree._stamp_integrityruns inside the same_txnas the flush, so a crash mid-batch leaves no partial stamps.Test plan
python3 -m pytest tests/test_integrity_hash_chain.py -v→ 10 passedpython3 -m pytest tests/test_local_store.py tests/test_error_signal.py tests/test_entitlements.py tests/test_integrity_hash_chain.py -q→ 60 passedGenerated by Claude Code