Files

3.8 KiB

Follow-up row brief: stack-release.sh hardening after D1 (row 162 review notes)

Draft by Darkwing for Sage (sage-0882), from Filbert's five non-blocking notes on row 162 round 1, #1659 comment 28997. Line numbers are scripts/stack-release.sh and the brief as of row 162's candidate; the script is byte-identical in r1 and r2. This row starts only after row 162 lands, and it rebases on that landing.

Suggested gate: Filbert approves the candidate manifest; cli suite and every scripts/test-*.sh green on Sage's gate. Suggested owner: Darkwing, reviewer Filbert, gate owner Sage.

None of the five is a known failure today. Items 1 to 4 each fail closed or can't be reached with the current pin. The fix is to make each one refuse earlier, or tell the truth sooner, with codes row 162 already has. No new refusal code.

Items

  1. Precheck unreadable drop-ins. drop_in_override (:503) scans the same three directories as install_guard in scripts/bus-service.sh (:100), but skips a directory or file it can't read ([ -d ], grep 2>/dev/null). install_guard dies on that same path, after the stop, so the run goes through item 6 and the live stack stopped for nothing. The precheck refuses drop-in-override with the path when a unit path, drop-in directory or .conf file exists but can't be read, using install_guard's own tests (-r, -x, a failed read). Test: a drop-in file with mode 000 (and a directory with mode 000) refuses before any systemctl stop in the stand-in log, and the units stay active.

  2. Close the is-active to read race. plan_store (:573, check at :577) and the --restore event count (:716) choose the held-store read or the stopped-store read from one is-active call. If the bus stops between the check and the readOnly open, the open can leave -wal or -shm beside a stopped store, and the next run refuses store-unclean. Fix: after a held-store read, check is-active again. If the bus stopped meanwhile, report it (--plan: say the store state changed during the read and print no migration line; rollback: refuse restore-mismatch before anything stops) instead of using the count. Test: a stand-in systemctl that answers active then inactive.

  3. Compare the copy check with the target. The copy-check gate step (:373) runs stack-copy.sh check --business, which proves the bus, Console and CLI agree on one copy, not that the copy is the one this run installed. Pass the expected copy id (or compare the check's reported id with the target) and fail the gate with copy-check on a mismatch. Test: a stand-in check that reports agreement on another copy fails the gate.

  4. Don't split a quoted Environment=. read_units (:148) reads the systemctl show output (show at :144) and splits its Environment= line on spaces with read -r -a (:157). systemd quotes a value that holds a space, so a MOSAIC_CLAUDE_BIN path with a space reads as a prefix of itself. Smallest fix: read_units returns 1 when that line holds a quote or backslash, so its callers refuse as they do for an unreadable unit (unit-flags-drift at :535, check-failed at :561; the status view at :743 then skips its unit flags line). Parsing systemd's quoting is the larger option. The same split reads ExecStart argv (argv_of, :145, used at :153 and :159); cover it the same way. Test: a stand-in unit with Environment="MOSAIC_CLAUDE_BIN=/a b/claude" refuses by name and never reads /a.

  5. Re-pin brief item 8. docs/plans/2026-10-18_stack-release.md item 8 (:180-185) says the plan reads the schema "with no store read". sage-0745 and mos-0741 replaced that with the held or immutable read that row 162 implements. Sage re-pins the brief text; no code.

Out of scope

The bus-side PM marker (ruling 2's follow-up) and anything in Mos's live window.