Skip to content

fix(guard): protect ai-memory, Muse Code and Codex dotenv stores (A2 G8-A02) - #1240

Open
seathatflowsinourveins wants to merge 12 commits into
mainfrom
fix/credential-guard-store-gaps
Open

seathatflowsinourveins wants to merge 12 commits into
mainfrom
fix/credential-guard-store-gaps

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

Closes A2 finding G8-A02 by protecting the registered ai-memory, Muse Code and Codex stores in the guard and maintained deny copies. The inventory, metadata checker and canary exclusions carry the same additions; canary exclusions match both literal and canonical spellings.

  • Original base: 90471d63f20918efa3a63ef949caffd8c012656c.
  • This fold's parent: f2462c3717fb30786d93ba433dda610129426a20, the reviewed Fold 9 head. Fold 9's parent was ac01e51b4293b1bd6aa15e01f2611d5de5610a39, the merge of origin/main at a887cc4bbc5825391f622bb1fd71580ea97511fb into the reviewed 42e8b821 head.
  • Lane: lane:foundation.
  • Fold 9 changes the descriptor helper's comments, the key-management decision addendum and their two existing evidence rows. The PR description is carried on the PR.
  • This fold corrects the decision's final-head counts and scope, refreshes its existing evidence row, and updates the PR description.

The implementation and registered store definitions are cited by repository path and line only. No credential path or value is reproduced in this body.

Final behavior

  • The guard, settings template and hand-maintained deny copies cover the added stores. The existing hook-command and example-file controls remain part of the prior folds' coverage.
  • Six inventory rows feed metadata-only status checks. override_variables is distinct from a file pointer: the checker warns for any set data-directory override other than the stack default, including empty and blank values; prepare refuses an empty, blank or relative override.
  • scan_sink builds canonical exclusion forms against the live filesystem at each scan. An exact exclusion resolves its parent and preserves its final component; a glob exclusion resolves its whole directory. A symlink at an excluded name keys that link, while its ordinary target inside a covered root is scanned as itself.
  • The worker derives directory-root paths and file-root parents from their open descriptors. An unavailable or ambiguous descriptor path ends the walk as walk_error, making the sink incomplete. A literal suffix on a file root's own basename is preserved separately.

Fold 9: sealed finding NC-1240-1

NC-1240-1 (P2), fixed. The code comment and decision addendum now cite the Linux kernel matching this host and the pinned man-pages release for the descriptor-path mechanism. The kernel explicitly calls the deletion suffix ambiguous. fd_path already refuses every suffixed target, including a live file or directory whose actual name ends in (deleted); it never strips the suffix or tries to disambiguate it with a second lookup. Its production callers use directory descriptors and fail closed on None. A file root's basename is joined to the accepted parent separately and kept verbatim.

proc_pid_fd(5) at the supplied release documents descriptor links and readlink, but does not document the deletion suffix. The addendum identifies its exact documentation in proc_pid_exe(5) and proc_pid_maps(5), bounds those pages to their interfaces and cites the kernel call chain for descriptor-link behavior.

Fold 9 changed no executable behavior or tests. Its executable AST matches ac01e51b after removing docstrings. The brief required a new failing regression only if behavior changed, so no fail-first overlay was needed. Fold 9 closed its one sealed finding.

Fold 10: sealed verdict at f2462c3

  • R-1240-1 (P2), fixed. The decision and this PR description now report 12,307 hashed files and file rows for the final f2462c37 head. The 12,308 result belonged to the intermediate builder tree that included an extra PR-body file and its evidence row.
  • R-1240-2 (P3), fixed. The Fold 9 scope names the worker comments, the decision addendum and their two existing evidence rows. The PR description is carried on the PR. This correction fold changes the decision and its existing evidence row; the complete corrected PR description is supplied separately.
  • NC-1240-1, already closed. Fold 9's pinned descriptor-path citations and ambiguity policy remain intact.
  • R-1240-3, refuted by the sealed resolution. The citations already include repository, tag, full commit, source path, line and URL.
  • F3, recorded follow-up. The earlier decision's outside-root link_out claim overlooks the worker's return for an excluded entry before following its link. This fold leaves the deferred item open.

