diff --git a/docs/scratchpads/AMD1213-D-transaction-and-helper-hardening.md b/docs/scratchpads/AMD1213-D-transaction-and-helper-hardening.md index edcea5a7..368d7bb8 100644 --- a/docs/scratchpads/AMD1213-D-transaction-and-helper-hardening.md +++ b/docs/scratchpads/AMD1213-D-transaction-and-helper-hardening.md @@ -13,13 +13,42 @@ which understated progress by roughly two defects. Branch head `3667a7a7`. | Defect | State | Evidence | |---|---|---| -| D1 transactional rollback | Substantially implemented | `fleet-launch-command.ts` snapshots links before mutating, prepares the manifest, and has `injectFailure` seams at `prepare-manifest`, `write-manifest`, `close-manifest`, `rename-manifest`; restores `manifestLinksBefore` on failure | +| D1 transactional rollback | **Confirmed** — controls exist and are strong | see below; one narrow gap (in-memory link restoration unasserted) | | D2 exact managed-link classes | Substantially implemented | classifier at `fleet-launch-command.ts:598-663`: exact resolved credential, direct one-component plugin/skill only, symlink target and ancestor rejected, `realpath` containment, duplicates rejected | | D3 ambient-PATH executable resolution | **Closed** — executables `585dac7a`, environment `3667a7a7` | see below; one deliberate residual (HOME) | | D4 config check/apply safety | Substantially implemented | `secure_dir` ancestor checks, `read_private` with `O_NOFOLLOW` + fstat, apply via mkstemp + fchmod 0600 + fsync + dev/ino re-check before `os.replace`, compatibility path separated | | D5 bounded test seam | **Closed this pass** (commit `b91b702a`) | see below | | D6 validate-by-path then exec-by-path | Substantially implemented | helper runs as a verified snapshot piped to `bash -s`, not executed by pathname; the same binding applied to the runtime in D3 | +### D1 — confirmed, and a correction to my own survey + +I first reported that eleven `injectFailure` seams existed in production and **zero tests used +any of them**, and that D1's rollback path had never been executed. That was wrong. The grep +behind it searched for the identifier `injectFailure` in the specs; the specs supply the injector +as an inline lambda, so the controls were there and the search could not see them. Method note +for the next survey: grep the production seam names, not the parameter name. + +The controls that exist, all in `fleet-launch-command.spec.ts`: + +- **All ten mutation seams**, table-driven — `mkdir-seat`, `prepare-manifest`, `write-settings`, + `write-snapshot`, `credential-link`, `prune-link`, `install-link`, `write-manifest`, + `close-manifest`, `rename-manifest`. Each asserts byte-for-byte restoration of six artifacts + (settings bytes, settings mode, generated snapshot, manifest, credential symlink target, plugin + symlink target) plus the absence of the `.tmp` manifest. +- **New-seat rollback** — a failure on a seat the transaction itself created leaves no directory + and no residue. +- **`ROLLBACK_INTEGRITY` escalation** — three parent-substitution attacks (symlink swap, inode + replacement, rename away) each produce a typed refusal, leave an external sentinel untouched, + and write `.mosaic-fleet-launch-recovery.json`. A replacement of the transaction-created seat + is likewise refused rather than deleted. + +That is a real RED→GREEN matrix, not an implementation read as done. + +**Gap, narrow:** nothing asserts the in-memory restoration of `plan.managedLinks.links` to +`manifestLinksBefore` — the filesystem is checked, the plan object is not. It matters only if a +caller reuses a plan after catching a failure, which nothing currently does, so this is +defence-in-depth rather than a live defect. Worth one assertion when D2/D4/D6 are confirmed. + ### D2 — one thing worth recording so it is not "fixed" later The alias concern in the packet (`duplicates/normalization aliases`) is closed by strictness, not @@ -156,9 +185,9 @@ skip. Falsified by inverting the guard's default to `!leaseEnforcementActivatabl ## Still open -- **D1/D2/D4/D6 need confirmation, not assumption.** They read as substantially implemented but I - have not run the packet's full RED→GREEN control matrix against each seam. This is now the - largest remaining item in the amendment. +- **D2/D4/D6 need confirmation, not assumption.** They read as substantially implemented but I + have not run the packet's full RED→GREEN control matrix against each seam. D1 is now confirmed + (see above), D3 and D5 are closed; these three are the remaining item. - **D3's HOME residual** is routed to harness-homes (see above). It is stated, not engineered around, and it does not belong to this branch. - Required next evidence per the packet: all D1–D6 observed RED→GREEN controls, framework-shell,