11 KiB
11 KiB
#1050 — Installer P0–P9 state machine and red-first fixture
Objective
Implement C1 from the canonical greenfield-install PRD v2: a transactional P0–P9 installer spine, a side-effect-free P0–P8 --check, and a lane-parametric Debian/glibc non-root from-zero fixture. The acceptance milestone is an attributable RED on the pre-C1 installer while preserving P3 PASS.
Authority and scope
- Canonical requirements:
jason.woltje/jarvis-braindocs/plans/2026-08-04-greenfield-install-blockers-PRD-v2.md. Currency was re-derived after compaction: authenticated fetch resolvedorigin/maintocb23e5fbc8a282fa967b93d7a134fa48d11b4bb1; the PRD and charters are byte-identical to the previously read remote copies. - Tracking:
mosaicstack/stack#1050ongit.mosaicstack.dev(author read back asbe-coder-05). - Historical implementation base:
origin/next4df478cdd150fdf8d52ea109f02ade5d85017acd. Delivery PR #1054 targetsmainunder L0's trunk-only rule;nextremains a non-merging integration lane. - Out of scope: PATH, skills, headless wizard/identity, activation remediation, #869 wiring, RM-02, main promotion.
docs/TASKS.mdis orchestrator-single-writer and is not modified by this worker.
Plan
- Pre-register the canonical phase/output/side-effect-free/fault-injection checks and observe RED against the base installer.
- Commit the immutable red-first acceptance fixture before implementation.
- Add the state-machine/journal/postcondition spine without repairing P4/P5/P8 symptoms.
- Wire the expected-RED from-zero fixture into Woodpecker using Debian/glibc and a non-root target user.
- Run shell/static baselines, situational container validation, code review, security review, then deliver through a PR to
nextunder the coordinator-owned merge path.
Budget
- Working estimate: 32K reasoning/output tokens.
- Hard external cap: none stated.
- Adaptation: keep implementation in shell surfaces already in scope; no package dependency install unless repository gates require it.
Pre-registered acceptance checks
| ID | Exact case | Expected pre-fix result |
|---|---|---|
| C1-R1 | tools/e2e-install-test.sh --lane next in a clean Debian 12 container as uid 1001 |
non-zero; P3 PASS; P4 NOT-MEASURED / UNDECLARED; P5/P6/P8 FAIL with own reasons |
| C1-R2 | tools/install-state-machine.test.sh phase table case |
RED because base installer does not enumerate canonical P0–P9 contracts |
| C1-R3 | side-effect-free --check case over a fingerprinted HOME |
RED because base --check is version-only rather than P0–P8 predicates |
| C1-R4 | fault injection after each P2…P8 | RED because base installer has no injectable durable journal/rollback state |
| C1-R5 | Docker unavailable | base harness incorrectly exits 0; replacement must fail non-zero |
| C1-R6 | lane resolution | bare checkout is forbidden; fixture must pass --next and assert the resolved prerelease version |
| C1-R7 | same Debian fixture with git absent vs present |
absent: P1 FAIL while legacy installer exits 0 and sync degrades; present: P1 PASS and observed store/runtime containment 101/101 |
Progress
- Charter, doctrine, delivery/CI/QA/docs guides read and re-anchored after compaction.
- Canonical PRD v2/v3 addenda and charters read from fetched
origin/main; numbering reconciles with the TL spec. No numbering conflict found. INV-B/C/D are binding and implemented without renumbering. - Target base reachability verified with
merge-base --is-ancestor. - Issue #1050 created and provider author read back.
- Initial RED captured; TL rejected P4's repo-root count as a false RED. Four populations disagree (framework payload 1, repo root 13, sync store 101 in the fixture, W-jarvis observation 7), so C1 now requires a checkout-free declared shipped-set artifact and reports P4
NOT-MEASURED / UNDECLAREDuntil C5 supplies it. - P6 strengthens #869: the two dead enforcement hooks reproduce from zero on a clean broker-less container. C1 asserts the breach but neither wires nor unwires it.
- P1 false pass identified from the P4 evidence row:
gitis absent from the Debian base and was undeclared even though skill sync shells out to it. C1 addsgitto P1; the fixture matrix preserves absent/present controls. The prior claim that web1's missing runtime skills reproduce this greenfield mechanism is withdrawn by the TL and is not carried here. - Corrected RED transcript captured and reported, including the git-present/absent controls and strict P3 PASS.
- State-machine implementation complete: private pre-mutation journal/snapshot, P0–P8
--check, P2–P8 fault seam, rollback, durable manifest/journal seal, action-status persistence, safe rollback roots, and stale-projection recovery. - Debian/glibc checkout fixture now packages the complete current checkout, verifies its digest in-container, and reaches the expected attributable RED without host inheritance. CI compares its exact final phase map/reasons to
tools/fixtures/greenfield-expected-red.tsv; the fixture remains red while the detector job is green only on an exact match. - Reviews complete. Reviews 80 (
rev-security-02) and 81 (rev-974) requested changes at3934e03f; their eight non-overlapping detector findings are being remediated red-first. Current remediation adds canonical-image portability, absolute P3 CLI propagation, exact expected-RED schema/cardinality, passwd-HOME binding, created-path owner/mode policy, real-action P2–P8 fault injection, verified non-empty remote installer execution, and seeded secret-canary/redacted diagnostics. Both old verdicts become void when the remediation head moves and require fresh independent review.
Risks / blockers
- The deployed create wrappers do not expose
--dry-run; identity preflight was performed throughpr-merge.sh --dry-runon the same HOMELAB repo, which resolvedgit.mosaicstack.dev+be-coder-05. The issue create then fell back from tea to the API but provider read-back confirmed authorbe-coder-05. nextis a non-merging integration lane; PR #1054 targetsmain. The old “pending promotion to main” caution dissolved when the base moved. #1050 remains open after merge and closes only after Jarvis validates the greenfield behavior.- #869 must remain staged and inactive.
- Late sequencing input MB-BRAIN-01 is accommodated without implementation or renumbering: P2 covers installer distribution only; P5 owns requested credential capability; P7 leaves an ordered seam for credential-dependent resource provisioning after P5.
Remediation review controls
- B1 RED: the next-lane harness failed immediately under
ci-base:latestas root/musl; it now models uid 1001/glibc explicitly and uses Python tree fingerprints instead of GNUfind -printf. - B2 RED: framework/runtime linking consumed bare
mosaicfrom PATH after P3 had committed an absolute path. The unified installer now exports/passesMOSAIC_CLI_PATH; the linker invokes that absolute artifact, and wizard auto-launch has no stale-PATH fallback. - B3 RED: a one-row manifest (
exit=1) certified any exit-1 log. Full-manifest validation now requires the exact three cases, one exit and P0–P9 row each, pinned require/forbid populations, and rejects malformed/duplicate/unknown rows; shrink is a negative control. - B4 RED: uid 1001 with a passwd HOME different from ambient HOME produced P0 PASS. P0 now binds uid, username, passwd HOME and shell and explicitly rejects root and sudo-with-inherited-HOME controls.
- B5 RED: mode-0777 CLI, mode-0644 identity, and mode-0755 credential storage passed. P3/P4/P5 now apply target owner/group plus executable/shared/private policies; framework credential storage is created 0700.
- B6 RED: fault injection only wrote
.selftest-*files. The synthetic path was removed; the P2–P8 matrix enters the normal action flow, proves an action observation occurred, injects after each real phase, and fingerprints rollback. - B7 RED: an HTTP-200 empty body exits zero when piped to Bash. The fetched installer must now be non-empty, digest-equal to
tools/install.sh.sha256, and that exact file is executed; failed/empty/mismatch controls are blocking and CI has a remote immutable-commit arm. - B8 RED: raw combined command output was duplicated to terminal and
commands.log. Both capture layers now redact before output/persistence; a seeded canary is positively emitted by the fake credential-capable registry and must remain absent from terminal, command log, npmrc, generated files and observed argv. The real greenfield fixture also scans those populations. - Advisory code review findings are fixed: URL userinfo redaction now handles raw
@, repeated:, percent encoding and multiple URLs in both capture layers; the real greenfield path positively emits its canary throughstate_run_captured; and verified-fetch removes its temporary body after successful execution. - Advisory security review's independent trust-root finding is DEFERRED by canonical PRD v2 §3, which explicitly excludes signed provenance. README now states precisely that the same-origin sidecar detects empty/corrupt/inconsistent publication but cannot authenticate against repository/server compromise; no stronger claim remains.
- The web1 no-manifest representativeness observation is recorded but intentionally not acted on: it is explicitly outside these eight blockers. This remediation does not weaken or otherwise change P9's manifest-presence assertion.
Verification log
bash -nand ShellCheck pass for all changed shell surfaces;git diff --checkpasses.bash tools/install-state-machine.test.shpasses, including exact P0–P8 rows, passwd-HOME/privilege discrimination, owner/group/mode attacks, persisted P4/P6 action failures, no synthetic fault implementation, unsafe/overlapping/symlink roots, and fatal journal initialization.bash tools/install-next-lane.test.shpasses insideci-base:latest, including exact@nextversions, immutable source fallback, source-build/archive-failure rollback, offline--dev, explicit refs, prerelease suffix mismatch, absolute P3 CLI propagation, secret redaction, real-action P2–P8 rollback, and stale projection recovery.- Comparator controls pass for verdict drift, unexpected exit, manifest shrink, missing phases, duplicate rows, unknown cases, and unknown kinds. Verified-fetch controls pass for successful execution and failed/empty/digest-mismatch rejection.
bash tools/e2e-install-test.sh --lane next --source checkout --git presentreturns the required expected RED in clean Debian/glibc as uid 1001: installer P0/P1/P2/P3/P7 PASS; P4/P5/P6/P8 and P9 blocking; noDone.claim; checkout archive digest pinned and current framework installer exercised.tools/verify-greenfield-expected-red.shconverts that expected detector result into a green CI assertion and fails on any unreviewed verdict drift.- Earlier repository gates passed:
pnpm typecheck,pnpm lint,pnpm format:check, upgrade manifest/rollback/durable-snapshot/migration suites, and focused@mosaicstack/mosaictests with an isolated npm prefix. Full exact-remediation rerun is required before push.