LearnNewsExamplesServices
Frontmatter
id16735
titleFleet control service joins the composition — optional fleet-server (Fleet-owned root + registered projections)
stateClosed
labels
enhancementaiarchitecture
assigneesneo-gpt
createdAtAug 8, 2026, 9:56 PM
updatedAtAug 9, 2026, 2:59 AM
githubUrlhttps://github.com/neomjs/neo/issues/16735
authorneo-fable-clio
commentsCount5
parentIssue16168
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 16715 Fleet workspace preparation: split pure plan from host-owned apply effects
blocking[ ] 16746 Harness demotion — dissolve loadFleetRuntimeContracts; FM stops supervising the organism
closedAtAug 9, 2026, 2:59 AM
milestonev13.2

Fleet control service joins the composition — optional fleet-server (Fleet-owned root + registered projections)

Closed Backlog/active-chunk-14 enhancementaiarchitecture
neo-fable-clio
neo-fable-clio commented on Aug 8, 2026, 9:56 PM

Graduated from D#16720 (FM client-side migration delta, body v12 @ 2026-08-08T19:52:47Z; final family-keyed quorum: fable AUTHOR_SIGNAL + APPROVED · Opus APPROVED (re-stamped, blockers verified closed) · GPT [GRADUATION_APPROVED] @ v12, findings closed + defer-closed at filed state). Matrix Option A — the #16176-inherited phase-2 selection, confirmed by the day's live receipts.

Context

The cockpit's fleet truth must be served from where the data lives. Today the shell spawns a host-side devFleetServer (ai/services/fleet/devFleetServer.mjs) that resolves ONE viewer at process boot and reads a host registry which does not exist post-hard-cut (root-cause receipt on #16699); fleetBridgeServer.mjs stamps that boot-bound viewer on every request behind one ephemeral local bearer. The composition (ai/deploy/docker-compose.local-agent-os.yml) carries chroma/kb/mc/orchestrator/ingress — no fleet service.

This is an auth/identity boundary change, not a Compose-only relocation (intake falsifier 1, 2026-08-08): GitHub PATs admitted by AuthService are not accepted by the current Fleet guard; the current server cannot simply become the image entrypoint.

Scope

Add the OPTIONAL fleet-server compose service: the same AuthService seat kb/mc occupy, serving the fleet wire from inside the composition — with a request-time identity boundary replacing the boot-bound viewer.

Contract Ledger

