- Server: include active_route_destination (lat/lng/eta) from drive_state.
- When Tesla is connected, the Origin → Destination strip collapses to a
single ConnectedTripStrip: "From car · Where to?". The origin is implicit
(the car's GPS), the manual From input + crosshair button disappear.
- If Tesla nav already has a destination, it auto-fills as the trip
destination; if the user has typed something else, an inline "Use Tesla
nav" button offers a one-tap swap.
- Mocks: driving + charging scenarios include an activeRoute so the flow
is testable end-to-end via ?mockTesla=driving / ?mockTesla=charging.
- Add OWNER_SECRET-based session: signed HMAC cookie, /api/auth/owner login,
requireOwner middleware. All Tesla routes refuse 401 without it.
- Bind OAuth state to a SameSite=Lax httpOnly cookie at /start, validate
match in /callback with constant-time compare. Refuses unmatched callbacks.
- Token store now mkdir 0700, writeFile + rename atomic, mode 0600 with
defensive chmod. Owner-only on disk.
- VIN masked to last 4 in responses; partner-register no longer echoes raw
Tesla body to clients; coord bounds checked on send-to-nav.
- Client: useTesla also tracks owner status; Connect Tesla button opens an
OwnerLoginModal when not authenticated, then continues to Tesla OAuth.
Conscious deferrals:
- Explicit CSRF tokens on POST routes: mitigated by SameSite=Lax cookies
+ same-origin CORS. Will revisit if cross-origin clients land.
- At-rest token encryption: deferred for single-user app; tokens are on a
0700 Dokku volume readable only by the app uid. Will add AES-GCM if we
multi-tenant.
Server:
- teslaTokenStore: file-backed token store at /app/data/tesla-tokens.json
- teslaClient: OAuth (authorize/code-exchange/refresh), Fleet API GET/POST,
listVehicles, getVehicleData, wake, sendNavigationRequest, getAppToken,
registerPartnerAccount; auto-rotates refresh tokens 60s before expiry
- /api/tesla/status, /api/auth/tesla/start, /api/auth/tesla/callback,
/api/tesla/state, /api/tesla/wake, /api/tesla/send-to-nav,
/api/tesla/disconnect, /api/tesla/register-partner
- State includes battery, range (mi→km), charging power/eta, GPS,
shift_state, model/trim auto-detected from vehicle_config
Client:
- useTesla hook: auto-fetches status, polls live state every 60s when connected
- Connect Tesla chip in TopBar; on connect shows battery% + range
- Per-stop "Send to Tesla nav" button (only when Tesla connected)
- "Use my location" button prefers vehicle GPS over browser geolocation
- Auto-detects model/trim from Tesla and updates the vehicle picker
- When in-car AND Tesla connected: auto-fills origin from car's GPS,
hides the vehicle chip (we know the car), hides GPX export and Share
- Travel dates: TopBar chip + popover (outbound/return/travellers); sent to
Grok prompt; itinerary.needsTravelDates drives a nudge banner; cache and
prefetch ledger invalidate when dates change
- Sea crossings: CrossingOption schema (Eurotunnel, DFDS, P&O, Brittany,
Stena Line); CrossingSwapBlock under tunnel/ferry/crossing stops with
trip-impact deltas and Book links; prompt requires 3-5 real options for
every UK ↔ mainland route; picking a crossing triggers silent re-plan
- Tesla in-car polish: UA + heuristic detection sets <html class="incar">;
CSS overrides kill backdrop-filter, scale fonts, enforce 44px tap targets,
disable hover flicker; geolocation + reverse geocode + crosshair button
inside the From input; up/down arrow reorder buttons replace touch-broken
HTML5 drag-and-drop
- Tesla Fleet API stub: /.well-known/appspecific/com.tesla.3p.public-key.pem
served from TESLA_FLEET_PUBLIC_KEY for partner domain verification;
OAuth callback + vehicle_data stub return 503 until partner approval
- Dockerfile + .dockerignore for Dokku deployment; server now serves
client/dist in production