The decision's SHA256 and byte count were refreshed once through scripts.host_receipts.register_file for both corrections. The worker bytes and all tests match f2462c37; no behavioral fix or new regression test is involved. Both blocking findings are addressed.

SOTA sources

  • Correction source: native-agent-stack at f2462c3717fb30786d93ba433dda610129426a20, manifests/evidence.json:5012,18565,65870. Counting the final-head files array yields 12,307 entries; comparison with ac01e51b4293b1bd6aa15e01f2611d5de5610a39 yields exactly two changed rows, for the decision and worker, and no PR-body row. The sealed resolution is MICRO-gpt61sol-resolution-f2462c37.md, SHA256 ed70562ea258a7c43a7b8b5a18c2beb7686adf5fc0a4d75304f7acdc1f3beb4a.
  • microsoft/[email protected], commit d504d40ab83839cb61942a812a99d183c42227b9: fs/proc/fd.c:174-189,211-214, fs/proc/base.c:1823,1838-1854, and fs/d_path.c:255-256,287-288,318-325. The host's uname -r reports 6.18.54.1-microsoft-standard-WSL2. These sources establish descriptor-path rendering and its ambiguous suffix.
  • kernel.org/pub/scm/docs/man-pages/[email protected], commit adb436b2e4471218021d86f188fb58dec3946eb8: man/man5/proc_pid_fd.5:13-23 for descriptor symlinks and readlink; man/man5/proc_pid_exe.5:23-25 for the suffix on executable links; man/man5/proc_pid_maps.5:151-153 for the suffix and ambiguity on mappings. The latter two pages do not establish descriptor-link semantics on their own.
  • Existing guard design records at original base 90471d63f20918efa3a63ef949caffd8c012656c: docs/decisions/2026-09-24-secret-storage.md, docs/decisions/2026-09-27-claude-harness-settings.md and docs/secret-storage.md.
  • Prior folds' configuration sources: akitaonrails/ai-memory at v2.4.1 (433a19f3d54dea287571b1423591db2a89965fa9), crates/ai-memory-cli/src/config.rs:573,1358-1364,2086-2095,2248-2266; v2.3.2 (353841d91618d20b110b208de284a74d0b960379), the same file at :462,1137-1145,1808-1817,1970-1974; and v3.1.0 (11ca7c5b3b65e7fc216c7eae5a9aac67d38c11ea), :760,2349-2357,3218-3227,3446-3450. These establish data-directory resolution, not descriptor-path behavior.
  • Prior folds' empty-value source: figment 0.10.19, ai-memory's locked crates.io release, src/providers/env.rs:504-519,614-625 and src/value/parse.rs:99-105; retained provenance is in docs/decisions/2026-09-29-key-management.md:1256-1265 at ac01e51b.
  • Historical ST9 acceptance used the official BurntSushi/ripgrep 15.2.0 release. This fold uses the already-fetched kernel and manual checkouts, with no network, installation or new runtime selection.
  • Muse Code's reference remains the repository's tools/muse_file_fence.py; the earlier folds found no upstream sign-in-path source. This fold adds no stronger claim.

Evidence-class table

Claim Evidence class Evidence
Descriptor links render through d_path; the suffix is ambiguous source_review Pinned kernel call chain above; cited files match their Git tag
Descriptor links and the other proc interfaces have the documented manual semantics source_review Pinned man-pages locators above; cited files match their Git tag
Fold 9 preserves executable behavior local_integration Parsed AST comparison with ac01e51b, ignoring docstrings, exit 0
Fold 10 preserves the worker and tests and corrects the final-head record local_integration / source_review Worker and test diff against f2462c37, exit 0; final-head manifest count and comparison above
Missing canonical root paths fail closed for directory and file roots; removed and non-path descriptors are refused synthetic Existing tests/test_canary_proof.py:967-997 rerun, exit 0
The live-name ambiguity follows the existing suffix-refusal branch and file-root reconstruction source_review tools/credentials/canary_scan_worker.py:418 and Walk.traverse; no new runtime claim

Local commands recorded for Fold 9

