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.mdin fleet-dispatch) in FleetDispatchContracts.cs so this repo builds standalone. - Hub DTO drift-killer:
GET /api/meta/hub-eventsforces 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:clientregenerates the TS client from it;npm run check:driftfails 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 atdocs/technical/ARCHITECTURE.mdfor how the system actually works.docs/plain/— the same system explained without jargon, for anyone who isn't reading code day to day. Start atdocs/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.