Repository navigation
Canary proof: per-consumer canary and zero-hit sink search with positive controls (key lane acceptance tool) - #579
Merged
Conversation
…pair rule The parked row's semantics (class test_canary, status test_only, environment-only CANARY_E2E_KEY, store file canary-e2e.env) with rotation and notes naming tools/credentials/canary_proof.py; credential_status accepts the pair only together; the runner's injectable-id set gains canary-e2e (contract draft 3, section 2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onsumer wrappers canary_proof.py holds only synthetic values and value-free records: durable scan_requested before any setup, CP03 validation with a per-kind permitted-field table, fsync-then-acknowledge HITs, create-only store publication, one classifier and value-free receipts. canary_scan_worker.py does every sink read inside the bounded runner's scope: descriptor-relative pre-walk, held-descriptor handoff and post-walk reconciliation, rg 14.1.0/15.2.0 with its pinned stats grammar, GNU decoders with raw and BOM fan-out, strict journal export parsing, Git object reconciliation and the escaped-URI SQLite dumper with actual-main identity. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d integrated tests A synthetic host per test (own HOME/XDG, 0700 runtime and store, pinned guard copy, reviewed rg and GNU decoders, fake journal/systemctl/systemd-cat); module-hook launchers for coordinator, worker and dumper. Fixes found by the tests: the store identity adds the publication ctime (a recreated file can reuse a freed inode), and the rg output cap is enforced after complete records are attributed, so a canary record that arrived is never lost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… stages carry no in-band control The classifier table runs every code over a real clean run's record; kill and failure points before the plan leave the latest request unfinished or incomplete. Fix found by the tests: control_gaps demanded the in-band control on producer-only stages (expected 0), which failed every U4 stream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reuse ripgrep 14.1.0 fixed-string/stats, CPython descriptor handoff and the pinned bounded runner. Reject hard type changes, incomplete setup, forged completion and premature comparison; cover declared user configuration/database globs. Co-Authored-By: GPT-6 Codex runtime worker (gpt-6.1-sol-max via OmniRoute, effort max) <noreply@openai.com>
… shadow tables by table_list The GPT-6 runtime worker's uncommitted continuation edits to the coordinator and the worker, committed as it left them (its CANARY-STATUS.md audit; paused for the shared quota reserve before it committed them). Coordinator: a setup child whose END is not complete refuses; a pointer target that is neither a regular file nor missing refuses; a `cleaned` event whose absence check failed is `store_absence_unverified`; the receipt carries `not_covered` from the full sink policy; the clean claim names the four quiescence residuals; A12's primary checkout is a module constant a test launcher points at its synthetic home; an unexpected exception prints only `internal_error`. Worker: the prepare-time journal read parses systemd v255 export framing by declared lengths (binary fields carry a uint64 LE length); short setup helpers fail on a nonzero exit or any stderr byte and cap their stdout; a zlib-framed loose-object file the store cannot account for is an unaccounted payload; an alternate into an excluded path or a config include is unplanned indirection; virtual tables need real shadow tables (PRAGMA table_list); the dumper checks its scope too; every Flow closes its selector. Co-Authored-By: GPT-6 Codex runtime worker (gpt-6.1-sol-max via OmniRoute, effort max) <noreply@openai.com>
…ent and command classes The GPT-6 runtime worker's uncommitted test edits, committed as it left them. Its last partial run (before the pause) had one B2 failure and stopped inside F-M2; the Opus continuation commits after this one repair and complete them. Adds StabilityTests (ST1-ST9), FifoTests (F-M1a/b/c, F-M2, F-M2b, F-M3, F-M4, F-M5, F-M6, F-U4), ModeTests (M1-M7), ContainmentTests (C2, C3, C5-C8 with the exec stub) and ContainmentRealScopeTests (the same plus C4 with the real ecosystem-bounded-run), CommandTests (exact argparse spellings, TTY and CLAUDECODE refusals, the K4 deny test that skips with `guard deny rule not present (K4 item 14)` per amendment C2, guard-allowed templates, the S8 wrapper's argv/home/null descriptors, child-side guard pin and plan-carried runtime paths), worker-launcher seams (argv record, forbidden opens, spawn failure, wrong runtime), a test-only store-worktree metadata seam, and `--skip-list` (C13). Co-Authored-By: GPT-6 Codex runtime worker (gpt-6.1-sol-max via OmniRoute, effort max) <noreply@openai.com>
…acOS Linux-only note The GPT-6 runtime worker's uncommitted documentation edits, committed as it left them (contract draft 3 section 15, amendments C2, C5, C6, C11, C12 and C13): the Canary proof section of docs/secret-storage.md (CLI, exit and verdict code tables, byte boundary, sinks, exclusions, window steps W1-W12) and its restart-step correction; decision-record Part 5 (pinned sources, repairs, evidence classes, budget, reconsideration conditions); the macOS note. Co-Authored-By: GPT-6 Codex runtime worker (gpt-6.1-sol-max via OmniRoute, effort max) <noreply@openai.com>
… git stderr only at fsck Run for the first time with the user service manager available, every ContainmentRealScopeTests case failed at prepare with setup_failed: the unchanged adoption/tools/ecosystem-bounded-run resolves `bash` (its `#!/usr/bin/env bash` line), `id` and `stat` through PATH, which the coordinator sets to CHILD_PATH, and the fixture CHILD_PATH held only the reviewed scanners (the runner's stderr, captured once in a debug launcher: "/usr/bin/env: 'bash': No such file or directory"). Production's CHILD_PATH (/usr/local/bin:/usr/bin:/bin) has all three, so this is a fixture repair; the runner stays unchanged. B2 wrapped git to print its stderr sentinel on every call, including the setup child's checkout-fingerprint rev-parse, which the continuation made strict (any stderr byte fails setup, contract 10.1/11). The sentinel is now written by the scan's fsck only, which is what B2 audits. After this, BoundaryTests.test_b2 and all seven ContainmentRealScopeTests pass with the real runner (8 tests, 50.8 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…C4/C9/C11 and C8 at the tool Each draft-2 fault class and draft-3 repair now has a named assertion that fails for its own reason (amendment C3): - UnitTests: rg record grammar under a consistent stats block (empty, unknown and unlabelled records). - Boundary: B4 lying-worker frames (an unterminated check under a matching END; a complete RESULT with stderr bytes); B6 an rg planted earlier on CHILD_PATH after the coordinator's check is never run; B7 attempt pattern files appended to or blank-lined after prepare. - Stability: ST1 the held descriptor reads the original inode (a clean file swapped in after the handoff still leaks in subpass 0); ST6 a store below a canary-named directory never reaches Git's argv; ST6 link outcomes (link_out incomplete; declared, covered, K and dangling links each counted); ST9 a bound in-root pointer target is an exact exclusion; ST9 the route recheck, with a seam that drops times from the identity tuple (the deferred shared-mapping residual), catching a same-size gzip-to-plain rewrite. - FIFO: F-M1b/c require changed_type at both seams. - Modes: M1 the real scanner's valid output then exit 2, raw ASCII behind a BOM alone, an emptied control file; M4 an index-less pack holding an unreachable canary blob and an fsck exit 128 without stderr; M5 the URI names each complete, a WAL-only change selecting its older main database (UTF-16, so raw WAL frames miss it), and a main-descriptor race whose name is restored before the pathname checks; M6 on its own (name, dangling target, path spanning components, a name after a newline, a key-home boundary name, negatives). - Containment: C8 prepare, scan (no request admitted) and arm refuse a pipe core collector; real scope C9 (no run state under /run/user/$UID) and C4 with a child started after both deaths; C4's worker budget raised so the scope backstop, not the worker, is what the observer sees. - Commands: C11 scan output appears only after every sink finished. - The fake journalctl models systemd v255 journalctl.c:2463-2474 (--after-cursor skips the first surviving entry after a vacuumed cursor), so a restored --after-cursor is caught. All 48 new or changed tests pass on this head (276 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ry, never the database's own inode A rename of the database file itself changes that inode's ctime, so the dumper's closing tuple recheck caught the earlier race whether or not the actual-main-descriptor check ran (the mutation runner showed the mutant surviving). Swapping the parent directory for a decoy and back leaves the database inode untouched: the held tuple, PRAGMA database_list and the pathname stat all pass, and only the identity of the descriptor SQLite actually opened fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mplete; unterminated checks are named Contract 5: when admission cannot append and fsync the scan request, no work starts and no current pass is published. The failed append used to surface as an internal error (exit 1); scan now prints a fixed line and returns 3. R2 forces fsync to fail and checks exit 3, no plan, and a verdict that is not clean. Contract 12 (plan coverage): a sink row that looks complete but whose ledger holds a declared check without a terminal result now yields check_not_scanned:<root id>:<check> (prefixed by the group outside the agent final) beside inventory_unreconciled. R3 forges such a ledger entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…M6's negative name stays one name Contract 13.7 and draft 2's 13.4: every command in the Canary proof section's command blocks and the workflow's status command is an allowed agent command and never names the secret variable (the user-run pair is excluded until K4's deny rule lands, amendment C2). The M6 negative case used the canary's first 20 characters, which can hold its '/' and then named a subdirectory; the slash is now replaced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aft 2's 65, 13 G6 repairs, 8 more)
Amendment C3 and contract 13.8: python3 -I tests/canary_mutants.py --json prints one object per mutant {id,
target_file, patch_sha256, killing_test, failing_assertion, killed}. Each mutant is an exact text edit that must apply
once and compile; it runs in a fresh scratch copy under /tmp (the pinned inputs plus the loader files the credential
inventory's validation requires, as a Git repository with one empty commit because prepare fingerprints HEAD). A kill
needs the named test to pass unmutated and then fail with an AssertionError ending in the named label; import, syntax
and other errors never count. The repository's input hashes are compared before and after. Patches, every test
output and a table with each fault's description are retained under --keep or a new /tmp/canary-mutants-*.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… invalid An unreadable record cannot be disarmed safely (the store file's inode is only known from the record), so cleanup now reports invalid (exit 4) the way disarm and arm do and removes nothing; previously it deleted the run directory whatever the record said. The unused first classification before the cleaned event is gone. StoreTests arms, breaks the record and checks exit 4 with the run directory and the synthetic store file kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kernel scope observers for C1/C3/C4/C7 The first complete mutation run (76/86 killed, 53/53 pristine) left ten survivors. Each was a test that did not isolate its fault, or a fault that a second layer also guards: - A scanner exit 2 is refused by the worker (settle) and again by the coordinator (a complete RESULT with a bad exit or stderr bytes is a protocol error): a unit test now pins the worker's rule and B4 the coordinator's. - R1's kill points each face a passing final again (an earlier point's unfinished request had masked the next). - B7's union edits run with one sink: a later sink's worker start re-hashed the union and hid the missing re-hash. - M3's anchor case keeps the bound first cursor, so only the anchor rule fails; M2 adds a compressed UTF-16 file on its own (only the BOM-first, same-encoding branch sees it) and requires every branch complete. - C3 kills the worker itself: under the real runner bash carries the worker's arguments too, and killing it left the worker running (the real-scope C3 then waited out the coordinator). Blocked children now write a ready marker before they block, so the kill never lands before the child runs. - Labels: S-no-list and the cleanup exit carry plain labels, so a failure names its assertion. The real-scope classes also watch the ecosystem-job scope cgroups themselves (C1, C3, C4 require the scope directory gone, not only the processes), and a new C7 case has every rg the worker starts report its own cgroup and limits: an ecosystem-job scope with memory.max 6 GiB, pids.max 256 and cpu.max 200000 100000. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion commands, lifeline and scope evidence docs/secret-storage.md: the PLAN, CP03 and ACK frames with every offset and width, CP03's C7 extensions (kind 9 COUNTER and its twelve counters, class 8 anchor, own-session path classes 14-16, FACTs 10 and 11), the one version-code formula (C13), what "upstream executable" means, the omniroute-lane arm with its registered home, and the build's synthetic acceptance: the skip list and the mutation runner (python3 -I tests/canary_mutants.py --json). Decision record Part 5: no lifeline pipe is used (C13 asked to define or delete it); the mutation table's shape and what its first run taught (a one-layer mutant of a two-layer guard survives, so each layer got its own oracle); the real-scope classes ran on the workstation after the fixture PATH repair; actual line counts against the budget. macOS note: moved out of the brew-services decision it had split from its bullet list, as its own paragraph. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ectory (S4); two table rows re-targeted The mutation run on 11c4aa0f killed 85 of 87. The omitted-re-walk mutant survived ST1 because unlinking a replaced file changes the held inode's ctime, which the post-view tuple recheck already sees; ST4 now also creates a file after the scan pass listed its parent and scanned its neighbour, which only the final re-walk's entry-list comparison can see (contract 13.3 S4). The ASCII-before-BOM mutant fails M2's every-branch-complete assertion first, so that is its named assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ew test changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the Opus review A GPT-6 runtime worker (gpt-6-astra, effort max, native login) repaired the findings of both reviews; the coordinator commits its working tree unchanged (the worker's sandbox mounts .git read-only): - the seven false-clean paths: discovered Git indirection files and damaged Git directories, a WAL family bound to a scanned SQLite main, an incomplete END never becoming complete, symlink coverage by the full selection rather than a root prefix, the journal cursor seal carried in the plan, an unterminated final journal entry, and virtual-table shadows owned by exact module suffixes; - cleanup stops the bound scope after a complete END using the unreaped command, with an empty cgroup required; the B1 sentinel is planted and checked as the same 24 bytes; FIFO fixtures observe the intended blocked child; the parent-death matrix covers every executable kind and helper stage the worker starts (80 subcases); - A12's second store is the primary checkout's common Git directory; truthful not_covered for absent stream roots; M2/M6 negative controls that can fail; pointer exclusion bound to prepared seals; the contract's section 13 and 10.3 acceptance cases added as permanent tests, each with its mutant; - the decision record no longer claims a real-scope containment pass before one is recorded. Sandbox gates: 141 tests OK (13 skipped: 12 real-scope classes, 1 K4 deny rule), FIFO 9/9, boundary 12/12, mutants 135/135 killed by their named permanent tests. Co-Authored-By: GPT-6 Codex runtime worker (gpt-6-astra, native, effort max) <noreply@openai.com>
…_unreconciled validates The 2026-10-01 read-only re-check of the repair round (a07b7a24) found one remaining false-clean path and one record-validation defect. This round repairs both, one low finding and the documents. - Worker: a directory the walk reaches directly with Git object-store shape (objects/<2 hex>/<rest of an object name>, or a pack or index file in objects/pack) where no logical store is recognized (no HEAD, refs or *.git name, no gitfile) now refuses as git_indirection_unplanned, the gitfile damaged-target refusal. Before, its zlib loose objects went to the plain view and a canary inside them read as clean (reproduced at a07b7a24: scan exit 0, complete). - Coordinator: scan_finished's request-level reasons accept inventory_unreconciled as sink rows already do. A hard-error run on a busy root now reads as incomplete (status 3), not as an invalid record (4) whose cleanup kept every runtime file (reproduced at a07b7a24: S5 pack, status 4). - Worker: the M2 negative count floors each view at zero; a view that lost its in-band control no longer packs -1 into an unsigned field (a sequence gap, protocol_error). - Tests: RepairTests.test_objects_only_store_reached_directly_refuses (Git-made zlib loose objects holding the run's canary in no raw form, an index-only objects/pack, a packed store); the S5 status assertion through the real validator; test_m2_negative_count_stays_unsigned_without_inband_ control; git_stores 1 for damaged .git directories, the first Git layer's own oracle. - Mutants: R-OBJONLY, R-S5-VALID and R-M2-UNSIGNED added. R-02 survived its first run because the objects-only refusal is a second layer; it is now killed by REPAIR-GIT-damaged-store-recognized. R-19's edit text follows the changed M2 line. - Docs: the exact damaged Git layouts; ripgrep 15.2.0 as a source-reviewed grammar, not executed; the verdict-code table's prefixed check_not_scanned codes and suffix notation; the coordinator's outside-sandbox results in place of "pending"; updated counts; residuals for the unfixed findings. Workstation run, outside any sandbox, fresh TMPDIR under /var/tmp: python3 -I tests/test_canary_proof.py -v ran 143 tests in 1015.455 s, OK, 0 skipped; canary_mutants.py --check --json: all 138 apply once and compile; --json: 138/138 killed, pristine runs 90/90, repository inputs unchanged; git diff --check clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… commit, last) evidence/receipts/canary-proof-verification-20261001.json records the coordinator's gates on the canary head (the unit suite with its real-scope containment cases, the mutation runner, and the credential, guard, Codex worker-lane and pre-commit suites), the review rounds and the residuals. manifests/evidence.json from main 000aae7 re-registers the fourteen changed files and adds the receipt; scripts/validate.py passes with 183 receipts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
5 tasks done
seathatflowsinourveins
pushed a commit
that referenced
this pull request
Oct 1, 2026
…ed; #578's sources as plain citations The first update of the dated edition under its own overturn conditions 4 and 5. - cross:credential-practice, in the keys lane owner's wording: the canary proof tool merged with #579 (e58850f) and its synthetic acceptance on the workstation is recorded (143 unit tests, 138 of 138 mutants, 531 suite tests with one failure by design); the acceptance names what the two receipts record, class local_integration_check; the end-to-end proof on the new distribution has not run on any host and stays a new-host step; closure c3 and c4 reworded. - The seven citations of PR #578, which merged as 65a7b03, become plain source paths; the record lists five merged pull requests and two open ones (#575, #535). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
seathatflowsinourveins
pushed a commit
that referenced
this pull request
Oct 1, 2026
…ed; #578's sources as plain citations The first update of the dated edition under its own overturn conditions 4 and 5. - cross:credential-practice, in the keys lane owner's wording: the canary proof tool merged with #579 (e58850f) and its synthetic acceptance on the workstation is recorded (143 unit tests, 138 of 138 mutants, 531 suite tests with one failure by design); the acceptance names what the two receipts record, class local_integration_check; the end-to-end proof on the new distribution has not run on any host and stays a new-host step; closure c3 and c4 reworded. - The seven citations of PR #578, which merged as 65a7b03, become plain source paths; the record lists five merged pull requests and two open ones (#575, #535). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
seathatflowsinourveins
pushed a commit
that referenced
this pull request
Oct 1, 2026
…ed; #578's sources as plain citations The first update of the dated edition under its own overturn conditions 4 and 5. - cross:credential-practice, in the keys lane owner's wording: the canary proof tool merged with #579 (e58850f) and its synthetic acceptance on the workstation is recorded (143 unit tests, 138 of 138 mutants, 531 suite tests with one failure by design); the acceptance names what the two receipts record, class local_integration_check; the end-to-end proof on the new distribution has not run on any host and stays a new-host step; closure c3 and c4 reworded. - The seven citations of PR #578, which merged as 65a7b03, become plain source paths; the record lists five merged pull requests and two open ones (#575, #535). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 1, 2026
…e); keys row, landed sources, distribution row (#583) * Architecture edition: the keys lane's row after the canary proof merged; #578's sources as plain citations The first update of the dated edition under its own overturn conditions 4 and 5. - cross:credential-practice, in the keys lane owner's wording: the canary proof tool merged with #579 (e58850f) and its synthetic acceptance on the workstation is recorded (143 unit tests, 138 of 138 mutants, 531 suite tests with one failure by design); the acceptance names what the two receipts record, class local_integration_check; the end-to-end proof on the new distribution has not run on any host and stays a new-host step; closure c3 and c4 reworded. - The seven citations of PR #578, which merged as 65a7b03, become plain source paths; the record lists five merged pull requests and two open ones (#575, #535). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Architecture edition: the distribution row after the recipe follow-up merged (#582) - cross:wsl-distro no longer says stage 1 waits for the follow-up: PR #582 merged as b8dd81d, and the recipe now starts with a rehearsal on a throwaway name and pre-checks in the workstation distribution. The install command, the new-host steps, the lane gate and the notes say so; nothing in the recipe has run on a host. - The winner's pin_source follows the pinned hash to its new line in the recipe (250, was 99): the follow-up inserted sections above it, and the build checks a citation's bounds, not its content. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Architecture edition: selections follow the repositories' own quality, not the source host's legacy The user's rule of 2026-10-01: evaluate each repository on its own quality and do not shape the new distribution by what the source host has installed, pinned or failed to integrate. - durable-memory: ai-memory is the reference arm, not a default (the 2026-09-27 decision). agentmemory joins with the one matched harness result on record (recall_all@5 0.821 against 0.570 on LongMemEval-S, Mac, descriptive), MemPalace as an arm, Hindsight as arm K1 judged fresh; the gate no longer treats this host's integration holds as evidence about the repository; the first new-host step installs every arm fresh. - token-efficiency, in the Gate A owner's words: comparison_required; the 14-component profile is the source host's selection and one arm, the lean base an arm of equal standing, and the E2E decides which components stay. - Trading rows, in the trading lane owner's words: the verdict selections that had been listed as alternatives for lacking a stack pin are winners of their layers (DVC, pandera, agent-retrieval-bench, Inspect AI, MLflow), each with its upstream install command and the class its recorded run supports. - cross:runtime-workers: a candidate without a repository pin is a candidate, not an exclusion. - Every comparison row carries the reason that its merit winner is undetermined and that the comparison selects. Verdicts: 20 selection_of_record_open, 15 comparison_required, 2 new_host_required. 130 winner entries. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Architecture edition: the memory comparison is against ai-memory with its reranker off, not production A cross-family audit corrected the wording of the one matched memory result. The 0.821 against 0.570 recall on LongMemEval-S compares agentmemory's arm D2 with ai-memory's arm C3: the production embedder and query prefix with the reranker off. ai-memory's production arm runs the LLM reranker (C4, amendment A14) and has not run, nor has agentmemory through its shipped hooks (D2h); the arms' captures and embedders differ and the ai-memory build was a 2.5 pre-release. The durable-memory row and the record now say configuration-level evidence, not a production head-to-head, and cite the convergence record itself (paired difference +0.251, 95% CI +0.203 to +0.299). Overstating a challenger is the same bias the merit rule excludes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Re-register this branch's changed files in manifests/evidence.json (hot-file protocol) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Scout <scout@local> Co-authored-by: Claude Fable 5.1 <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.
Scope
tools/credentials/canary_proof.py(coordinator) plants a unique synthetic canary. Named consumers use it throughtools/credentials/credential_run.py. A contained worker,tools/credentials/canary_scan_worker.py, then searches the named sinks with positive controls: ripgrep over every scan mode, GNU decoders, Git object stores, SQLite and the journal. The classifier refuses, and never reports clean, unless every required check has a fresh, complete result bound to the run. Scanner and decoder children run in a finite systemd user scope and do not outlive a dead coordinator. No sink byte, file name or link target reaches the coordinator process. Also included: thecanary-e2einventory entry, consumer wrappers, acredential_status.pyrow, the mutation runnertests/canary_mutants.py, and docs.2979742f; the canary's emitted commands are checked against its guard (sha25633a11fc0…) by the unit suite.000aae77(main, with K3 Command guard tightening: systemd-run launchers, substitutions in double quotes, macOS ps -E, systemctl show-environment, fail-closed and work budget #511 and K4 Guard K4: runner commands, bounded interpreter reading, OmniRoute management routes #567 merged).lane:foundation.tools/credentials/canary_*,tests/test_canary_proof.py,tests/canary_mutants.py,adoption/credential-inventory.json,adoption/platforms/macos-arm64.md,scripts/credential_status.py,tests/test_credential_status.py,tests/test_credential_run.py(one test-id set),docs/secret-storage.md(canary section),docs/decisions/2026-09-29-key-management.md(canary part),evidence/receipts/canary-proof-verification-20261001.json, and the shared hot filemanifests/evidence.json(re-registration and this receipt only).SOTA sources
cg_is_empty_recursive(cgroup emptiness), https://github.com/systemd/systemd-stable/blob/v255.4/src/basic/cgroup-util.c#L927; systemd tree https://github.com/systemd/systemd/tree/db11bab38ccf1ed257f310d29070843d4c58ea01; util-linux v2.39.3setprivparent-death signal, https://github.com/util-linux/util-linux/blob/v2.39.3/sys-utils/setpriv.c#L1055; wait(2), https://man7.org/linux/man-pages/man2/wait.2.html.table_listhttps://www.sqlite.org/pragma.html#pragma_table_list. Virtual-table shadow ownership followssqlite/sqlite@version-3.45.1:ext/fts5/fts5_main.c(fts5ShadowName),ext/fts3/fts3.c(fts3ShadowName) andext/rtree/rtree.c(rtreeShadowName).objects/<2 hex>/<rest>,objects/pack).Evidence-class table
local_integrationpython3 -I tests/test_canary_proof.py -vlocal_integrationpython3 -I tests/canary_mutants.py --jsonlocal_integration(workstation scope enforcement)... -v ContainmentRealScopeTestslocal_integrationsource_review(GPT-6 verification, Opus review, Opus re-check)canary-proof-verification-20261001Local commands run
Reviews (one review round, one repair round, one re-check with a bounded fix)
.gitname reached directly, plus a record-validation defect. One bounded fix round (Opus builder) closed both, each with a test and a mutant, and fixed an unsigned M2 count. The coordinator reviewed the code diff.Residuals
Recorded in the decision record and the receipt, from the Opus re-check:
requested_incomplete(it is never clean);Walk.covered's exclusion, time, special-file and symlinked-parent branches, and several O12 changes have no test of their own;--text, a count-based Git reconcile);bind_scope's refusal paths and the realscope_populatedparser are untested (the native success path ran);Also: ripgrep 15.2.0 is accepted on a source-reviewed grammar and was never executed (14.1.0 runs); the implementation and test file exceed the contract's line ceilings (an accepted deviation for required logic).
Decision record
docs/decisions/2026-09-29-key-management.md(canary part, including "Re-check round (2026-10-01)");docs/secret-storage.md(canary section).Checklist
🤖 Generated with Claude Code