fix(integrity): verify-integrity CLI crashed against running daemon (allowlist + graceful-None)#2222
Merged
Merged
Conversation
The integrity hash chain shipped in 0.12.342 (#2200 / #2210), but FLYWHEEL §7 live verification surfaced an immediate crash: `clawmetry verify-integrity` calls `get_store(read_only=True)` which returns the `_ProxyStore` proxy when a sync daemon is running (the daemon holds DuckDB's process-level writer lock, so any other process cannot open the file even read-only — see memory `reference_duckdb_process_lock`). The proxy forwards each call through HTTP to `/__local_query__/<method>`, but the daemon-side allowlist (`_DAEMON_METHODS` in `routes/local_query.py`) did not include `verify_integrity` — so the proxy returned `None` and the CLI crashed: TypeError: 'NoneType' object is not subscriptable at cli.py:2542 status = result["status"] This commit is two layers of defense so the same family of bug cannot re-emerge for any future LocalStore method exposed through the CLI: 1. Add `verify_integrity` to `_DAEMON_METHODS` (proxy now succeeds against the running daemon). 2. CLI defensiveness: if `result is None` (older daemon predating this fix, daemon unreachable, anything else returning a sentinel None), print a clear "could not reach the running daemon's verifier — restart the sync daemon" message and exit 2 instead of crashing on subscript. Three new regression tests in `tests/test_verify_integrity_cli_proxy.py` pin both halves: the allowlist entry, the None-graceful branch, and the already-good "real chain break" branch. Caught by FLYWHEEL §7 live verification — installed 0.12.342 wheel, ran `clawmetry verify-integrity` against the running daemon, observed the crash, fixed it. No user has hit it yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Visual diffComparing No flagged differences (running with ALWAYS_POST=1).
Folder: pr/2222/ac76cd3b35e4. Full PNGs also attached as a workflow artefact. Generated by visual-diff bot. Pixel diffs >1% flagged; eyeball the table before merging. This check is non-blocking — fail = bot bug, not a code problem. |
5 tasks
vivekchand
added a commit
that referenced
this pull request
May 28, 2026
+ #2222) CHANGELOG entries for two changes already on main: 1. #2217 — syslog/SIEM export (CEF + JSON over udp/tcp/tcp-tls). New Enterprise-grade exporter; off by default. Closes #2199. 2. #2222 — verify-integrity CLI daemon-proxy crash fix. Caught by FLYWHEEL §7 live verification immediately after 0.12.342 shipped: the new CLI subscript-crashed against any standard install because verify_integrity wasn't in the daemon-proxy method allowlist. Two- layer fix (allowlist + CLI graceful-None) plus 3 regression tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Caught by FLYWHEEL §7 live verification
Immediately after
[RELEASE]of #2210 (the tamper-evident hash chain) hit PyPI as 0.12.342, I installed the fresh wheel and ran the new CLI against the running sync daemon (the live-verify step that the FLYWHEEL done-bar requires). It crashed:Root cause
_cmd_verify_integritydoesstore = get_store(read_only=True). When a sync daemon is running (the standard install)get_store()returns the_ProxyStoreproxy because DuckDB locks at the process level — see memoryreference_duckdb_process_lockand PR #1253 — and any other process opening the file (even read-only) gets rejected by the daemon's writer lock.The proxy forwards every method call through HTTP to
/__local_query__/<method>on the daemon. That endpoint enforces a per-method allowlist (_DAEMON_METHODS) so a stolen bearer token cannot call arbitraryLocalStore.<method>.verify_integritywas not in the allowlist → the daemon returned a 400 → the proxy swallowed it asNone→ CLI crashed.Fix (defense in depth)
routes/local_query.py— add"verify_integrity"to_DAEMON_METHODS. The proxy now succeeds against the running daemon.clawmetry/cli.py— explicitif result is Nonebranch that prints a clear message ("could not reach the running daemon's verifier — restart the sync daemon to pick up the new wheel") and exits 2. So even if a future method is added to the CLI without being allowlisted, the CLI prints a human error instead of crashing on subscript.Tests
tests/test_verify_integrity_cli_proxy.py— 3 new tests:verify_integrityis in_DAEMON_METHODS(prevents drift).All 13 integrity-cluster tests pass locally (3 new + 10 existing in
test_integrity_hash_chain.py).Audit the class of bug, not just the instance
Per memory
feedback_audit_class_of_bug_not_just_instance— checked whether any other recently addedLocalStore.<method>is invoked from the CLI and missing from the allowlist. None found in the current CLI; the SIEM exporter (#2199 in flight) does not depend on the proxy.🤖 Generated with Claude Code