Skip to content

Fleet Studio B2b (#1540) — remote peer-studio control + live streaming - #1547

Merged
jeonghun-jj-lee merged 5 commits into
feature/free-tier-fleetfrom
amico/issue-1540-base-peer-control
Sep 24, 2026
Merged

jeonghun-jj-lee merged 5 commits into
feature/free-tier-fleetfrom
amico/issue-1540-base-peer-control

Conversation

@jeonghun-jj-lee

@jeonghun-jj-lee jeonghun-jj-lee commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Fleet Studio B2b (#1540) — remote peer-studio control + live streaming on the observation path

One integration PR for the whole B2b DAG (parent #1540, slices #1541–#1545), targeting feature/free-tier-fleet. Design-of-record: ADR 0034 (D1–D7) + ADR 0033 Amendment 1, both in-base. Every slice is TDD (RED→GREEN), additive, and grounded against the deliberate-review corrections that bind on the issues.

Slices (all GREEN, director-verified)

Final gate battery (all GREEN on 669500d)

Gate Result
Extension full suite 4930 passed / 11 baseline / 48 skip — 0 new failures
Extension typecheck clean (exit 0)
Additive-invariants 4/4
Overlay typecheck clean across all 7 packages (no allowlist)
amico-run suite 1762 passed
Bundle-build gate PASS (5/5 bundles + verb-router smoke)
App touched suites (bun test) 81 passed

E2E verification (partial — the ext-host isn't running)

  • READ proven live: Studio reachable via SSH forward (:45096), GET /session/ses_f3df…→200 with both the standalone cred and the peer reader token.
  • WRITE gate not testable live: the running services are pre-B2b builds (no write gate wired). Full E2E requires deploying the new binary + app dist → VS Code restart.
  • Binary built from this branch (sha d2cbf0f2, channel=dev).

To deploy + verify (for the reviewer)

# from the merged feature/free-tier-fleet (or this branch with override):
AMICODE_DEPLOY_OVERRIDE="pre-merge-1547" pnpm --filter amicode run build:app
pnpm --filter amicode run build:binary
# restart VS Code → the B2b stack lights up on the observation path

Closes #1540

…dmin authority + self-owned control issuance

Grant foundation slice of ADR 0034 (D3): the NET-NEW lifecycle-admin authority
persistence, the self-owned control fast-path, and the owner-resolvable control
grant read #1542 needs. All additive; peer studios stay additive.

- @amicode/schema: fleet_lifecycle_authority.ts — the shared on-disk authority
  store contract (record shape, path, writer, resolver) at
  ~/.amico/fleet-lifecycle-authority.json, env-overridable. The cross-package
  seam is a shared on-disk contract (amico-run writes, the extension reads),
  the same pattern as fleet_roster/fleet_config — never a cross-package import.
- amico-run: `amico fleet enroll` (client redeem) records the enroller as this
  machine's lifecycle-admin authority via an injectable recordLifecycleAuthority
  seam with a real default — enroll stays byte-identical when defaulted.
- extension fleet_lifecycle_authority.ts: the service-side resolver ("who holds
  authority for machine X"), feeding management-verification and #1545 routing.
- extension fleet_control_bootstrap.ts: evaluateControlBootstrap (a NEW predicate
  mirroring evaluateObserveBootstrap, which refuses control) — self-owned +
  management-verified authorizes; every other case requires approval (no
  privilege bleed). management-verified is a DEFINED predicate (enroll-seeded
  authority + serving peer + held reader token). enableSelfOwnedControl mints an
  ACTIVE control grant on the explicit enable, no target-side interaction.
- fleet_control_lifecycle.ts: findControlGrantByTarget — resolves the controlling
  machine's own active control grant by targetMachineId, with its token (ADR D2).
- AC3 (control-not-auto-restored) is a regression guard on the landed
  fleet_headless_rehydration.ts — a test asserts it, no re-implementation.

Tests: new fleet_control_bootstrap + fleet_enroll_authority suites; extended
fleet_control_lifecycle, fleet_headless_rehydration, and amico-run
fleet_enroll_verb suites. All touched suites green; typecheck clean; amico-run
bundle gate + INVARIANT_STRICT additive gate pass.
@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 8080daaf-8c7e-4e88-85a4-fffb3c6310a8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

amicode-ci added 4 commits September 24, 2026 16:34
…ote writes

Mirror the #1537 observation READ seam for WRITES, with the GET/non-GET
decision INVERTED: a NON-GET request (prompt/archive/delete) to a peer-owned
session is authorized by the pure evaluateRemoteWriteGate and, when allowed,
proxied to the owner; GET is ignored (the read plane owns it); local/unowned/
non-session/amicode writes fall through byte-identical.

- ObservationWriteRouter (session_multiplexer.ts): resolve() inverts GET,
  authorizes via the gate, returns a peer target | named deny | undefined.
- D2 grant-key fix: grantReader resolves the controlling machine's OWN active
  control grant by targetMachineId === owner (findControlGrantByTarget, #1541),
  NOT a requesterMachineId-keyed lookup that would deny every write.
- createObservationWritePlane (new observation_write_plane.ts): its OWN
  proxyToPeer via HubProxy, presenting the PEER reader token the owner accepts
  (NOT the control token, which the owner has never seen and would 401; NOT the
  ControlGatedResolver adapter, which drops the peer credential). Honest
  boundary documented: a distinct owner-enforced control token is future work.
- Dispatch wiring (server.ts): ObservationWritePlane interface + observeWrite
  seam + attachObservationWritePlane; consult beside observeRead inside
  if (this.engineProxy) — allowed proxies to the owner, transport-down is the
  peer-unreachable 503, auth denials (no-control-grant/grant-revoked/
  insufficient-scope) are a 403 carrying the gate's real reason, NEVER local.
  Structural no-op when unattached (byte-identity).
- index.ts: attach the write plane in the observation branch, wired from
  fleetPeers (owner map, serving peers for reachability + credential) + the
  lifecycle grant deps.

Part of #1540. ADR 0034 D2/D4/D5.
…033 D1-D4)

A NEW, separately-armed observation /event interception that reuses
SseFanInDriver as a library (ADR 0034 D6 / ADR 0033 Amendment 1): NOT the
premium fleet-plane wire, NOT behind AMICO_FLEET_MULTIPLEX, NOT behind the
multiplexer. Armed on observation readiness (the driver declines at zero
non-local owners = the fleet-of-one byte-identity guard); no focus-snapshot
provider on this path so byte-identity holds. Per-peer arms auth as themselves
with their own reader token; local arm rides the app credential.

- server.ts: observeEvents field + attachObservationEventPlane + a separate
  /event dispatch consult beside (never replacing) the premium wire.
- index.ts: attach a SseFanInDriver in the observation branch, wired from
  fleetPeers (ownerMap/localMachineId/localEventUrl/peerBaseUrl/peerToken).
- +5 tests: fleet-of-one byte-identity oracle (vs no-plane), live peer fan-in,
  cursor pass-through, inert-when-unattached, production wiring (peer /event
  dialed with the reader token). Premium server.ts wire + fleetMultiplexEnabled
  untouched (the #1519 invariant test stays green).

Director-run recovery (autodev honest degradation): the dispatched implementer
session was interrupted with nothing written; worktree was pristine.

Part of #1540.
…losed affordances

State channel (Data Contract): amicode_control { controlState, reason, eligibility }
rides the fleet projection (GET /amicode/fleet/sessions) as a sibling of
amicode_owner — the SINGLE carrier, derived from remote_session_state.ts (the SoT,
preserving distinct reasons the write gate collapses). All five SoT reasons
enumerated: no-control-grant, grant-revoked, revocation-pending, insufficient-scope,
transport-down. The app consumes it off DropdownSession.

Session surface:
- Fail-closed chip: disabled write affordances + visible human-readable reason per
  state (never a live erroring button).
- Enable control (self-owned): dispatches amicode.fleet.enableControl to the VS Code
  native-modal confirm; on success the projection flips to interactive + the driving
  banner lights.
- Request control (shared): affordance present, dispatches to the #1545 request route
  (backend not yet built — honest inert placeholder).
- Persistent driving banner: Portal to document.body, data-driving-peer hook (assertable),
  survives intra-session navigation.
- Owner-routed remote-delete: built (reuses arm→confirm interaction over the #1542 write
  plane's owner-routed path), attached to the session timeline.
- Archive: no discrete confirm (per D4).
- Fleet Manager grant panel: list + enable/disable/revoke affordances; pending-requests
  stub for #1545.
- Sidebar: read-only preserved (control surfaces on session + Fleet Manager only).

Director-run recovery (autodev honest degradation): dispatched implementer interrupted
with 15 files of uncommitted work — reviewed, gates run, committed.

Part of #1540.
…hake

Net-new shared-peer control path (ADR 0034 D3, slice 5):

- fleet_control_request.ts: pending-request store (file-based, keyed,
  state machine: pending → approved|denied), submit/approve/deny operations.
  Injectable deps, env-overridable path (AMICO_FLEET_CONTROL_REQUEST_FILE).

- Server routes: POST /amicode/fleet/control-request (submit),
  /control-approve (authority-gated, mints control grant),
  /control-deny (no grant). All under /amicode/fleet/* (never-proxied).

- Route matrix: control-approve/deny added to LIFECYCLE_ADMIN_PREFIXES
  (only lifecycle-admin authority can approve or deny).

- GET /amicode/fleet/grants now returns live pending_requests (replaces
  the #1544 empty stub).

- fleet_control_bootstrap.test.ts extended: 3 new tests pin the
  shared-peer arm (bootstrap → submit → approve → grant, deny path,
  no-privilege-bleed invariant).

- fleet_control_request.test.ts: 26 tests covering the store, submit,
  approve, deny, fail-closed, already-granted, multiple requesters,
  and route-matrix enforcement.

Invariants:
- Shared path NEVER borrows the self-owned fast-path (no privilege bleed)
- Fail-closed: no approval → no control grant
- A headless target renders nothing; approval is from the authority holder

Closes #1545
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant