From 4eb2075c7ac01085d5e3751ee87a5c01cba585d2 Mon Sep 17 00:00:00 2001 From: Developer Date: Wed, 14 Oct 2026 12:12:02 -0400 Subject: [PATCH] docs(website): device-connections backend contract for the full "build real" feed (W-devices) Documents the blocker: a richer connected-devices panel (platform, app version, last-seen, accessory pairing) needs a FastAPI endpoint that does not exist yet. Records the proposed GET /api/v1/account/connections contract and the website wiring to adopt it, and notes what already shipped truthfully without a backend change. Co-Authored-By: Claude Opus 4.8 --- .../backend-contracts/device-connections.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 website/docs/backend-contracts/device-connections.md diff --git a/website/docs/backend-contracts/device-connections.md b/website/docs/backend-contracts/device-connections.md new file mode 100644 index 0000000..4499655 --- /dev/null +++ b/website/docs/backend-contracts/device-connections.md @@ -0,0 +1,65 @@ +# Backend Contract Proposal — Device Connections feed (W-devices) + +Status: **Partially implemented.** The website now shows the device/connection data it can +truthfully obtain today. A richer "connected devices" view (platform, app version, last-seen, +accessory pairing) needs a backend feed that does not exist yet. + +## What shipped on the website (no backend change) + +The account page "App Connections & Sync" block previously hardcoded a connected iOS app +("iPhone 16 Pro", "v4.1.0", "14m ago") and a paired "Cardo Packtalk Edge". These were +fabricated. They are now replaced with truthful, real-data states: + +- **Google account** — reflects the signed-in Firebase user (real). +- **Authenticated devices** — count comes from the real `/api/account/sessions` feed + (proxied to `${MOTORSIGNAL_API_BASE_URL}/api/v1/auth/sessions`), already rendered in + detail in the Active Device Sessions panel. +- **Helmet comms & accessories** — "Unavailable on web": a browser cannot observe Bluetooth + pairing. Managed in the mobile app. +- **Apple Watch** — "Unavailable on web" (unchanged, already truthful). + +## Why the full feature needs a backend + +A browser cannot see a rider's paired Bluetooth hardware, installed mobile app build, or +device platform. Those facts live on the device and in MotorSignal's backend. The auth +sessions feed is close but does not classify platform / app version / accessory pairing. + +Delivering a true "connected devices" panel therefore requires a backend endpoint (FastAPI; +out of scope for the website task and must be authorized separately). + +## Proposed contract + +Endpoint: `GET ${MOTORSIGNAL_API_BASE_URL}/api/v1/account/connections` +Auth: Bearer access token (same as the sessions endpoint). + +```jsonc +{ + "devices": [ + { + "id": "string", + "kind": "mobile_app | web_session | accessory", + "platform": "ios | android | web | null", + "label": "iPhone 16 Pro", // human-friendly, backend-provided + "appVersion": "4.1.0 | null", + "lastSeenAt": "ISO-8601 | null", + "pairingStatus": "paired | disconnected | null", // accessories only + "current": false + } + ] +} +``` + +Rules: +- The backend is the only source of platform / app version / accessory pairing. The web + client must render exactly what it returns and must never infer or fabricate these. +- Absent/empty feed → truthful empty state ("No linked devices"), never sample data. +- Accessory (Cardo/Sena/GoPro/Apple Watch) rows appear only if the backend reports them; + otherwise the web continues to show "Unavailable on web". + +## Website wiring once the endpoint exists + +1. Add `fetchConnections()` to a lib module, proxied like `/api/account/sessions`. +2. Replace the current heuristic "Authenticated devices" row with the real feed, grouping by + `kind`, showing `label`, `appVersion`, and relative `lastSeenAt`. +3. Add tests for: real feed rendering, empty feed → empty state, and no fabrication when the + endpoint is unavailable.