Files
stack/docs/fleet/reference/generated-env-boundary.md
Jarvis 18b7ab96e7
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
feat(fleet): enforce generated environment boundary
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 03:30:59 -05:00

7.6 KiB

Fleet Generated Environment Boundary

Card: FCM-M2-001 · Issue: #758 · Status: unreleased/card-local

The local fleet roster is the desired-state authority. A launch reads a deterministic, roster-derived generated projection and an optional strictly data-only local file; neither file is a second roster or a command configuration surface.

Paths and ownership

For agent <name> under <MOSAIC_HOME>/fleet/agents/:

Path Owner Purpose
<name>.env.generated Mosaic projection writer Complete deterministic launch data rendered from the authoritative roster.
<name>.env.local Operator Optional, constrained local machine data. It cannot shadow generated keys.
<name>.env Legacy input only Read once during projection generation, then regenerated/relocated or privately quarantined. It is never a launch authority.
<name>.env.quarantine Mosaic quarantine Mode-0600 private record of forbidden legacy input; it is never read by the launcher.

The systemd templates do not load either environment file. They invoke Bash with a fixed, cleared bootstrap environment; the launcher reads and validates .env.generated and .env.local itself before it queries, creates, or stops an exact tmux session. It does not source, eval, or execute an environment-supplied command. Exact stop derives its socket from the same validated generated projection, not from systemd or ambient environment data.

All projection, local, and quarantine files must be regular files with no group or world permissions. The agent environment directory must also be a real, non-symlink private directory; it is validated before either environment file is read or tmux is queried. Unsafe paths, symlinks, or permissions fail closed. Diagnostics identify only a rule code, key name, and SHA-256 content hash; they never print values, credential material, or command text.

Allowed data

.env.generated is complete and ordered exactly as follows:

MOSAIC_AGENT_NAME=<roster name>
MOSAIC_AGENT_CLASS=<roster class>
MOSAIC_AGENT_RUNTIME=<roster runtime>
MOSAIC_AGENT_MODEL=<roster model hint>
MOSAIC_AGENT_REASONING=<roster reasoning>
MOSAIC_AGENT_TOOL_POLICY=<roster tool policy>
MOSAIC_AGENT_WORKDIR=<absolute roster work directory>
MOSAIC_TMUX_SOCKET=<roster socket or empty>

The generated launch contract supports only claude, codex, opencode, and pi. fleet add uses that same runtime authority and rejects any other runtime before it writes the roster or changes projection, local, or quarantine files. The legacy dogfood stub on its separate mosaic-factory socket remains an observability canary; it has no generated-launch adapter and cannot be added through this projection path.

.env.local may contain only these non-secret data keys:

  • MOSAIC_RUNTIME_BIN
  • MOSAIC_HEARTBEAT_RUN_DIR
  • MOSAIC_HEARTBEAT_INTERVAL
  • MOSAIC_CLAUDE_JSON
  • CLAUDE_CONFIG_DIR

Local paths must be safe absolute paths and the interval must be a positive integer. Comments, quoted/export syntax, duplicate keys, unknown keys, generated-key shadowing, sensitive key names, and MOSAIC_AGENT_COMMAND are rejected. The launcher derives the only executable command from the validated runtime, model, and reasoning data; no arbitrary command compatibility path exists. When a Pi runtime writes a fresh <name>.hb.native marker, its native heartbeat remains authoritative; the shell sidecar resumes its status=ok fallback only after that marker is stale or absent.

Legacy disposition

During projection generation, legacy roster-derived keys are regenerated from the roster. A valid allowed local value is relocated to .env.local; forbidden, malformed, duplicate, sensitive, and unknown legacy entries cause the legacy file to be moved to .env.quarantine and are represented by sanitized diagnostics. This is deterministic and idempotent after the legacy file has been consumed.

USC interface packet

This card does not add a USC site file, write a USC roster, or run a site canary. The following is the consolidated downstream interface packet. Status is deliberately separated from checkout presence: no product release version has been evidenced for this interface set.

Interface Canonical public path and version Tracker/release status Downstream limit
M1 structural compiler parseRosterV2 in packages/mosaic/src/fleet/roster-v2.ts; schema docs/fleet/reference/roster-v2.schema.json; roster version: 2 FCM-M1-001 is recorded done, merged as #764 (aa5b43b); no released product version is asserted here. Parse YAML/JSON and canonicalize a supplied v2 site roster without writes.
M1 semantic resolver validateRosterV2Semantics in packages/mosaic/src/fleet/roster-v2.ts; baseline framework/fleet/roles/ plus roles.local/ FCM-M1-002 remains in-progress in docs/TASKS.md; unreleased. Reuse the shared resolver only; no parallel role resolver or lifecycle action.
M1 disposition evidence packages/mosaic/src/fleet/example-profile-dispositions.ts; docs/fleet/migration/example-profile-disposition.md; retained fixture version: 1 FCM-M1-003 remains not-started in docs/TASKS.md; unreleased even though these checkout artifacts are inspectable. Inspect fixture/profile/service disposition evidence only; it is not migration authorization.
M2 generated boundary packages/mosaic/src/fleet/generated-env-boundary.ts; generated projection contract in this document FCM-M2-001 card-local and uncommitted; unreleased. Render/write a roster-derived projection; local input is never authority.

The canonical source remains <MOSAIC_HOME>/fleet/roster.yaml for the current local fleet path. Generated environment data is a rebuildable projection, not an operator-editable source of membership, runtime policy, or lifecycle state.

Corrected downstream gates: M2 supplies only parse/validation/projection evidence and does not permit a USC site canary, reconciliation, or lifecycle mutation. M3 must first define and validate the canonical local reconcile/lifecycle path. M4 then supplies preview/migration and its separate canary/rollback gates; only after those M3 and M4 gates may a site migration or canary be considered. This card authorizes none of those actions.