The Python commands used the preinstalled CI virtual environment on PATH. The manifest counts below describe the final f2462c37 head; the other results are retained Fold 9 checks.

python3 -m unittest tests.test_canary_proof.UnitTests.test_ai_memory_root_without_a_canonical_path_is_incomplete
exit 0; one existing test passed

git diff --exit-code linux-msft-wsl-6.18.54.1 -- fs/d_path.c fs/proc/base.c fs/proc/fd.c
exit 0 in the supplied kernel checkout

git diff --exit-code man-pages-6.19 -- man/man5/proc_pid_fd.5 man/man5/proc_pid_exe.5 man/man5/proc_pid_maps.5
exit 0 in the supplied man-pages checkout

git diff --check
exit 0

python3 scripts/validate.py
exit 0; 12,307 hashed files, 71 components, 4 profiles, 243 manifest receipts

python3 scripts/evidence_manifest.py --check
exit 0; 12,307 file rows

python3 scripts/host_receipts.py validate
exit 0; 183 host receipts

Fold 9's worker AST comparison also exited 0; no test file changed. Its kernel and manual pins were verified locally. Fold 9 did not repeat the earlier folds' full canary, mutation or guard acceptance runs, or qualify a host installation.

Local commands run for Fold 10

Python commands used PATH=/var/tmp/cc-cc-work/venv-ci/bin:$PATH from the workspace root.

python3 -m unittest tests.test_canary_proof tests.test_runtime_worker_openhands_push_gate
exit 0; 282 tests, 137 skipped

python3 scripts/validate.py
exit 0; 12,307 hashed files, 71 components, 4 profiles, 243 manifest receipts

python3 scripts/evidence_manifest.py --check
exit 0; 12,307 file rows

python3 scripts/host_receipts.py validate
exit 0; 183 host receipts

git diff --check
exit 0

The pinned kernel and manual file comparisons were rerun with exit 0 for each; their tags resolve to the full commits above. The worker's executable AST still equals ac01e51b after removing docstrings. A diff against f2462c37 confirms unchanged worker bytes and tests. Final-head manifest inspection confirms 12,307 entries, no PR-body row and exactly the decision and worker rows changed from ac01e51b; only the decision row changes in this correction fold. These checks do not reproduce historical fail-first, mutation, full ST9 acceptance or host-installation claims. No new behavioral regression is required for the two documentation corrections.

Decision record

docs/decisions/2026-09-29-key-management.md:1314 records NC-1240-1's mechanism, ambiguity policy, exact citations, verification and bounded layer-resolution scope. Its Fold 10 addendum at :1392 records R-1240-1 and R-1240-2, the pinned final-head evidence and the dispositions of NC-1240-1, R-1240-3 and F3. The previous template-count addendum remains in docs/decisions/2026-10-02-new-wsl-client-configuration.md.

Boundaries and follow-ups

The proof remains Linux-only; a macOS descriptor-path branch is not implemented. The existing tests cover directory, glob and file roots; git and tasks roots use the same code and remain separately untested. The earlier class-wide follow-up retains read-class and spelling gaps, other profile exclusions, alternate data-directory sources, prepare-time binding of overrides and whole-store archive/interpreter handling. A value exported only in the writer's shell remains outside the proof's binding. Host installation and the subsequent host-copy test belong to the existing landing procedure.

Checklist

  • No new workflow, permission grant, paid surface, credential or dependency.
  • No credential value or concrete credential path is reproduced here.
  • No credential store was inspected by this fold.
  • Changed file rows are registered through scripts/host_receipts.py's register_file API.
  • Independent landing review is requested for this fold.

🤖 Generated with Claude Code

…G8-A02)

A2 audit finding G8-A02 (P1): the secret-path guard, the user settings
template, the credential inventory and the Muse file fence named no
ai-memory or Muse Code store, and Codex's dotenv file was covered only by
the generic .env reader rule.

- scripts/hooks/secret_path_guard.py: three STORE_PATHS patterns appended
  after index 16: ai-memory/auth-token, auth-header and auth-tokens/
  (service_secret_path), Muse's .config/muse/auth.json and Codex's
  .codex/.env (native_store_path). The ai-memory hook commands, which name
  only --data-dir, and a sibling .env.example still pass.
  adoption/hooks/claude/SHA256SUMS re-pinned.