Target surface Authority (current) Pinned behavior (this leaf) Fail-closed / fallback Docs consumer Evidence
fleet-server service + profile ai/deploy/docker-compose.yml + docker-compose.local-agent-os.yml layering (base/local); no fleet service today EXTEND the existing base/local layering — no seventh bespoke composition file. Local Agent OS + downloadable FM profile REQUIRE the service (fresh install renders a live plane-owned roster); headless cloud omits it. Ingress must NOT hard-depend on fleet-server: a Fleet-less headless profile stays valid. Absent service ⇒ cockpit shows the topology-aware disconnected banner (#16721 vocabulary), never a crash. Deployment runbook + FM install guide Rendered docker compose config witness for BOTH profiles (with + without service)
Fleet HTTP entrypoint devFleetServer.mjs (one viewer at boot) + fleetBridgeServer.mjs (ephemeral local bearer stamping that viewer per request); current AuthService PAT verification emits provider-validated facts; no ownerPrincipal field exists anywhere today Request-time AuthService admission (same seat kb/mc occupy) → an immutable per-request context carrying the provider-validated AuthInfo facts emitted by AuthService (authProvider, providerBaseUrl, providerUserId, display login); no ownerPrincipal exists in S1 — its derivation/normalization stays S2 #16736 + S4 #16738 authority. Boundary: S1 composes the generic AuthService-backed HTTP entrypoint, exact routes, storage root, and read-only/probe surface; S2 owns the Fleet-specific forge-mode/admission policy and stable-principal subject semantics. NO boot-bound viewer in the composed entrypoint. Unadmitted request ⇒ refused with explicit auth error; no anonymous fallback identity; every principal-bound verb fails closed with the declared degraded: awaiting-<slice> marker until S2 + S4 land. ADR carrier #16747 (pure-client topology) Auth witness (S1-bounded): PAT admitted / anonymous refused / served request-identity facts match the provider-validated AuthInfo; stable-principal equality becomes S2/S4 evidence
/fleet + /fleet/probe routes ai/deploy/Caddyfile.local-agent-os (local: loopback HTTP) + ai/deploy/Caddyfile (cloud: TLS-terminating) — the wire exact-matches /fleet and /fleet/probe Public path = upstream path, EXACT match (no handle_path prefix-strip — it would miss both routes). Identity-header stripping at ingress per the canonical kb/mc pattern; Host/CORS policy identical to the kb/mc routes. Local = loopback HTTP; cloud = Caddy-terminated TLS (the graduated body's "TLS pass-through" wording is RETIRED — not the canonical pattern). Route absent (headless) ⇒ 404 from ingress; no fleet leak. Deployment runbook Caddy route witness in both profiles; probe reachable only authenticated
Fleet data root No declarative member exists today; registry/tenant default checkout-relative .neo-ai-data/fleet (intake falsifier 2) NEW declarative AiConfig.fleet.dataDir leaf per ADR 0019: leaf(default, env, type) — entrypoint-fixed, read at the use site; explicit planeMember decision per ADR 0019 §10.5 (an anchored leaf with no decision fails closed); ONE Fleet-owned named volume covering keys + ciphertext CO-LOCATED. No use-site env re-derivation, no runtime mutation, no defensive ?.. Missing/unplaced root ⇒ boot refusal (member-coherence walk), never a silent checkout-relative fallback. ADR 0019 + #16747 Persistence witness: volume survives container recreation; boot-refusal witness on unplaced root
S1 wire availability n/a (new service); ADR 0038 §2.2 fact 3 binds: roster visibility is DEFAULT-PRIVATE, never inferred from authentication or team membership S1 serves EXACTLY the authenticated identity-bearing /fleet/probe. ALL owner-scoped Fleet-state reads — roster (listAgents/getAgent) AND the tenant registry (listTenants) — are principal-bound by construction (ADR 0038 §2.2 fact 2: Fleet state is ownerPrincipal-owned) and FAIL CLOSED until their named slices land: S4 #16738 (principal) + S5 #16739 (CAN_OBSERVE_FLEET_OF enforcement) + S3 #16737 (viewer-scoped projection). Auth-only visibility is FORBIDDEN, not deferred — serving the whole roster behind bare admission would implement the inference the ADR bans. Principal-bound WRITES (grants, roster-projection writes, lifecycle mutation) identically fail closed (S2 #16736 · S4 · S5). The implementing PR carries the exact verb table; this leaf pins the CLASS split. Refused verb ⇒ explicit degraded: awaiting-<slice> marker, never a partial success and never an auth-only fallback view. Cockpit connection-truth surface (#16721) + ADR 0038 §2.2 Wire witness: probe succeeds authenticated; roster/tenant/principal-bound verbs return the declared refusal — a witness asserting listAgents succeeds behind bare auth is itself the defect
Health / readiness Composition's node-service healthcheck discipline (kb/mc); the existing helper is MCP-specific (intake falsifier 4) Readiness = authenticated identity-bearing probe proving AuthService admission + served identity + fixed Fleet root — NOT a bare TCP-listener check. Failing probe ⇒ compose-unhealthy; dependent tooling sees it. Deployment runbook Healthcheck witness in rendered compose + live probe receipt
Storage boundary (the STEP_BACK ✗ repair, binding) #16176 Diamond-1 Option A (selected); the shared-volume facade is its REJECTED Option B The service owns a Fleet-owned entrypoint-fixed durable root — scoped to what S1 actually owns: registry, tenant, key material. Grants-ledger durability = S6 #16740; audit + lifecycle durable stores = their named later slices. S1 creates NONE of those stores. Graph/mailbox/roster facts cross authenticated registered projections / service APIs — NEVER a mount or schema-read of another service's private storage. Cross-plane read without a registered projection ⇒ architectural rejection at review. #16168 (parent) + #16747 Review-gate + projection-only wire witness

Acceptance Criteria

  • Optional fleet-server service lands by EXTENDING base/local compose + Caddy layering (both profiles render; no new composition file), with exact-match /fleet + /fleet/probe routes and kb/mc-identical header/Host/CORS policy.
  • Request-time AuthService admission with an immutable per-request context of provider-validated AuthInfo facts — no ownerPrincipal in S1 (derivation/normalization stays S2 #16736 + S4 #16738; principal-bound verbs fail closed with the declared degraded marker); the boot-bound viewer is retired from the composed path.
  • AiConfig.fleet.dataDir declarative leaf (ADR 0019-conform, explicit planeMember decision) + ONE Fleet-owned named volume (keys + ciphertext co-located); container runs against container-internal data roots with no host checkout (the Matrix-A falsifier).
  • S1 availability contract implemented as pinned: EXACTLY the authenticated identity-bearing probe is S1-valid; roster (listAgents/getAgent), tenant-registry (listTenants), and all principal-bound verbs fail closed with explicit degraded markers until S3/S4/S5 land — auth-only visibility forbidden per ADR 0038 §2.2.
  • Health/readiness = the authenticated identity-bearing probe (admission + served identity + fixed root).
  • Evidence set: rendered compose/profile witness, persistence/recreation witness, auth/identity witness, wire-availability witness — each bounded to this phase.

Sequencing

  • #16715 / PR #16731 (pure plan / host apply split): DISCHARGED — merged 2026-08-08 (10591e80e5).
  • Merge-order dependency: #16747 (ADR carrier amending ADR 0020/0026, recording the pure-client topology). The ADR lands first or in the same window; this leaf cites it — D1 wants early authoring for exactly this reason.
  • Blocked by: none — claimable after revalidation of this repaired body.

Signal Ledger

Family-keyed at D#16720 final filed state: fable AUTHOR_SIGNAL + APPROVED (re-bound) · Opus APPROVED (re-stamped, both blockers verified closed at source) · GPT [GRADUATION_APPROVED] @ body-19:52:47Z (findings closed at v12; defer-closed 20:06Z; filed C5 graph verified). Full ledger: D#16720 closing comment. (Supersedes the filing-time "GPT re-stamp pending" prose — the re-stamp landed.)

Unresolved Dissent

None open. The v9-anchor GPT DEFERRED (parent-authority collision) was repaired in v11 and closed by the v12 [GRADUATION_APPROVED] + defer-closed receipts.

Unresolved Liveness

@neo-gemini-pro benched. Kimi engaged (falsifier cycles / seat witness) without final-anchor signal — recorded, never implied consent.

Discussion Criteria Mapping

D#16720 criteria (1)–(9): see the closing comment's receipts. Intake alignment (this body v2): the [ARCH_ALIGNMENT] comment of 2026-08-08T20:59Z — all six ledger rows adopted; falsifiers 1–5 addressed in place.

Intake alignment (v3): the [REVALIDATION] comment of 2026-08-08T21:4xZ — the ownerPrincipal sequencing contradiction repaired per its four exact points (S1 = provider-validated AuthInfo facts; principal derivation = S2/S4; boundary sentence; S1-bounded auth witness). Truth-fold (v4, 2026-08-09): the S1 ready-read row narrowed per the PR #16761 review's authority delta — probe-only S1; roster + tenant-registry reads classified owner-scoped and fail-closed to S3/S4/S5; auth-only visibility named FORBIDDEN per ADR 0038 §2.2 fact 3 (default-private is accepted authority, not a preference).

Origin: D#16720 · Body v4 (contract-aligned 2026-08-08; visibility truth-fold 2026-08-09) · Retrieval Hint: "fleet-server compose service optional AuthService seat provider-validated AuthInfo Fleet-owned durable root registered projections"

tobiu referenced in commit 92c0a49 - "feat(fleet): compose authenticated Fleet service (#16735) (#16761) on Aug 9, 2026, 2:59 AM
tobiu closed this issue on Aug 9, 2026, 2:59 AM