LearnNewsExamplesServices
Frontmatter
id17281
title`devFleetServer` ignores `fleet.planeBearerFile` and then refuses plane mode with the wrong remediation
stateClosed
labels
bugai
assigneesneo-kimi-iris
createdAtAug 17, 2026, 10:04 AM
updatedAtAug 17, 2026, 10:44 AM
githubUrlhttps://github.com/neomjs/neo/issues/17281
authorneo-kimi-iris
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 17, 2026, 10:44 AM

devFleetServer ignores fleet.planeBearerFile and then refuses plane mode with the wrong remediation

neo-kimi-iris
neo-kimi-iris commented on Aug 17, 2026, 10:04 AM

devFleetServer ignores fleet.planeBearerFile and then refuses plane mode with the wrong remediation

Context

Found during the #17271 intake (recorded there as adjacent debt). The fleet.planeBearer leaf's own JSDoc (ai/configBase.mjs) promises the two-home custody split — direct value wins, else NEO_FLEET_PLANE_BEARER_FILE names a secret file, "Read at the use site by the Fleet entry, never at import." The composed Fleet server honors it through resolveFleetPlaneBearer (ai/services/fleet/fleetServer.mjs:640). The DEV entry does not: devFleetServer.mjs constructs the plane mailbox client with credential: AiConfig.fleet.planeBearer — the direct leaf only.

The Problem

A deployment on the file custody class (the canonical Compose shape — "env literals are the wrong custody class for credentials", per the leaf's own comment) boots npm run ai:fleet-server or npm run cockpit with NEO_FLEET_PLANE_BEARER_FILE set and the direct value empty. The dev entry reads the empty direct leaf, the plane client sends no Authorization header, plane admission refuses, and the boot dies with fix fleet.planeBase / fleet.planeBearer — a remediation that names the WRONG fix while the configured file sits unread. The file indirection the leaf documents is silently inert on the dev journey.

The Architectural Reality

  • devFleetServer.mjs already imports from fleetServer.mjs (assertFleetPlaneAdmissionBearerClass, assertFleetViewerMcAuthorizationClass) — the resolver sits beside them, so the fix is an import + a swap, zero new machinery.
  • resolveFleetPlaneBearer({aiConfig}) is the sanctioned use-site read (ADR-0019): direct wins, else the file, else '' — and the dev entry's existing empty-credential behavior (tokenless planes decide admission themselves) is preserved by the '' fall-through.
  • The wake-stream admission credential (assertFleetPlaneAdmissionBearerClass) already resolves both homes via resolveFleetPlaneAdmissionBearer — only the MCP mailbox credential has the gap.

The Fix

devFleetServer.mjs builds the plane client credential through resolveFleetPlaneBearer() instead of reading the direct leaf. Unit witness: a FILE-only boot resolves the file's value into the client credential (the resolver's injection seam keeps the spec hermetic); the direct-wins precedence is pinned against regression.

Decision Record impact

aligned-with ADR 0019 — completes the leaf's documented contract at the dev entry; no new leaves, no re-derivation (the resolver IS the use-site read).

Acceptance Criteria

  • A NEO_FLEET_PLANE_BEARER_FILE-only boot of the dev fleet entry resolves the file's value as the plane credential (witnessed).
  • Direct value still wins when both homes are set (witnessed).
  • Neither home set preserves the current empty-credential path (no behavior change for tokenless/in-process journeys).
  • A live FILE-only plane boot binds the mailbox/compose/catch-up seams plane-side (evidence run on the canonical local plane).

Out of Scope

The launcher-side file materialization shipped in #17276 stays as-is (it materializes the file into the child's direct env — compatible with this fix, and the launcher's custody story remains its own) · the admission-bearer and viewer-MC chains (already two-home).

Related

#17271 (the intake that surfaced it) · #17276 / PR #17277 (the journey whose launcher papers over it for the composed path) · ADR-0019.

Live latest-open sweep: latest 20 open checked 2026-08-17T08:05Z, no equivalent; A2A herd-window sweep clean.

Origin Session ID: 0c5a1cf3-093b-4e9d-a7ba-74137e4d4f23

Retrieval Hint: query_raw_memories("devFleetServer planeBearerFile file custody resolveFleetPlaneBearer misleading refusal")

tobiu referenced in commit 2f09831 - "fix(fleet): devFleetServer resolves the plane bearer from both declared homes (#17281) (#17282)" on Aug 17, 2026, 10:44 AM
tobiu closed this issue on Aug 17, 2026, 10:44 AM