docs: add Phase 25.5 device config sync plan

Plan for replacing hardcoded user/car/avatar with managed server-synced configuration, enabling multi-device and zero-code-edit deployment scenarios.

Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Mathieu Moran
2026-08-10 16:21:49 -04:00
co-authored by Copilot
parent 235ca65822
commit 69beb07430
+41
View File
@@ -1482,6 +1482,47 @@ must be fixed, redeployed uncommitted, and the affected in-car test repeated bef
and **ready-to-install** sign-off. Afterward, the owner handles permanent installation outside the
phase roadmap.
### Phase 25.5: Device profile & configuration sync — 🚧 PLANNED (local config mgmt)
**Unstarted.** Replace hardcoded `account.name`, `car.model`, and avatar with managed configuration editable on the server and synced to the Pi. Enables multi-device/multi-user scenarios and eliminates manual code edits.
#### Scope
- **Server-side config editor**: add a simple "Device Settings" page on the remote portal (login-protected, device-scoped) with editable fields:
- Device nickname (device_name, for display on the portal and Pi topbar)
- Car model/year (already in DB via Phase 24's `device_id` + `car_model`, but allow user override)
- Profile picture upload (stored server-side, served to both portal and Pi via API endpoint)
- Owner name / username (replaces hardcoded `account.name`)
- **Pi-side config sync**:
- Add a new `device_config` table to local SQLite (device_name, owner_name, car_model, avatar_url, sync_timestamp, hash)
- On Pi startup and every 30 minutes, fetch the latest config from the remote server via a new `/api/device-config` endpoint (authenticated with device_key, not user login)
- If hash differs, update local config table and restart the web app (or hot-reload via settings API)
- Fall back gracefully to hardcoded defaults if server is unreachable
- **UI updates**:
- Pi topbar shows the synced `device_name` instead of hardcoded car model (or car model from synced config)
- Pi sidebar shows the synced owner_name instead of hardcoded `account.name`
- Avatar image sourced from synced `avatar_url` (served from server, fallback to local placeholder)
- All trip/tracking records use synced values at capture time (no retroactive changes to history)
- **Device authentication**: use an existing `device_key` (generated on first Pi provisioning, stored in `/home/yaris/app/yaris-obd/.device-key` or env var) to authenticate the `/api/device-config` request. Server validates device_key against the Postgres `devices` table.
#### Implementation phases
1. **Server (Phase 25.5a)**: add `device_name`, `owner_name`, `avatar_blob` columns to Postgres `devices` table; create `/api/device-config` read endpoint and `/api/device-config` POST endpoint for edits; add Settings UI to portal for these fields.
2. **Pi config table & sync (Phase 25.5b)**: add `device_config` SQLite table; implement 30-min sync fetch on Pi; hot-update app globals if config changes.
3. **UI updates (Phase 25.5c)**: update topbar, sidebar, avatar rendering to use synced config; test full cycle (edit on server → Pi syncs → UI reflects change).
4. **Acceptance (Phase 25.5d)**: multi-sync cycle test, network loss recovery, avatar upload/display, retroactive trip behavior.
#### Benefits
- No code edit needed to rebrand a deployed Pi
- Server becomes the source of truth for device identity (enables future multi-Pi/multi-car scenarios)
- Avatar management centralized
- Graceful fallback if server unavailable (Pi uses last-synced config)
- Enables future features: device rename, device status on portal, bulk config across devices
#### Trade-offs
- Adds config sync complexity and latency (eventual consistency)
- Requires device authentication key rotation strategy (future)
- Metadata storage (avatar blob) requires server-side image handling
---
### Phase 26: Native Android companion app — 🚧 PLANNED (low priority, always last)
Revives the phone-relay goal (Phase 11/12) properly this time, using a real native app instead of
a web page - the only way to actually hold a WiFi connection to the Pi's hotspot and a cellular