- adoption/templates/claude.settings.template.json: Read(~/...),
  Read(**/...) and Edit(~/...) denies for each store, ahead of the .env
  carve-outs.
- adoption/credential-inventory.json: five protection-only entries.
- tools/muse_file_fence.py: .local/share is a protected home input.
- docs/decisions/2026-10-02-new-wsl-client-configuration.md: addendum with
  the new piece counts (419 pieces, 226 practice).

Sources: akitaonrails/ai-memory v3.1.0 (11ca7c5b)
crates/ai-memory-cli/src/config.rs:3347, :3359 and
src/server_profiles.rs:30; openai/codex rust-v0.163.0 (83086188)
codex-rs/arg0/src/lib.rs:270-276.

Tests fail on 90471d6 with only the two test files overlaid and pass
here: tests.test_secret_path_guard (test_g8_a02_*, linear-time leads) and
tests.test_muse_file_fence (test_local_share_home_input_refused).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 17, 2026
Fold 2 of PR #1240 (A2 finding G8-A02) on 8d735d9: the nine findings of
the Claude security read (CHANGES_REQUESTED) and the Muse read (P3).

- P2-1, P2-2, P2-3: the Muse auth.json, Codex .env and Codex auth.json
  patterns (STORE_PATHS 18, 19 and 3) also read the ${XDG_CONFIG_HOME:-...}
  and ${CODEX_HOME:-...} spellings, as LinearScans through
  default_run_scan like index 1; the regular-expression equivalence test
  covers all four new scans.
- P3-1: ai-memory's pattern (17) also reads $AI_MEMORY_DATA_DIR and
  ${AI_MEMORY_DATA_DIR:-...} (ai-memory v3.1.0 config.rs:760);
  POINTER_VARIABLE gains AI_MEMORY_DATA_DIR, the pointer variable of the
  four ai-memory inventory rows.
- P3-2: <data_dir>/auth.json (config.rs:3028-3038, :3064-3075): pattern,
  Read/Edit denies and the ai-memory-provider-auth inventory row.
- P3-3: a reader of the ai-memory data directory or the Muse config
  directory itself, or a glob over its top level, is refused (the
  HF_HOME_ROOT precedent); `ai-memory backup --to FILE` still passes.
- P3-4: tests for the default and override spellings, the directory reads
  and the six inventory rows; the carve-out comment is corrected.
- P3-5: the auth-tokens row points at upstream's first profile, default
  (config.rs:996, :1220).
- P3-6: .claude/settings.json and the docs/secret-storage.md hand-merge
  block carry the 18 rules.

SHA256SUMS re-pinned; the record addendum states 422 pieces (229
practice); manifest rows re-registered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fold 3 of PR #1240 (A2 finding G8-A02) on e4309ef, the two blocking
findings of the CC verdict CC-DELTA-e4309efc.md (findings 1 and 2 of
MICRO-delta-e4309efc.md).

- Finding 1 (P2): ai-memory's data-directory override is a directory,
  and the pointer-variable field means the path of a store file. The
  four ai-memory rows now read it the way the CODEX_HOME and HF_HOME
  rows read theirs, as a path-template default:
  ${AI_MEMORY_DATA_DIR:-$HOME/.local/share/ai-memory}/<file>, with
  pointer_variables []. scripts/credential_status.py accepts that one
  extra template prefix; expand_template, which the checker,
  credential_run.py and canary_proof.py all use, already resolves it.
  With the variable exported, canary_proof.py's pointer_paths no longer
  lists the directory (so prepare binds no directory pointer), its
  exclusions hold the four token files under it as key paths instead of
  the directory, and credential_run.py no longer strips the variable
  from child environments. The guard keeps refusing reads through the
  variable (POINTER_VARIABLE keeps the name; its comment says why).
- Finding 2 (P3): the STORE_ROOTS comment now states the rule exactly.

