← back to Charge And Explore

PLAN.md

151 lines

# Charge & Explore — Product Plan

_Codename `tesla`. Source: product spec captured 2026-08-01._

## Executive summary

The strongest product is **not another EV route planner**. It is a decision
engine that answers: **"Which reachable charging stop will give me the best
experience during the time my vehicle is charging?"** Defensible value =
combining charger quality, route detour, walking access, restroom availability,
opening hours, family/pet suitability, weather, and activities that fit a
conservative charging window.

**Architecture:** iOS-first native app (SwiftUI, Swift Concurrency, MapKit,
Core Location, AuthenticationServices, Keychain, APNs), backed by a TypeScript
service layer, PostgreSQL/PostGIS, Redis, object storage, and a provider-adapter
layer.

### v1 non-negotiables
- Works fully **without a connected Tesla account** (manual vehicle + battery profile).
- Tesla Fleet API is an **optional read-only personalization layer** only.
- Request only read scopes: `openid`, `offline_access`, vehicle data, location.
  **No** command or charging-command scopes in v1.
- Treat Tesla `nearby_charging_sites` as contextual enrichment for an authorized
  vehicle — **not** the app's global Supercharger database.
- Launch station data: **NREL** (US/Canada) + commercial (HERE/TomTom) later;
  Open Charge Map only as a low-confidence supplement.
- Apple MapKit + Apple local search for the lowest-friction MVP, behind provider
  interfaces so Google/Yelp/HERE/Mapbox can be added without a rewrite.
- Avoid continuous background phone location; prefer consented Tesla telemetry +
  server-originated APNs, else a local conservative timer.
- **Neutral branding** (Charge & Explore / ChargeStop). "Tesla" never leads the
  app name, icon, or branding.

## Primary risk = data rights, not implementation

Tesla's public Fleet API docs do **not** describe a downloadable, redistributable
global Supercharger catalog. `nearby_charging_sites` needs an authorized vehicle
and returns stations near *that vehicle*. → The product needs a **separately
licensed** station DB and must preserve field-level provenance + provider
restrictions.

**Hard don'ts:** don't crawl Tesla's site/app/in-car/undocumented endpoints;
don't drive synthetic coordinates through `nearby_charging_sites` to build a DB;
don't store/redistribute Tesla fields beyond the Fleet API Agreement.

## Legal / privacy / App Store gates  (detail: `docs/legal-and-appstore.md`)

- **OAuth:** `ASWebAuthenticationSession` (never an embedded login form); backend
  holds the Tesla secret + does the code exchange; `state` + nonce + exact
  redirect-URI + PKCE where supported; refresh tokens are rotating secrets stored
  KMS-encrypted server-side, **never** on the iOS device.
- **Telemetry:** opt-in, field-level consent; minimum signals (`Soc`/`BatteryLevel`,
  `ChargeState`, `TimeToFullCharge`, `FastChargerPresent`, optional `Location`);
  separate toggles for connect / live-updates / precise-location / trip-history.
- **Privacy law:** precise geo is *sensitive* (CCPA) and GDPR-regulated; documented
  retention defaults; in-app export + account deletion + disconnect + token
  revocation are mandatory.
- **Trademark:** no Tesla marks/logos/UI imitation; conspicuous "independent, not
  affiliated" disclaimer; trademark clearance on the chosen name.
- **App Review:** full **demo/mock mode** (synthetic vehicle/station/place/telemetry)
  so a reviewer with no Tesla can complete every flow; default location to
  "While Using"; privacy manifest + nutrition label aligned with every SDK.

## The recommendation core  (BUILT — `backend/src/core/`)

### Charging-time estimator
DC charging is nonlinear (power tapers as SOC rises), so `energy / maxKw`
under-estimates high-SOC sessions. We integrate the curve **band-by-band**,
versioned per model/trim/pack, and present a **range** ("about 28–36 min"), never
false precision. Active sessions prefer Tesla `TimeToFullCharge` once stable
(75% telemetry / 25% model), model as fallback + anomaly detector. Always shorten
an itinerary if the car will finish early — returning early beats a full car
blocking a stall.

