Files
stack/docs/DEVELOPER-GUIDE/architecture/fleet-first-start-identity.md
T
2026-08-16 18:33:39 -05:00

4.0 KiB

Fleet First-Start Identity Boundary

Status: Implemented by issue #1264. Requirements: FCM-REQ-12, AC-FCM-10.

Problem

launchRuntime() called checkSoul() before runtime execution. A missing top-level SOUL.md caused checkSoul() to spawn a child mosaic wizard with inherited stdio. Under a systemd-created fleet pane with no TTY, that child blocked or failed before the runtime boundary even though generic defaults/SOUL.md and defaults/USER.md already shipped in the same MOSAIC_HOME.

Chosen boundary

The fix remains at checkSoul() and does not add flags to yolo, fleet commands, systemd units, or start-agent-session.sh:

  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, 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.
  7. Temporary files are removed, and both installed contracts are re-opened through the no-symlink secure-file reader before launch continues.
  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.

Identity and authority

The copied defaults deliberately say “Mosaic agent”; they are a generic behavioral base. They are not the source of a fleet seat's identity. The canonical roster controls:

  • exact agent/session name;
  • canonical role/class and persona;
  • peer rows and point of contact;
  • tmux socket and helper target; and
  • communications generation.

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; 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.
  • All required source snapshots are validated before the first destination is published, preventing a missing second default from leaving a partial seed.
  • Existing operator files are never chmodded or rewritten.

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. 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.

Non-goals

  • Runtime installation or pane-PATH resolution (#1256/#1258).
  • The held ~/.mosaic launch-composition layer in PR #1213.
  • Personalizing the operator's standalone identity without a wizard.
  • Changing fleet systemd or shell launcher code.