Skip to content

Wave 12: route-auth lead-finder, install update hygiene, heavy lease in a sandbox, "new": null for dirty files - #2159

Merged
remigiusz-antczak merged 1 commit into
mainfrom
land/wave-12
Oct 31, 2026
Merged

remigiusz-antczak merged 1 commit into
mainfrom
land/wave-12

Conversation

@remigiusz-antczak

Copy link
Copy Markdown
Collaborator

Wave 12: four changes; the commit message has the detail and known limits.

What changes

  1. Route-auth lead-finder: route_auth_map.py lists HTTP handlers and their auth evidence; a mutating handler with none is HIGH. It runs in review_checks.sh --full. Report-only: silence proves nothing.
  2. Install hygiene: bumping an unedited install leaves no skill backup or .new copies, the summary scans only the paths install writes, and install deletes nothing it did not create.
  3. Heavy lease in a macOS sandbox: with a read-only cache dir, writers fall back to a per-user 0700 temp dir and readers check both. Sandboxed code can forge or block a lease there, which only delays or denies heavy commands.
  4. Unknown "new": diff-mode rows in files with uncommitted edits get "new": null.

Verification

  • Affected suites: 82 of 82 sections passed before the final fold (an install.sh comment, one test at 15 of 15 on this commit, a changelog line). CI runs the full set.
  • One independent review per change. No red is left open; the install red is fixed, and its test fails on the old code.
  • Size ratchet ok, with one documented raise.

🤖 Generated with Claude Code

…in a sandbox, "new": null for dirty files

Review (deep-code-review):
- scripts/route_auth_map.py DIR: a report-only, stdlib-only lead-finder
  for missing authentication (CWE-306/862). It inventories HTTP handlers
  (Next.js app routes, pages/api, "use server" exports, Express, Router,
  Hono and Fastify calls, FastAPI and Flask decorators) and prints one row
  per handler with the auth evidence it found. A mutating handler with no
  evidence is HIGH, a GET with none is INFO. A Next middleware or proxy
  whose matcher covers the route counts as evidence when it names an
  identity check or can answer 401/403, so a custom-named session gate
  counts. A quoted /path literal in that file reads as an allow-list
  entry (a trailing (.*), /* or /:name* is dropped first), unless it is
  a prefix of a matcher entry or sits in the condition of an if whose
  body can refuse. Known ceilings: conditions are not evaluated; a scope
  check written as a ternary, an && chain, a switch case or a
  redirect-only body reads as an exemption; regex, computed or imported
  allow-lists are not read; and a 401/403 that checks no identity (CSRF,
  geo, rate limit) also counts.
- review_checks.sh --full runs it as tool route-auth (HIGH rows as rule
  missing-auth); references/security-appsec.md routes it from the
  Anonymous GET sweep.
- review_checks.sh diff mode: "new" is null (unknown) for every row in a
  file that differs from HEAD in the working tree. The file list comes
  from a lock-free git status that leaves .git/index alone; a failed read
  omits the key and says so on stderr. method-situational.md documents
  the third value.

Install (install.sh, perun_marker.py, vendor_drift.py):
- A version bump of an unedited install leaves no skill backup and no
  .new copies: the fresh backup is dropped when it equals the previous
  install recorded in the marker (a backup holding any entry that
  install did not write is kept), an unedited slash command is refreshed
  in place, and an existing .new / .new-N that already holds the shipped
  file stops a duplicate. Install deletes no file it did not create in
  that run, so .new files already on disk stay. Edited, pre-Perun and
  differing files are never touched.
- The install summary's Generated list scans only the paths install
  writes. It used to scan whole host dirs for newer files, so under a
  home target it also listed session transcripts, todos and other files
  that other processes wrote during the run. Known ceiling: a file
  another process writes inside one of those paths during the run (a
  rewritten settings.local.json, a new file in .claude/commands) still
  lists.
- vendor_drift.py compares an "(install placeholder)" stub with the docs
  file install.sh copies over it, so a clean install no longer reads as
  drift; a missing docs file fails closed.

Delivery (perun_policy.py, stage_run.py):
- On macOS, the heavy-job throttle and the exclusive train lease work
  inside a Claude Code sandbox. heavy-acquire could not write its lease
  under the read-only user cache dir, so sandboxed scanners ran unleased
  and no other session could count them. Writers now use the first
  writable of the usual dir and a per-user fallback under the sandbox
  temp dir (only a real directory owned by the user with mode 0700, with
  no symlinked or foreign directory below it), and every reader,
  including the heavy_gate.py hook, checks both.
  PERUN_HEAVY_DIR still pins one dir. Other platforms keep the 1.628.0
  behaviour.
- Readers open lease files without blocking and skip anything that is
  not a regular file, so a planted FIFO cannot hang the hook. stage_run
  only unlinks a stale lease outside the usual dir and never signals a
  process group named there.
- Known ceiling: anything running in the sandbox can write the fallback,
  so it can forge or block a lease, or stall another sandboxed writer,
  and so delay or deny heavy commands. The same user's sessions already
  share that temp dir.

Tests: 82/82 affected suite sections (run-ci-tests.sh --affected
6eb3f03, run before the install-summary test fold, which changes only
an install.sh comment, that test and a changelog line);
test-install-hygiene.sh 15/15 on the final tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@remigiusz-antczak
remigiusz-antczak merged commit a235394 into main Oct 31, 2026
10 checks passed
@remigiusz-antczak
remigiusz-antczak deleted the land/wave-12 branch October 31, 2026 00:25
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