How the properties connect, where contracts live, and which protocols cross each boundary. Reflects current state as of 2026-04-28: Feature #7 (Gateway Extraction) Phase 6 Track A landed 2026-04-21, the ace_supervisor repo split into robot-supervisor-service + robot-gateway-service, and shared schemas live as @valeron/gateway-contracts (a workspace package inside robot-gateway-service, not its own repo).
Containers = where the code runs. Boxes = repos. Arrows = runtime traffic with protocol labels.
@valeron/gateway-contracts (in-repo workspace pkg)"]
RSS["robot-supervisor-serviceace binary · :8090/log · /healthz"]
end
subgraph CJ["Capture Jetson — v0-ace00-capture"]
direction TB
RCS["robot-capture-service@valeron/gateway-contracts consumed by| MGA
%% --- Classes ---
classDef cloud fill:#0a1a24,stroke:#60a5fa,color:#dbeafe;
classDef robot fill:#0e1a12,stroke:#9ac76a,color:#d7e7c5;
classDef mobile fill:#1a0f1e,stroke:#c084fc,color:#e9d5ff;
classDef desktop fill:#1a1a0e,stroke:#eab308,color:#fef3c7;
classDef web fill:#0e1a1a,stroke:#22d3ee,color:#cffafe;
classDef shared fill:#1a120e,stroke:#f97316,color:#fed7aa;
classDef device fill:#111,stroke:#64748b,color:#cbd5e1;
classDef extnode fill:#1a1a1a,stroke:#6b7280,color:#d1d5db,stroke-dasharray:5 5;
class CPS cloud;
class RGS,RSS,MFA,RCS robot;
class MGA mobile;
class DFA,DTA desktop;
class WPA,WMA,WMS web;
class DP shared;
class Golfer,FieldTester,Customer,Operator device;
class PIPE,AD,HAL,ACED extnode;
%% Subgraph styling
style Cloud fill:#05121c,stroke:#60a5fa,color:#dbeafe
style Robot fill:#081408,stroke:#9ac76a,color:#d7e7c5
style RJ fill:#0c1f12,stroke:#9ac76a,color:#d7e7c5
style CJ fill:#0c1f12,stroke:#9ac76a,color:#d7e7c5
style MobileNative fill:#140a17,stroke:#c084fc,color:#e9d5ff
style DesktopSub fill:#14130a,stroke:#eab308,color:#fef3c7
style WebSub fill:#0a1414,stroke:#22d3ee,color:#cffafe
style SharedSub fill:#140f0a,stroke:#f97316,color:#fed7aa
style Devices fill:#0b0b0d,stroke:#64748b,color:#cbd5e1
Thick double lines (==>) are the phone-to-Gateway path that Feature #7 introduced (Phase 3+4 of the rollout, shipped 2026-04-21). Dotted orange arrows mark where contract source-of-truth lives. Dashed nodes are owned outside Valeron but run on our hardware: ace_devel (Jimmy's nav stack, Nav Jetson) and golfer (Brandon + Marius's capture pipeline, Capture Jetson).
Colors used in the diagram + in the contract table below.
new_shot)Every contract that crosses a process or host boundary, where it lives, which surfaces it joins.
| Contract | Boundary | Protocol | Auth | Source of truth |
|---|---|---|---|---|
| Cloud edge functions pair · start-session · end-session · end-my-session · active-device-for-user · users-by-device · sessions · courses · connect |
Client (phone, web, robot, ferry) ↔ Cloud | HTTPS | Supabase JWT (user) or service-role (robot, ferry) | docs-platform/apis/cloud/edge-functions/*.yaml |
| Capture → Gateway webhook enrollment_complete |
Capture Jetson → Nav Jetson (Gateway) | HTTP (LAN) | Bearer CAPTURE_WEBHOOK_SECRET |
docs-platform/apis/webhooks/capture-to-gateway/enrollment_complete.md |
| Capture → Supervisor webhook shot_complete |
Capture Jetson → Nav Jetson (robot-supervisor-service) | HTTP (LAN) | Bearer CAPTURE_WEBHOOK_SECRET |
docs-platform/apis/webhooks/capture-to-janice/shot_complete.md (path retains the capture-to-janice slug — Janice is the persona name, robot-supervisor-service is the canonical service) |
| Supervisor → Gateway shot_complete forward POST /capture/shot_complete |
Loopback on Nav Jetson | HTTP loopback | Bearer GATEWAY_INTERNAL_SECRET |
@valeron/gateway-contracts v0.2.0 (in robot-gateway-service/packages/contracts/; ACL-104) |
| Phone → Gateway live feed GET /ws · GET /shots · GET /shots/:id/{video,thumbnail} |
Golfer phone (LAN / AP) ↔ Gateway | WS + HTTP | Session token (?session=… on WS; Authorization on HTTP) |
@valeron/gateway-contracts v0.2.0 (in robot-gateway-service/packages/contracts/; ACL-104) |
| Capture Jetson internal pipeline ↔ capture service (Contract 1 + 2) |
Two processes, same host | HTTP loopback + Unix sockets | HMAC-shared-secret (Contract 1) / bearer (Contract 2) | docs-platform/apis/capture/{internal-http,unix-sockets}.md |
| Robot onboarding | Field-tester / operator phone ↔ Robot Jetson | HTTP | Bluetooth-provisioned creds (future) | docs-platform/apis/robot/ONBOARD.md |
| Gateway → Cloud cloud_sync batched shot uploads |
Nav Jetson (Gateway) → Cloud | HTTPS | Service-role key (SUPABASE_SERVICE_ROLE_KEY) |
Reuses apis/cloud/edge-functions/sessions.yaml |
| Operator ↔ Supervisor desktop-ferry-app |
Operator laptop ↔ Nav Jetson (robot-supervisor-service) | Tailscale | Tailscale identity (mesh VPN) | Per-tool README (no cross-surface contract) |
| Operator ↔ ace nav stack desktop-tuner-app ("Jamal Tooner") |
Operator laptop ↔ Nav Jetson (ace_devel, ace_app.service) |
Tailscale SSH → curl :8090 |
Tailscale identity (mesh VPN) | Per-tool README (no cross-surface contract) |
| Field app ↔ ace_dashboard (planned) forthcoming transport swap from today's HTTP :9000 → :8090 |
mobile-field-app ↔ ace_dashboard (Nav Jetson) | WS | TBD | TBD · JSON-over-WS (proto later) per Jimmy · not yet ticketed |
| Supervisor ↔ ace_dashboard (planned) forthcoming transport swap from today's HTTP :8090 |
robot-supervisor-service ↔ ace_dashboard (Nav Jetson) | WS | TBD | TBD · same JSON-over-WS shape as MFA · not yet ticketed · confirmed by Jimmy 2026-04-19 ("you don't need to go to 8090 anymore") |
| Cloud → Robot push | Cloud → Robot | none | n/a | docs-platform/apis/webhooks/cloud-to-robot/README.md — explicitly documents the pull-only policy |
Every Valeron-maintained repo + external-owned repos we consume, colored by surface. Names per ADR-022 (Phase B–E renames complete).
robot_supervisor_service.service · path: /opt/valeron/supervisor/ace_supervisor via Feature #7 (Phase 6 Track A landed 2026-04-21). Hosts the @valeron/gateway-contracts workspace package at packages/contracts/.ace-pilot) intentionally deferred.mobile_field_app.service · path: /opt/valeron/fieldapp/course_features publish flowapis/cloud/edge-functions/sessions.yamlnav2.yaml tuning tool for on-robot nav params.ace_devel nav stack via Tailscale SSH → curl localhost:8090; restarts ace_app.service systemd unit. Does not route through robot-supervisor-service.robot-capture-service, owned outside Valeron.mobile-field-app will swap its transport from direct HTTP to the Supervisor (:9000 → :8090) for a WS connection against ace_dashboard once it ships.ace binary · :8090Feature #7 has shipped. Phase 6 Track A landed 2026-04-21. mobile-golfer-app talks to the Gateway directly, the golfer web app that used to live at ace_supervisor/ui/golfer/ is retired (not drawn), and the Supervisor's shot_complete branch is a pure loopback forward to Gateway — Supervisor no longer owns shot_store, cloud_sync, or the phone WS channel. Schemas that cross the Gateway boundary live in @valeron/gateway-contracts v0.2.0 — a workspace package at robot-gateway-service/packages/contracts/, not a separate repo (the earlier "shared-gateway-protocols" name from the F#7 design doc never became a real package).
Janice is the persona, not the canonical name. The supervisor service was historically called Janice, and the persona is preserved in the systemd unit Description, log prefix, and alert templates. The repo + service identifier is robot-supervisor-service / robot_supervisor_service.service per ADR-022 Amendment 2026-04-22 (Jetson-side rename landed 2026-04-23 via ACL-185). Anywhere this diagram says "Supervisor" + the persona note, that's the same thing.
Two-Jetson topology. The robot is a two-board system: Nav Jetson (Tailscale hostname v0-ace00-robot as of 2026-04-22 reflash; runs the C++ nav stack, robot-supervisor-service, robot-gateway-service, mobile-field-app) and Capture Jetson (v0-ace00-capture; runs the shot-tracking pipeline + robot-capture-service). Both sit physically on the robot — the historical "Robot Jetson" label is misleading. They're connected over an eth1 RJ45 cable on subnet 192.168.50.0/24 (.10 Nav, .11 Capture, per ADR-023). On-course operation is internet-free; cloud sync is queue-and-forward.
What's deliberately absent. No cloud-to-robot push exists, by design (robots are NAT'd, connectivity-variable, and on-course typically offline per ADR-023). The apis/webhooks/cloud-to-robot/ doc exists to enshrine the pull-only policy. Observer UI / Supervisor UI for operators is elided — per ADR-021 it migrates cloud-hosted, framework TBD, not yet a standalone repo.
ace_dashboard — planned, not shipped. Jimmy's forthcoming service on the Nav Jetson that fronts HAL + nav (and presumably other robot-services) behind one boundary. Dashed node in the Nav Jetson subgraph. Both Nav-Jetson clients of nav today migrate through it: (1) the Field-app transport swap (HTTP :9000 → RSS :8090 becomes WS → ace_dashboard), a one-file change in mobile-field-app/src/lib/stores/transport.js bundled with ACL-108 (Svelte+TS migration); (2) the Supervisor's own nav-stack calls (today RSS → :8090 on the C++ ace binary) also move to WS via ace_dashboard — confirmed by Jimmy 2026-04-19 ("you don't need to go to 8090 anymore"). Neither migration is ticketed yet — both wait on ace_dashboard shipping. Feature #7 Phase 5 Step 5 (relocating mobile-field-app into Gateway) was cancelled 2026-04-19: same-origin collapse was a golfer-phone / Safari-HTTPS driver, and Field Control runs over Tailscale so the constraint doesn't apply. mobile-field-app stays in its own repo, own port, own systemd unit.
HAL surfaced as its own node. Per Jimmy's framing, ace_dashboard "encapsulates all calls to robot services (HAL / nav / etc)" — HAL is a named upstream by definition, so surfacing it separately from the nav stack keeps the diagram honest about what ace_dashboard is fronting. Today HAL has no external callers (it's accessed intra-binary inside ace_devel); the only inbound edges on the diagram are the dashed planned edges from ace_dashboard. This is the right state: HAL becomes reachable from outside the ace binary exactly when ace_dashboard ships.
Identity axes to remember. Repo name ≠ Supabase project name ≠ env-var key ≠ persona name. cloud-platform-service (the repo) drives the ace_cloud Supabase project (preserved), which is addressed in consumer repos via ACE_CLOUD_* env vars (preserved). robot-supervisor-service (the repo + unit) carries the Janice persona (preserved in description/logs/alerts). See ECOSYSTEM.md §Repository Index for the multi-axis carve-out pattern.
Ground truth: docs-platform/architecture/ECOSYSTEM.md (repo enumeration),
docs-platform/architecture/FLOWS.md (12 product flows; cite a flow before changing wiring),
docs-platform/apis/ (contract sources),
cloud-platform-service/docs/plans/2026-04-16-gateway-extraction.md (Feature #7 design doc),
docs-platform/decisions/023-on-course-network-topology.md (ADR-023 — internet-free operation),
docs-platform/decisions/022-repo-renames.md Amendment 2026-04-22 (underscored unit names).
When this diagram and those sources disagree, the sources win — this file is a snapshot.