### Stop score (0–100, decomposable)
`0.25·Route + 0.20·Charger + 0.20·Amenity + 0.15·TimeFit + 0.10·Nighttime +
0.05·Walkability + 0.05·BasicNeeds`, with `Route = 100·e^(−detourMin/12)` (smooth,
no filter-edge jumps). **No crime-data "safety score"** (bias / false assurance /
redlining) — expose observable nighttime-comfort signals + a confidence label
instead. Hard eligibility gates (compatible charger, reachable with reserve, not
closed/private, detour within max, garage constraints OK, min provider
confidence) run **before** ranking.

### Activity matching
`T_required = walkOut + visit + walkBack + returnBuffer`, buffer =
`max(5, ceil(0.20·window))`. Eligibility uses the **lower bound** of the charge
estimate, not the midpoint. Walking time must come from a **pedestrian route**,
not straight-line distance (a café across a freeway is not a 2-min walk). When
nothing fits: say so, suggest an in-car / restroom-only break — never force a bad
pick.

## Providers (revalidate pricing before signing)

- **Maps/places:** Apple MapKit + Apple local search = recommended MVP default
  (lowest SDK/privacy friction). Mapbox+Yelp when custom maps + restaurant depth
  justify cost. HERE for global enterprise. Google Places = deepest POI but
  material cost + display/caching rules; don't casually mix with a non-Google map.
- **Chargers:** NREL (free, US/Canada, ~daily) for launch; HERE EV / TomTom EV
  (commercial, dynamic status) for scale; Open Charge Map (CC BY, request the
  open subset) as low-confidence supplement. Store **dynamic availability
  separately** from static facts and label freshness ("reported available 2 min
  ago by Provider X"); never infer open stalls from user density.
- **Provenance:** every canonical field keeps provider, record id, retrieved/
  effective/verified timestamps, confidence, license, attribution, redistribution
  flag, cache expiry. Precedence: contracted operator feed > government >
  authorized Tesla contextual > verified user correction > community aggregator >
  unverified report.

## Six-month roadmap (~2,880 team hours, ~2.5 FTE)

| Sprint | Weeks | Goal |
|---|---|---|
| A | 1–2 | Legal/technical foundation: PRD, data-source decision, Tesla app registration, trademark screen, privacy data map, threat model. |
| B | 3–4 | Design system + **mock mode** (synthetic providers, App Review demo). |
| C | 5–6 | NREL ingestion, canonical station schema, PostGIS search, map/list, provenance display. |
| D | 7–8 | Amenities + walking access (Apple local search, pedestrian routes, hours parser, restroom/family filters). |
| E | 9–10 | Route planning + detours + offline corridor schema. |
| F | 11–12 | **Charging estimator + Stop Score + activity matcher** (this repo's core), explanation UI. |
| G | 13–14 | Tesla read-only connection (OAuth, backend exchange, token vault, disconnect). |
| H | 15–16 | Active charging experience (telemetry config, session service, APNs return alerts, timer fallback). |
| I | 17–18 | Offline (GRDB), privacy center, export/delete, accessibility. |
| J | 19–20 | Monetization (StoreKit), station reports + moderation console. |
| K | 21–22 | Hardening + external TestFlight beta (load, security remediation, circuit breakers). |
| L | 23–24 | App Store submission + phased launch. |

**Must ship:** search (nearby/destination/route), manual vehicle profile,
licensed station catalog w/ provenance, map+list, detour + charger facts +
walking + hours + restrooms, charge estimate range, explainable Stop Score,
activity matching w/ buffer, optional read-only Tesla, manual+telemetry active
alert, offline corridor, corrections, privacy center + deletion, full demo mode.

**After approval:** photos/reviews, hotel/attraction affiliates, commercial
charger providers, live availability, Live Activities/Watch, more countries.

**Defer:** vehicle commands, virtual-key pairing, CarPlay, Android/RN rewrite,
food ordering, behavioral ads, AI "safety" claims, unmoderated user tips.

## Pricing (freemium)

Free (nearby + destination search, basic amenities, manual profile, nav handoff) ·
Plus $4.99/mo (route compare, activities, read-only Tesla, active alerts, offline,
history) · Family/Traveler $7.99/mo (multi-profile, presets, shared trips) ·
Fleet/Partner contract. Later: hotel/attraction affiliates (labeled, never alter
organic Stop Score), sponsored charger-host offers, destination partnerships.

## Success metric

Not raw map sessions — optimize for **confident stop decisions** and
**successful charging breaks**.