fix(#1264): harden unattended identity bootstrap
ci/woodpecker/pr/ci Pipeline failed

This commit is contained in:
goals
2026-08-16 18:33:39 -05:00
parent 43fa047787
commit 9dc90be7e1
14 changed files with 448 additions and 288 deletions
@@ -14,17 +14,20 @@ fleet pane with no TTY, that child blocked or failed before the runtime boundary
The fix remains at `checkSoul()` and does not add flags to `yolo`, fleet commands, systemd units, or
`start-agent-session.sh`:
1. A nonblank `MOSAIC_AGENT_NAME` selects the fleet path.
1. A present, nonblank, whitespace-exact `MOSAIC_AGENT_NAME` selects the fleet path.
2. `resolveFleetIdentity()` must resolve that exact member through the existing roster/helper
boundary before any identity seed.
3. Safe bounded snapshots are read from only the missing contracts under `defaults/`.
4. Each snapshot is written to a random owner-private temporary file in `MOSAIC_HOME`.
5. `linkSync()` publishes the complete file without overwriting an existing path. `EEXIST` means a
boundary, and any ambient `MOSAIC_AGENT_CLASS` must canonicalize to the roster class, before any
identity seed.
3. `lstatSync()` preflights every destination directory entry without following links, so a dangling
link is rejected before its counterpart can be published.
4. Safe bounded snapshots are read from only the missing contracts under `defaults/`.
5. Each snapshot is written to a random owner-private temporary file in `MOSAIC_HOME`.
6. `linkSync()` publishes the complete file without overwriting an existing path. `EEXIST` means a
concurrent seat or operator won; the existing path is preserved and revalidated.
6. Temporary files are removed, and both installed contracts are re-opened through the no-symlink
7. Temporary files are removed, and both installed contracts are re-opened through the no-symlink
secure-file reader before launch continues.
7. `composeContract()` independently re-resolves the roster and injects exact member identity and
communications data.
8. `composeContract()` independently re-resolves the roster, securely reads `USER.md` through a
descriptor at the point of use, and injects exact member identity and communications data.
A standalone launch with no `MOSAIC_AGENT_NAME` retains the interactive wizard.
@@ -39,13 +42,14 @@ not the source of a fleet seat's identity. The canonical roster controls:
- tmux socket and helper target; and
- communications generation.
An unknown ambient name fails before any file is seeded. This avoids replacing the interactive wall
with a fleet of indistinguishable or ambiently invented identities.
An unknown/padded ambient name or mismatched ambient class fails before any file is seeded. This
avoids replacing the interactive wall with a fleet of indistinguishable or ambiently invented
identities.
## Concurrency and filesystem properties
- Sources and final destinations are bounded regular files beneath `MOSAIC_HOME`; symlinks are not
followed.
- Sources and final destinations are bounded regular files beneath `MOSAIC_HOME`; target and dangling
symlinks are not followed.
- New files have mode `0600`.
- Hard-link publication is same-filesystem, atomic, and no-clobber.
- A temporary path is removed only when this process successfully created it.
@@ -56,9 +60,12 @@ with a fleet of indistinguishable or ambiently invented identities.
## Verification
`src/commands/launch-first-start.spec.ts` uses the production-kind boundary: the real built CLI in a
no-TTY subprocess, not a direct wizard test. A fake lease launcher records whether execution reached
the runtime boundary and captures the composed prompt. Positive and negative cases prove the check
can both proceed and refuse.
no-TTY subprocess, not a direct wizard test. The package `test:vitest` gate builds Mosaic before
Vitest, while the clean-checkout command builds its workspace dependencies first, so ignored
`dist/cli.js` cannot be absent or stale. A fake lease launcher records whether execution reached the
runtime boundary and captures the composed prompt.
Positive and negative cases prove the check can both proceed and refuse. Composition coverage also
replaces a previously validated `USER.md` with an external symlink and proves point-of-use refusal.
Real Pi authentication and provider task execution remain environment tests, not claims of this
fixture.