5.2 KiB
5.2 KiB
FCM-M2-002 — Generation-Guarded Fleet Agent CRUD
- Task / issue: FCM-M2-002 / #758
- Branch / base:
feat/758-fleet-agent-crudfromorigin/main191efaefeb5c0c6bb218c1292d12ce8e73ace12b - Budget: 30K card allocation; no deployment or live-fleet actions.
Objective
Provide local roster-owned create, get, update, and delete mutations with a generation precondition, deterministic dry-run plan, complete-state structural/semantic/projection validation before writes, atomic roster persistence, and redacted recovery output on a late projection failure.
Scope and exclusions
- Roster v2 is the sole desired-state authority. Reuse
parseRosterV2,renderRosterV2Yaml,validateRosterV2Semantics, and the generated-environment boundary. - Fresh create defaults to
enabled: trueanddesired_state: stopped; this card never starts a runtime. - Excluded: reconcile/apply; lifecycle/session/systemd/tmux actions; migration/canary; remote/connector/gateway mutation; arbitrary commands/channels/secrets; generated files as authority;
docs/TASKS.mdand orchestration ledger changes.
Red-first plan
- Add failing tests for dry-run non-mutation, stale generation, concurrent writer locking, stopped default create, equivalent idempotency, complete proposed-state semantic/boundary validation, atomic roster write, and injected late projection failure with redacted recovery details.
- Implement only a roster-v2 CRUD service and file adapter; no legacy
fleet add/removebehavior expansion. - Add operator/reference docs for JSON outcomes, generation retries, recovery, and no-runtime-action boundary.
Progress
- Preflight: clean exact base and no duplicate PR confirmed.
- Intake read: FCM PRD/AC-FCM-03, task row, launch and generated-env boundaries, roster v2/resolver contracts, legacy fleet command behavior, delivery/QA/TypeScript/security/documentation guidance.
- TDD: RED observed for the missing CRUD module. GREEN: focused suite passes 7 tests covering stopped-default create, stale generation, idempotency, dry-run non-mutation, concurrent lock denial, exact stale/absent generated-projection delete cleanup, and redacted late-projection recovery.
- REVIEW-1 remediation: RED observed for absent CLI create/get/update/delete/plan wiring. Added roster-v2-only JSON commands, including safe
get, read-only planning/dry-run, explicit persisted-start recording (never runtime start), stable handled error codes, and focused CLI coverage. - REVIEW-2 remediation: RED observed for missing direct fleet-control-plane registration and ambiguous partial late-I/O result. The public surface is now direct
mosaic fleet {create,get,update,delete,plan}(not root gatewaymosaic agent); a late filesystem projection failure returns non-zero redacted JSON withauthoritativeRoster: committedandprojections: incomplete, proving no rollback/no-op claim. - REVIEW-3 remediation: RED observed for unnamed update/delete plans and deleted-agent quarantine conflict.
plan <operation> [name]now requires target names only for update/delete; delete validates/removes only exact generated state while retaining local/legacy/quarantine/unrelated files. Actual CLI/filesystem tests cover create/update/delete plans, plan validation/non-mutation, retained artifacts/dry-run bytes, unsafe permission/symlink rejection, and post-roster delete recovery. Added the required operator how-to. - REVIEW-4 remediation: RED observed that actual Commander create accepted and silently dropped disallowed
command,channel, andsecretRefkeys. The--agentobject and nestedlaunchnow use strict own-property allowlists; non-plain/prototype-sensitive shapes and unknown keys failinvalid-requestbefore resolver, roster, or projection mutation. Actual Commander plan/create/update tests cover top-level command/channel/secretRef/constructor/prototype/__proto__shapes and nested launch unknown fields, byte-identical retained artifacts, non-zero exit, and diagnostics that never echo rejected values. Docs state the same boundary.
Risks / assumptions
- ASSUMPTION: M2 mutations operate exclusively on the existing v2 roster contract because generation/lifecycle fields are v2-only; legacy v1 add/remove commands remain unchanged compatibility paths.
- A multi-file roster/projection write cannot be one filesystem rename. The roster is authoritative; a post-roster projection failure returns a redacted recovery plan naming only safe paths/actions, never environment values.
Verification evidence
pnpm --filter @mosaicstack/mosaic test -- fleet-agent-crud-command.spec.ts fleet-agent-crud.spec.ts generated-env-boundary.spec.ts— PASS (48 tests after REVIEW-4 remediation).pnpm --filter @mosaicstack/mosaic test— PASS (54 files, 794 tests after REVIEW-4 remediation).pnpm --filter @mosaicstack/mosaic lint— PASS.pnpm --filter @mosaicstack/mosaic typecheck— PASS.pnpm format:checkandgit diff --check— PASS.- Root
pnpm typecheck,pnpm lint,pnpm format:check, andgit diff --check— PASS after REVIEW-4 remediation; full package test is 54 files / 794 tests. - REVIEW-4 remediation focused checks are green; fresh full-delta independent review is required before author-green. No commit, push, or PR opened.