Files
Jordan Ritter 171943469a fix(showcase): guard reaper against reserved 'showcase' record + isolate review fixes
Cross-session review fixes for the --isolate machinery (one concern:
source + test + docs).

1) Reaper reserved-name guard (critical): _reap_isolate_slot trusted
   slot records — a record naming 'showcase' (corrupt, or written by an
   older CLI version before apply_isolation reserved the name) passes
   the charset regex, so the reap ran `docker compose -p showcase down
   --remove-orphans --volumes` against the LIVE default stack,
   destroying the PocketBase named volume. The reserved name now gets
   the same treatment as the path-traversal guard: warn (naming the
   record and why it is dangerous) and leave the slot intact for manual
   inspection — no compose-down, no state removal.

   Call-site enumeration: _reap_isolate_slot's sole caller is
   _sweep_isolate_slots, at 3 sites (dead-PID reap, project-recorded/
   no-owner reap, age-fallback reap), all passing
   "$slot_entry" "$slot_proj" — all three flow through the new guard
   identically.

   Red-green: the new bats test ("a slot whose project record reads the
   RESERVED 'showcase' is left intact...") was run against the UNFIXED
   code first and FAILED — the sweep logged "Attempting to reclaim
   stale slot 0 (project showcase has no live containers and no
   recorded owner)" and reaped the slot. It passes with the guard.

2) .iso-bak restore race: two concurrent runs can both see a stale
   backup; the loser's mv is the FINAL command of its `[ -f ] && mv`
   AND-list, so its failure trips set -e and kills the CLI pre-claim
   with a raw error. Both mv's now carry `2>/dev/null || true` — the
   survivor's restore wins, the loser proceeds with restored originals.

3) Keep-test absence regexes greped only the `--project-name <name>
   down` spelling; the reaper's own downs use `-p <name> down`, so a
   keep-branch regression via the -p form passed undetected. Both keep
   absence assertions now match `(--project-name|-p) <name> down`.
   Mutation-verified: a temporary -p-form compose-down added to the
   keep branch made BOTH broadened tests FAIL; reverted, suite green.
   (All other absence assertions use the word-matched generic
   `compose ... down` regex, which already covers both spellings.)

4) RUNBOOK.md/DEBUGGING.md contradicted shipped code: the manual
   teardown was quoted without --volumes plus notes claiming
   `down --remove-orphans` leaves named volumes (the shipped survival
   notice and every teardown path include --volumes), and the name rule
   was documented as `[a-z0-9_-]+` (actual: starts with [a-z0-9], then
   [a-z0-9_-], uppercase normalized with a warn, 'showcase' reserved).
   Both updated to the shipped semantics; the now-redundant separate
   `down --volumes` snippets removed.

Verification: full `bats showcase/scripts/__tests__/` green (60 tests);
shellcheck on _common.sh shows no new warnings vs baseline
(pre-existing SC2034/SC2115 only, line-shifted).
2026-06-10 08:58:28 -07:00
..