LearnNewsExamplesServices
Frontmatter
id14574
titleRemote-tenant connect: tenant URL + PAT → remote MC/KB
stateOpen
labels
enhancementaiarchitecture
assignees[]
createdAtJul 4, 2026, 3:25 AM
updatedAt4:59 AM
githubUrlhttps://github.com/neomjs/neo/issues/14574
authorneo-opus-ada
commentsCount1
parentIssue13015
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Remote-tenant connect: tenant URL + PAT → remote MC/KB

Open Backlog/active-chunk-2 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on Jul 4, 2026, 3:25 AM

Context

The Fleet Manager's local-first path (define agents → start → observe on this machine) is the operator's own workflow — but the design-partner cohort's actual entry is different: they connect to a remote Agent-OS tenant (hosted Memory-Core + Knowledge-Base) rather than stand up the full stack locally. #13015's MVP names this a first-class entry — "remote-tenant connection (tenant URL + PAT → remote MC/KB — the design-partner cohort's actual journey)" — and the cockpit direction (apps/agentos/design/fleet-manager-cockpit-plan.html, Lane D3) carries it. It is currently undecomposed: the local-fleet leaves shipped (registry/lifecycle/provisioning); the connect-to-a-remote-tenant entry has no leaf.

The Problem

A design partner evaluating Neo should not have to stand up the whole Agent OS to try it. The low-friction entry is: point the cockpit at a hosted tenant (a URL + a PAT) and drive it. Without this leaf the FM manages only a local fleet, so the revenue-relevant design-partner journey has no product surface. This is an adoption-wall leaf: the sellable "connect and go" story rides on it.

The Architectural Reality

  • Two-hemisphere boundary is the design rule (inherited from #13015): the tenant PAT is a secret — stored/used Node-side (Brain), never transits the browser. The PAT rides in through the connect call and authenticates MC/KB transport; it never comes back out.
  • Consumes existing tenant substrate: ai/services/knowledge-base/ + ai/services/memory-core/ already speak remote (the cloud-tenant deployment class + ingestTenant.mjs KB path exist). This leaf is the cockpit-reachable connect surface over that substrate, not new transport.
  • Wire surface: a connect verb on FleetControlBridge + FLEET_WIRE_METHODS (src/ai/fleet/fleetWireMethods.mjs), dispatched fail-closed via dispatchFleetRequest — the same pattern the local control verbs use. The result is a public tenant descriptor (endpoint + status), never the PAT.
  • deploymentClass interplay (#14456): connecting to a cloud-tenant implies the propose-only / isolation-by-default posture that sandbox names; this leaf records the class it establishes.

The Fix

  • Add a connectTenant control verb (single-params: {tenantUrl, credential}) to FleetControlBridge; add to FLEET_WIRE_METHODS + the browser-side bridge; dispatch fail-closed. Credential held Node-side; return {endpoint, status, deploymentClass} (no PAT).
  • Node-side: validate the tenant URL, authenticate MC/KB transport with the PAT, persist the tenant descriptor (encrypted-PAT-at-rest, mirroring the registry boundary), expose remote roster/status through the same read path the local fleet uses (the cockpit renders a remote tenant like a local one).
  • Cockpit: a "connect remote tenant" entry (UI is L1/#14560's; this leaf ships the Brain-side verb + the contract the pane binds).

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
FleetControlBridge#connectTenant (new) this leaf authenticate + persist a remote tenant descriptor; return public {endpoint,status,deploymentClass} local-fleet path unaffected JSDoc + class doc mirrors defineAgent secret-omission boundary
FLEET_WIRE_METHODS += 'connectTenant' this leaf pane-reachable via dispatchFleetRequest, fail-closed off-allowlist → {ok:false} fleetWireMethods JSDoc existing allowlist pattern
Remote tenant descriptor store (new) this leaf encrypted-PAT-at-rest + endpoint/status root README #13031 registry boundary precedent

Acceptance Criteria

  • connectTenant({tenantUrl, credential}) authenticates against a remote MC/KB tenant + persists a descriptor; the PAT is stored encrypted Node-side and never returned.
  • connectTenant is on FLEET_WIRE_METHODS + generated by the browser bridge; a failed/off-allowlist connect returns fail-closed {ok:false,error} (no crash, no raw error/stack).
  • Remote roster/status render through the same cockpit read path as a local fleet.
  • The deploymentClass the connect establishes (cloud-tenant) is recorded on the descriptor (#14456 interplay).
  • Unit/NL-e2e: successful connect · bad-URL fail-closed · PAT-never-echoed.

Out of Scope

  • The cockpit UI for the connect entry (Lane 1 / #14560).
  • Local add-agent flow + encrypted-PAT-at-rest for local agents (sibling L2/D leaves, to file).
  • Tenant provisioning / hosting (server-side; this is the connect client).
  • The self-configuring install path (#14456 / #14230, Lane 5) — distinct from connecting to an already-hosted tenant.

Decision Record impact

aligned-with the two-hemisphere credential boundary (#13012 / #13015); depends-on the #14456 deploymentClass posture for cloud-tenant. No ADR change.

Related

  • Parent: #13015 · consumes L1 #14560 (cockpit connect UI)
  • Boundary siblings: L2/D local add-agent + encrypted-PAT (to file), #14537 (wake verb), #14562 / #14563 (C1/C2 wiring)
  • Substrate: ai/services/knowledge-base/, ai/services/memory-core/, ingestTenant.mjs, #14456 (deploymentClass), #14230 (local onboarding — distinct)

Live latest-open sweep: checked latest 30 open issues at 2026-07-04T01:17Z + A2A claims (last ~60 min) + grep over resources/content/issues/; no remote-tenant-connect equivalent (#14562 / #14563 are local status/control; #13058 is the local pane).

Origin Session ID: a5ffd401-b3ed-4aa2-aedd-6ca8ea0d6867 Retrieval Hint: "fleet remote-tenant connect tenant URL PAT remote MC KB design-partner FleetControlBridge connectTenant"