ci/woodpecker/pr/ci Pipeline failed
rev-security-03 REQUEST_CHANGES (review note on the brain), all four findings verified by measurement before fixing: F1 BLOCKER — brokerSocketPresent used access(path, S_IFSOCK). S_IFSOCK (0xC000) is a file-type constant, not an access() mode (0-7): on node 24.18.0 the call throws ERR_OUT_OF_RANGE, so the probe could NEVER return true and the swallow-catch made every un-seamed call report the broker absent — on this host (roster v1) 'mosaic fleet start' would have refused broker-absent forever. Now stat().isSocket(), matching the bash side's [ -S ]. New spec exercises the REAL probe against a REAL unix socket (true), a regular file (false), and an absent path (false) — no seam, so no seam can hide this again. F2 — placeUnitFile's single catch conflated destination-absent with unlink-FAILED; on unlink failure it copied through the still-live symlink (copy-through overwrite measured by the reviewer). Now: ENOENT is the only swallowed lstat outcome; unlink failure aborts with a named UnitPlacementError BEFORE any copy. New spec proves the residue target's bytes survive an unlink failure and the destination link is untouched. F3 — observeBroker defaulted unit/socket to false when seams unset, and production injects none: plan/status/doctor reported a healthy broker as absent. Seams still take precedence; with no seam the real stat() probes run. The v2 start path (and apply-with-running) now re-check the socket after enable+start with a NAMED lifecycle-precondition-failed refusal — previously only the v1 path had that protection, and the refusal was masked into the generic recoverable result. Acceptance fixtures gain hermetic brokerSocketEnv paths (the old fixture asserted the lying default). F4 (note) — unlink race stays inside the user-owned dir; no action. Local gates on this tree: vitest 1566/1566, typecheck, lint, prettier 3.8.1, verify-sanitized all pass. CI 2468's sanitization failure did not reproduce locally on the identical tree; watching the fresh pipeline.