Tests: tests.test_canary_proof
UnitTests.test_ai_memory_data_dir_override_is_no_pointer and
StabilityTests.test_st9_ai_memory_data_dir_override_passes_prepare
(needs a reviewed ripgrep), and the updated
tests.test_secret_path_guard test_g8_a02_inventory_rows. SHA256SUMS
re-pinned; manifest rows re-registered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…rride

Fold 4 of PR #1240 (A2 finding G8-A02) on 0378825, the P2 of the CC
verdict CC-DELTA-03788258.md (MICRO-delta-03788258.md).

Fold 3 made the four ai-memory rows' templates follow the data-dir
variable while the canary U8 root stays at the default directory, so an
exported non-default value moved the exclusions away from the root that
is scanned and dropped the checker's override warning.

The shape chosen is the CC's first one, the smallest that keeps every
reader consistent:
- The four rows keep the fixed default path. This stack pins --data-dir
  to it wherever it runs ai-memory, and the flag wins over the variable
  (akitaonrails/ai-memory v3.1.0 crates/ai-memory-cli/src/config.rs
  :2349-2355; the variable is read at :760).
- AI_MEMORY_DATA_DIR moves to a new optional, warning-only field,
  override_variables. scripts/credential_status.py validates it and
  native_store_overrides reads it, so the checker reports
  store_path_overridden again. canary_proof.py and credential_run.py do
  not read it: no scan root, exclusion, pointer binding or child
  environment follows it.
- The TEMPLATE_PREFIXES addition of fold 3 is reverted.
- The guard keeps refusing reads through the variable; the pointer
  variable test now also covers override_variables.

The other shape, U8 following the same template with exclusions under
every root it walks, was not taken: it moves a scan root after a value
the stack never passes to ai-memory.

Two claims of fold 3 corrected: the rows' shape is not the CODEX_HOME
and HF_HOME shape (Codex roots and exclusions both follow the registered
homes; U8 has no equivalent), and the variable does not move the data
directory for this stack's own invocations, whose flag wins.

Test: tests.test_canary_proof
UnitTests.test_ai_memory_data_dir_override_is_no_pointer exports the
variable to a non-default directory and asserts the token files under
every U8 ai-memory root are keys and the checker reports the override;
it fails on 0378825. SHA256SUMS re-pinned; manifest rows re-registered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ride

Fold 5 of PR #1240 (A2 finding G8-A02) on 0c21a1d, B1-B4 of the CC
verdict CC-DELTA-0c21a1d1.md (security read MICRO-security-0c21a1d1.md).

- B1 (P2): the four ai-memory token names are key exclusions under the
  default and also under the override variable's absolute, non-blank
  value (scripts/credential_status.py override_paths, used by
  tools/credentials/canary_proof.py exclusions, the one list prepare
  digests and the scan uses). No scan root moves. The three claims that
  this stack pins --data-dir everywhere are narrowed to the settings
  template's hooks and the drafted launchd template; runs without the
  flag follow the variable, and the exclusions now cover them.
- B2 (P2): the data-dir resolution is cited at the pinned tags, from the
  vendor's source at each tag: v2.4.1 (Linux pin, 433a19f3)
  crates/ai-memory-cli/src/config.rs:1358-1364 with the variable at :573,
  and v2.3.2 (macOS pin, 353841d9) :1137-1143 and :462. v3.1.0
  (11ca7c5b, installed on the WSL host) agrees at :2349-2355 and :760. The
  token-file locators are given at the pinned tags too; auth-tokens/ comes
  from v3.1.0 only.
- B3 (P3): the override warning fires only for a non-blank value other
  than the default, as ai-memory's env_string reads it (v2.4.1
  config.rs:2086-2095, v2.3.2 :1808-1817).
- B4 (P3): the store_path_overridden comment is corrected, the checker
  paragraph of docs/secret-storage.md names override variables, and the
  key-management decision gains a dated addendum that defines
  override_variables beside pointer_variables.

Tests, failing on 0c21a1d: tests.test_canary_proof UnitTests
test_ai_memory_tokens_written_under_a_moved_data_dir_are_keys_under_every_root
and test_ai_memory_override_warning_needs_a_non_blank_value_other_than_the_default.
SHA256SUMS re-pinned; manifest rows re-registered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…fused

