Files
stack/docs/plans/reviews/2026-09-10_m20-correction-verdict.md

5.1 KiB
Raw Permalink Blame History

M20-CORRECTION-FILBERT-1 (#1500) — corrective-slice verdict

Reviewer: Filbert. Role disclosure: I was the I1 reviewer and the reviewer who reproduced D1D10; this verdict relies on fresh evidence against the corrected code, not inherited approval. Frozen snapshot /tmp/m20-correction-review-5ffad9u7 at manifest SHA-256 af97b5be51760f9075e6df859fee8cedf068fbb6b8464f208b48c129f1f99991 (14 files verified before and after; snapshot unchanged). Baseline b3fa2210…; the two contextual files (packages/mosaic/package.json, src/index.mjs) are byte-identical to the baseline, so exactly 12 files carry the correction. All work in a disposable baseline-plus-overlay tree; no live commands, Docker, secrets, or shared-log edits.

Verdict: APPROVED for the exact corrective slice

Tested observations

  • Suites: 43/43 package tests (loop-expanded safety suite plus schema suite) and 5/5 combined launcher fixtures in my overlay tree — matching the coordinator's 43 and 48/48. The 30 source-level test( occurrences expand to 43 at runtime via the parameterized D1/D2/private-mode loops.
  • D1D10 independently reproduced as fixed. Beyond the author's suite, I reran my own charter-review attacks against the corrected code: missing root → missing-path; the matching-id symlinked provider that previously returned valid exit 0 → symlink-forbidden; https://user:secret@…url-credentials-forbidden with path+code only; malformed JSON → fixed invalid-json code with zero marker echo; the restored fixture returns valid.
  • Extra hostile controls (mine, beyond the suite): FIFO as a provider file → not-a-regular-file with no hang; a stray file where an account directory is expected → not-a-directory; an unreadable mode-000 regular credential.json sibling leaves validation green and list clean (never opened); a chmod-000 directory inside the root refuses; usage errors still exit 2.
  • FD-anchored containment, as reviewed in source: Linux/procfs gate first (explicit unsupported-platform refusal, no silent fallback); .. in the root string rejected; the root path walked from / through per-component directory() opens with O_DIRECTORY|O_NOFOLLOW; lstat-then-open with inode/device recheck (path-changed); jsonFile rechecks inode/device/mode after O_NOFOLLOW|O_NONBLOCK open, caps reads at 1 MiB with a bounded buffer loop, and discards the parser message entirely. Directory FDs anchor child traversal. Errors map to distinct codes (missing-path, inaccessible-path, not-a-directory, symlink-forbidden), and loadRegistry returns empty entries on any refusal — the CLI checks errors before printing, so no partial list output.
  • Private-mode contract: every traversed directory 0700 and every metadata file 0600, owned by the invoking uid, enforced at both lstat and post-open fstat. The README states the contract accurately, including that public Git fixtures cannot preserve modes and the tests re-chmod temporary copies.
  • Schema corrections verified: numeric version exactly 1 (fuzzed with 2, "1", "banana-schema", null, true across all five record kinds); per-kind nested shapes with unknown-field checks for every harness entry, not only pi; URL userinfo/protocol/hash/whitespace rejection with http requiring allowInsecureTransport; default-account enrollment; provider credential-type membership; harness reference existence. Diagnostics carry paths and codes only — no input values, no unknown-key names, no stack spew.
  • Disclosed 14/15 history: consistent with the code (cross-reference validation now precedes the final emptiness check) and honestly recorded with logs; the failing control never accepted a missing registry in either version.

Untested assumptions (design-verified only)

  • Rename-race protection: the inode/device recheck and FD anchoring are statically reviewed, not race-tested. The README disclaims transactional multi-record consistency, which is the right scope.
  • Non-Linux refusal: read in source (rootDirectory platform gate); not executed on another platform here.
  • Wrong-owner refusal: untestable on this single-uid host.

Residuals (documented, not defects)

  • Hardlinks: a hardlink placed inside the 0700 tree with content matching its filename would validate; containment is by inode checks, not provenance. Creating one already requires write access to the tree, so it sits outside this slice's threat model. Worth a README sentence in a future touch.
  • Reporting is fail-fast (first error only) rather than the accumulated error list of increment 1; a behavior change, acceptable for a validator, noted for the record.

Effect and remaining gates

Approval covers committing exactly the 12 changed files (14-file snapshot including the two identical contextual files) at manifest af97b5be…. Materialization remains blocked pending its own chartered increment and review; nothing here authorizes live activation, refresh execution, or service work. Host-wide suites with image/state effects were not rerun, per the request's constraint; the package and launcher fixtures are the applicable green evidence for this package-only change.