Skip to content

Fleet Mission Control

Cockpit for the fleet (FLT-13): worker LEDs, a session-tree dispatch queue, live run stream, gate status, usage-governor telemetry, pick-by-name repo dispatch, artifact-run (document/presentation generation), and a gated command plane (launch/cancel runs, per-host availability toggle). C# ASP.NET Core backend + Angular PWA frontend, served on localhost + tailnet only.

Reads stay open behind the tailnet perimeter; every write requires the fleet bearer or a loopback-minted cockpit session — the browser itself never holds the fleet key. See docs/technical/ARCHITECTURE.md §5 for why.

Architecture

fleet-dispatch file queues (OneDrive)   usage-governor state.json   Jira REST (FLT)
              │                                   │                     │ (60s cache)
              ▼                                   ▼                     ▼
        FleetMissionControl.Api  ── net10.0 minimal API + SignalR /hubs/fleet
              │  /api/workers /api/runs /api/governor /api/board /openapi.json
              ▼
        Angular 22 PWA (standalone + signals + @microsoft/signalr)
        TS client GENERATED from OpenAPI via NSwag — drift = CI failure
  • Contracts: fleet-dispatch DTOs are mirrored (frozen contract, docs/run-agent-contract.md in fleet-dispatch) in FleetDispatchContracts.cs so this repo builds standalone.
  • Hub DTO drift-killer: GET /api/meta/hub-events forces the SignalR payload types into the OpenAPI document; the frontend hand-writes only the four hub method names (WorkerHeartbeat/RunUpdated/GovernorTier/QuotaUpdated).
  • OpenAPI artifact: building the API emits openapi/FleetMissionControl.Api.json (committed). npm run generate:client regenerates the TS client from it; npm run check:drift fails when the committed client is stale.
  • Binding: Kestrel listens on localhost:5170 plus any Tailscale (100.64/10) interface. All GETs stay open (tailnet = read perimeter); every write route carries .RequireFleetAuth().

Full endpoint table, request-path sequence diagrams, and every feature added since phase 1 (repo registry, session-tree cards, artifact run, unavailable-mode): docs/technical/ARCHITECTURE.md.

Run

# backend (terminal 1)
dotnet run --project src/FleetMissionControl.Api      # http://localhost:5170

# frontend (terminal 2)
cd frontend && npm ci && npx ng serve --proxy-config proxy.conf.json   # http://localhost:4200

The dev proxy forwards /api, /hubs (websocket), and /openapi to :5170.

Tests

dotnet test                 # backend: reader/parser suites against temp dirs
cd frontend && npx ng test  # vitest: store + component render specs

Client regeneration

dotnet build src/FleetMissionControl.Api   # refreshes openapi/FleetMissionControl.Api.json
cd frontend && npm run generate:client     # rewrites src/app/api/fleet-api.generated.ts

Commit both. CI runs npm run check:drift and fails on any divergence.

Design

Steel/amber ops palette, mono telemetry type, status LEDs, quiet-except-what-needs-you (design reference: FLT-13 proposal artifact). Desktop ≥1100px: 3-pane cockpit. 600–1099px (includes an unfolded Fold): dual-pane. <600px (phone): card stack with the gate first. A genuinely folded/spanned device (hinge-split posture) gets its own layout via @media (horizontal-viewport-segments: 2) regardless of width — see docs/technical/ARCHITECTURE.md §4 for why that's a separate axis from the width breakpoints, not a replacement for them. Light + dark via prefers-color-scheme and data-theme. Responsive via container queries.

Docs

Full documentation set lives under docs/, in two synced tracks:

  • docs/technical/ — technical reference: containers, endpoints, the SignalR live-update path, the responsive posture decision logic, the write-surface auth model, the repo registry/session-tree/artifact-run/availability features, CI gates, and a full library/pattern reference — all cited to file:line. Start at docs/technical/ARCHITECTURE.md for how the system actually works.
  • docs/plain/ — the same system explained without jargon, for anyone who isn't reading code day to day. Start at docs/plain/OVERVIEW.md.
  • docs/technical/making-of.md / docs/plain/making-of.md — a living journal of how this repo got built, commit by commit, including the responsive-posture defect that shipped with 95/95 green tests and screenshots before an outside review caught it, and the four features (repo registry, session-tree cards, artifact run, unavailable-mode) that landed 2026-07-18.