Fold 6 of PR #1240 (A2 finding G8-A02) on 7705ba7, B1-B5 of the CC
verdict CC-DELTA-7705ba78.md (reads MICRO-security-7705ba78.md and
MICRO-muse-7705ba78.md).

- B1 (P2): ai-memory canonicalises its data directory (v2.4.1
  crates/ai-memory-cli/src/config.rs:1366, v2.3.2 :1145, v3.1.0 :2357)
  and the scan worker excludes by exact bytes against children built
  from each root's string. override_paths now returns each moved file as
  written, normalised, resolved through symlinks, and re-anchored on each
  scan root's own path; canary_proof.py exclusions passes the roots. No
  scan root moves.
- B2 (P2): measured first-hand with ai-memory 3.1.0 init, keyless, in a
  throwaway HOME and working directory: with AI_MEMORY_DATA_DIR empty or
  blank the token files land in the working directory. figment 0.10.19
  (the crates.io crate matching ai-memory's Cargo.lock at v2.3.2, v2.4.1
  and v3.1.0) keeps empty values, src/providers/env.rs:504-519, merged
  at v2.4.1 config.rs:1318; canonicalise_or_keep keeps "" (:2254-2266).
  The checker now warns for any set value other than the default, and
  prepare refuses an empty, blank or relative value with
  override_variable_not_absolute. The four claims are corrected.
- B3 (P3): the default is described as ai-memory's
  dirs::data_local_dir()/ai-memory (v2.4.1 :2248-2252; dirs 5.0.1
  src/lin.rs:11-12, src/mac.rs:7, :13) and a config.toml data_dir
  (:1316); the inventory path is this stack's --data-dir value, and those
  moves are not modelled.
- B4 (P3): the digest claim is corrected (prepare's digest and each
  scan's plan are both built by exclusions(); no step compares them),
  and the scan-time test docstring is narrowed.
- B5 (P3): the guard comment no longer calls the variable warning-only.

Tests failing on 7705ba7: tests.test_canary_proof UnitTests
test_ai_memory_moved_tokens_are_excluded_in_their_canonical_spellings,
test_ai_memory_override_refusal_for_empty_blank_or_relative_values and
test_ai_memory_override_warning_for_any_set_value_other_than_the_default,
plus the prepare refusal in
test_st9_ai_memory_data_dir_override_passes_prepare (needs a reviewed
ripgrep). SHA256SUMS re-pinned; manifest rows re-registered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…th sides

Fold 7 of PR #1240 (A2 finding G8-A02) on c467543, B1-B3 of the CC
verdict CC-DELTA-c4675431.md (security read MICRO-security-c4675431.md),
by the verdict's RULING: match on canonical forms on both sides instead
of enumerating spellings.

- B1 (P2): the scan worker (tools/credentials/canary_scan_worker.py)
  takes each walked root's canonical path from the directory descriptor
  it opened (fd_path, /proc/self/fd/<fd>; the proof runs on Linux only)
  and excludes an entry when either its literal spelling or
  canonical_root + "/" + rel matches, for exact rules and for a glob
  rule's parent. Prepare (canary_proof.py exclusions) adds
  canonical_exclusion(path) = realpath(dirname) + "/" + basename beside
  every literal exact exclusion and glob directory. The four-spelling
  enumeration in scripts/credential_status.py override_paths is dropped;
  it returns the literal path only. A trailing-slash CODEX_HOME, a
  trailing-slash HOME with the variable unset (the routed case, closed
  by the same rule) and a trailing-slash glob directory now match.
- B2 (P3): the final component is never resolved, so a symlink planted
  at a token name keys only itself; its target directory is walked.
- B3: the fold-6 commit's B1 bullet described the four-spelling
  enumeration, which this fold replaces; key-management.md and the
  inventory note now state the canonical-on-both-sides rule, naming dir
  and glob roots as tested and the tasks root as covered by the same
  code but not separately tested.

Tests, through the worker's own walk (canary_scan_worker.Walk.traverse,
no scanner): test_ai_memory_moved_tokens_are_keyed_by_the_worker_in_every_spelling
(seven shapes plus a glob-root case; the two trailing-slash shapes and
the glob case fail on c467543) and
test_ai_memory_symlink_at_a_token_name_keys_only_itself (fails on
c467543). The end-to-end StabilityTests
test_st9_ai_memory_moved_tokens_are_never_opened_end_to_end needs a
reviewed ripgrep and setpriv and is skipped on this host and in CI.
Manifest rows re-registered; the guard is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nical form, fail-closed canonical path

Fold 8 of PR #1240 (A2 finding G8-A02) on 98e94f0, the CC verdict
CC-DELTA-98e94f0b.md (Claude read MICRO-delta-98e94f0b.md, Muse read
MICRO-muse-98e94f0b.md). Scanner-class PR: findings cited by path and id.

- B1 (P2; MICRO F4, Muse P2-1): the new ST9 end-to-end test
  (tests/test_canary_proof.py, StabilityTests) wrote the canary before
  prepare, so under a reviewed ripgrep it raised TypeError and pinned
  nothing. It now writes placeholders before prepare and the canary after
  it, and the unreachable doubled-slash forbidden entries are dropped (the
  seam builds dir_fd paths from readlink of the descriptor). Both ST9 tests
  now run and pass under ripgrep 15.2.0 (official release, sha256 checked).
- F1 (P3): a glob rule's directory is canonical by its whole realpath
  (canary_proof.py canonical_exclusion, directory=True); exact rules keep
  realpath(dirname) + basename. New test for a symlinked glob directory.
- F2 and Muse P3-1 (P3): an opened root whose descriptor has no path now ends
  the walk as walk_error (canary_scan_worker.py Walk.traverse, directory and
  file roots), never literal-only matching. Seam test forcing fd_path to
  None, plus fd_path direct cases.
- F3 (P3): kept by the ruling; the residual is stated in
  docs/decisions/2026-09-29-key-management.md and
  adoption/credential-inventory.json.
- F5 and Muse P3-3 (P3): g8_walk builds the plan with the sink's group and
  the current pointer paths; the glob-parent case moves to an agent-group A4
  walk.
- F6 (P3): new tests for a file root, a glob root, a glob parent and an exact
  rule that only the worker's canonical path meets, and for
  canonical_exclusion's forms; eleven G8-* mutants in tests/canary_mutants.py,
  each killed by a named test.
- F7 (P3): key-management.md and the inventory note say scan_sink builds the
  forms at each scan (prepare records a digest only), and list file roots as
  tested and git and tasks roots as served and untested.
- F8 (P3): the G8 unit tests that need /proc carry skipUnless(LINUX).
- Muse P3-2 (P3): recorded in key-management.md: the macOS F_GETPATH branch
  is not implemented, as the proof refuses non-Linux platforms.
- Q2: docs/decisions/2026-10-15-credential-term-grace.md locators re-pointed
  to canary_proof.py:1454-1455 and credential_status.py:361.
- manifests/evidence.json: six rows refreshed.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins marked this pull request as ready for review October 17, 2026 18:24
# Conflicts:
#	adoption/hooks/claude/SHA256SUMS
#	manifests/evidence.json
Fold on ac01e51 for the native codex review's P2: canary_scan_worker.py's fd_path() and the decision addendum now cite microsoft/[email protected] (d504d40a) fs/d_path.c and man-pages-6.19 for the appended suffix, and state how the ambiguous suffix is handled. 1 of 1 findings covered.

Built by GPT (cx/gpt-6.1-sol, max) through the Codex worker profile; committed, gated and pushed by the CC.

The CC removed the build's in-tree PR-body copy (.github/pr-body-1240.md), its manifest row and the decision paragraph that
named it: the body is on the PR. The sandbox had no writable scratch for it then.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Finding statuses from the builder's report:
- R-1240-1: fixed
- R-1240-2: fixed
- NC-1240-1: recorded
- R-1240-3: recorded
- F3: recorded

Built by GPT through the Codex worker profile (stack-worker, effort max); committed, fail-first tested, gated and pushed by the CC's script, whose results are in the PR body.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant