commit 16eb089cc315fe48a969f0cb390b7aaed77bbf1b Author: araharah-planner Date: Thu Oct 22 02:33:01 2026 +0800 docs(01-design-tokens-rams-foundation): create phase plan (4 plans, 3 waves) diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md new file mode 100644 index 0000000..df01aa1 --- /dev/null +++ b/.planning/ROADMAP.md @@ -0,0 +1,188 @@ +# Roadmap: araharah + +## Overview + +araharah turns Telegram into a privacy-respecting turn-by-turn navigator for KL: a bot handles +identity, search, and launch; a Telegram Mini App renders Rams-styled route guidance; Valhalla +routing, self-hosted Photon lookup, OpenFreeMap tiles, and MapLibre GL JS v6 supply the OSM +geodata layer; one Cloudflare Worker (static assets + webhook + `/api/*`) serves it all with +KV-only TTL storage. The roadmap follows the research's strict dependency funnel — design tokens +first (design fidelity is the flagged #1 sink for v1), then the bot/identity security floor, +then the Mini App shell with geolocation, then KL destination search, then routing and route +display, then live turn-by-turn guidance including backgrounded chat turn-cards, and finally a +hardening pass that earns the private launch. Two phases deliberately surface the project's +biggest unknowns early: WebView geolocation quirks (Phase 3) and KL search quality (Phase 4). + +## Phases + +**Phase Numbering:** +- Integer phases (1, 2, 3): Planned milestone work +- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED) + +Decimal phases appear between their surrounding integers in numeric order. + +- [ ] **Phase 1: Design Tokens + Rams Foundation** - Distill the Telemetry Rams system into a single token package and Rams-styled map basemap, with a mockup-vs-implementation approval artifact — before any screen is built +- [ ] **Phase 2: Bot Skeleton + initData Security** - grammY bot on one Cloudflare Worker: /start, command menu, /privacy, and HMAC-validated identity with TTL-only KV storage +- [ ] **Phase 3: Mini App Shell + Geolocation** - Telegram WebApp shell that boots, authenticates, and reads a reliable live location across the Android/iOS/Desktop client matrix +- [ ] **Phase 4: Destination Search + KL Gazetteer** - Free-text KL search that resolves landmarks despite Malay abbreviations and typos, venue cards, and Mini App launch with destination preloaded +- [ ] **Phase 5: Routing + Route Display** - Valhalla-backed route calculation shown as a Rams route line with quiet alternative cards; the full search→route→render loop lands +- [ ] **Phase 6: Turn-by-Turn Guidance (Live Driving)** - Client guidance state machine: maneuver banner, missed-turn auto-recalculation, honest ETA, haptics, seamless resume, and backgrounded chat turn-cards +- [ ] **Phase 7: Hardening + Private Launch** - Device-matrix QA, graceful failure states, privacy-by-construction audit, and golden-route regression before real drivers + +## Phase Details + +### Phase 1: Design Tokens + Rams Foundation +**Goal**: The Telemetry Rams design system exists as one centralized, importable token set — including map basemap cartography — with a user-approved mockup-vs-implementation gallery proving the fidelity bar before any product screen is built. +**Depends on**: Nothing (first phase) +**Requirements**: DSGN-01, DSGN-02 +**Success Criteria** (what must be TRUE): + 1. Every rendered Rams component derives exclusively from the centralized token set (exacted palette, 8px grid, radius-0, typography) — an audit sweep finds zero off-token color/spacing/typography values in the component sheet (DSGN-01) + 2. A side-by-side gallery comparing the rendered token/component sheet against the `stitch_minimalist_route_navigator/` mockup screens exists and is approved by the user — establishing the DSGN-02 approval artifact mechanism reused by every later UI phase + 3. A Rams-styled MapLibre basemap (OpenFreeMap `liberty` style forked to Rams tokens: grayscale grounding, muted land/water, prepared accent for route highlighting) renders in a browser (DSGN-01, map cartography) + 4. Design authority is singular: the duplicate inline Tailwind token blocks and the conflicting root `DESIGN.md` typography are superseded by the token package as the one source of truth (resolves the CONCERNS.md design-source conflict) +**Plans**: 4 plans + +Plans: +- [ ] 01-01-PLAN.md — Repo hygiene + Tailwind v4 token package (`theme/`) + self-hosted fonts + DESIGN.md supersession (D-01/02/04/05/06/07/16) +- [ ] 01-02-PLAN.md — Component sheet: `theme/src/components.css` + `sheet.html` consuming tokens only (D-03/D-11) +- [ ] 01-03-PLAN.md — Rams basemap: token-derived OpenFreeMap liberty fork + KL preview (D-08/09/10) +- [ ] 01-04-PLAN.md — Off-token audit (D-13) + Playwright captures (D-14) + DSGN-02 approval gallery (D-12), blocking user checkpoint + +Notes: +- Repo hygiene lands here first: scrub `*:Zone.Identifier` artifacts, `.gitignore` for OS junk/`node_modules`/secrets (pre-dates any credential handling). +- Project skill `.agents/skills/design-taste-frontend/` applies to all UI phases under its *existing brand/design system* special case: keep the Rams palette/type, app-screen house rules for dashboard-like surfaces, real-browser inspection for the gallery artifact. Telemetry Rams tokens are binding where skill defaults would differ. +- Standard patterns (no research phase needed): mockups are the spec; token extraction from the mockup Tailwind config. +**UI hint**: yes + +### Phase 2: Bot Skeleton + initData Security +**Goal**: Users can reach araharah through Telegram with a working command surface, and the backend's identity + privacy architecture is provably sound from the first deploy — the initData validator is the first backend artifact. +**Depends on**: Phase 1 +**Requirements**: ONBD-01, PRIV-01, PRIV-02 +**Success Criteria** (what must be TRUE): + 1. A new user sends /start and receives a concise explanation plus an always-available command menu (/help, /privacy) that answers correctly (ONBD-01) + 2. /privacy gives an honest, visible statement of what araharah stores and does not store (PRIV-01) — the in-app "trip ended, data deleted" messaging half completes with guidance in Phase 6, riding this requirement's message design + 3. Tampered, stale, and replayed initData payloads are rejected with CI test vectors and known-good HMAC cases passing; only validated identities receive a one-time session token (security gate — the phase's exit criterion) + 4. A storage spot-check shows KV with TTL-only namespaces and zero persistent coordinates or user profiles — privacy by construction holds from the first line of backend code (PRIV-02; re-audited in Phase 7) +**Plans**: TBD + +Notes: +- One Cloudflare Worker deployable (static assets + webhook + `/api/*`); KV `chat_sessions` (minutes TTL) is the first namespace; the `guidance_sessions` (~2h TTL) envelope is only designed with its consumer in Phase 5. +- Standard patterns (no research phase needed): grammY + Workers hosting is first-class documented; verify exact grammY initData typings at phase start (research gap). +**UI hint**: no + +### Phase 3: Mini App Shell + Geolocation +**Goal**: The Mini App opens inside Telegram, establishes a validated session, and obtains the user's live location reliably — with every fallback path that keeps location flowing when the primary path dies, verified on real devices. +**Depends on**: Phase 2 +**Requirements**: GEO-01, GEO-02, GEO-03, PX-02 +**Success Criteria** (what must be TRUE): + 1. On a real Android phone and iOS phone, the user grants location and sees their live position rendered on the Rams basemap; the permission grant persists across session restarts via LocationManager (version-gated) (GEO-01) + 2. When in-app location fails (Desktop Telegram without geolocation, or denied permission), the chat "send location" keyboard fallback recovers the origin and the app proceeds with it (GEO-02) + 3. Location denial shows a deliberate denied state (never a blank map), and the app renders correctly under Telegram light and dark themes while the map keeps Rams cartography constant (PX-02, platform themes) + 4. No coordinate written anywhere persists: storage remains TTL-ephemeral only, spot-checkable at phase exit (GEO-03) + 5. Device-matrix exit pass: Android + iOS + Desktop + plain browser each demonstrate boot → session → position, exercising the full fallback chain (pitfall research device-matrix criterion) +**Plans**: TBD + +Notes: +- Highest platform-integration uncertainty in the project — research recommends `/gsd-research-phase` (Android LocationManager stale-fix workaround, `getLiveData()` wrapper, WebView permission bridges, browser testing harness). +- BackButton wiring and safe-area groundwork are built here as shell infrastructure; the observable PX-01/PX-03 behaviors are claimed by Phase 6 where the full state graph exists. +**UI hint**: yes + +### Phase 4: Destination Search + KL Gazetteer +**Goal**: Users type a destination the way locals actually write it and get the right KL-metro landmark back, then step into the Mini App already aimed at their destination. +**Depends on**: Phase 3 +**Requirements**: SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03 +**Success Criteria** (what must be TRUE): + 1. Typing "KLCC" — plus the golden query set ("Sunway Pyramid", "DUKE", mall and kampung-style queries) — returns the right KL landmark in a shortlist (SRCH-01) + 2. Abbreviated, typo'd, and missing-space queries ("Jln Ampang" ↔ "Jalan Ampang", "Tmn", glued words) resolve to the same result as the canonical spelling (SRCH-02) + 3. Choosing a result sends a native venue card in chat confirming the destination before navigation opens (SRCH-03) + 4. Tapping through from the search result launches the Mini App with the destination preloaded — no re-entry in the webview (ONBD-02); adding araharah to the phone home screen and launching from there lands in the app ready to search (ONBD-03) + 5. The self-hosted Photon KL bake-off is concluded against the real-query acceptance corpus with the decision (and any gazetteer/fallback escalation) documented — the search-quality experiment closes, it doesn't stay open +**Plans**: TBD + +Notes: +- Budgeted bake-off: research recommends `/gsd-research-phase` (gazetteer sourcing/structure ~200 entries, Malay normalizer, photon-vs-fallback decision; funds a GraphHopper MY dump on the VPS). +- VPS provisioning (Photon + Valhalla hosting) begins here — free-first infrastructure mandate (Oracle Cloud Always Free candidate). +**UI hint**: no + +### Phase 5: Routing + Route Display +**Goal**: The product exists end-to-end: current location to Rams-drawn route with quiet alternative choices, on routing infrastructure fast enough for the guidance phase to build on. +**Depends on**: Phase 4 +**Requirements**: RTNG-01, RTNG-02 +**Success Criteria** (what must be TRUE): + 1. A user sees their calculated route drawn on the Rams-styled map — grayscale basemap grounding with the accent route line — from their current location to the chosen destination (RTNG-01) + 2. The user can choose among up to 3 alternatives presented as quiet Rams cards (time, distance, one-line difference) and the selection redraws (RTNG-02) + 3. The golden-route corpus (10–20 real KL origin/destination pairs) routes cleanly through self-hosted Valhalla (Malaysia extract) behind the Worker proxy — no dead ends, no geometry failures, latency and Worker subrequest budgets holding with instrumentation visible +**Plans**: TBD + +Notes: +- GUID-05/06 upstream design obligations land here deliberately: the route model carries step geometry + snapped-progress support from day one, and the ephemeral `guidance_sessions` KV envelope (id, chat ref, route snapshot ref, ~2h TTL) is designed here so the backgrounded turn-card service in Phase 6 has its session contract already defined. +- Standard patterns (no research phase needed): documented preprocess pipeline for Valhalla + the graph/tiles build; no exotic APIs. +**UI hint**: yes + +### Phase 6: Turn-by-Turn Guidance (Live Driving) +**Goal**: While driving, araharah behaves like real navigation — prominent maneuvers, silent self-healing recalculation, honest ETAs, haptic cues, seamless resume — and guidance survives the app being minimized via best-effort chat turn-cards. +**Depends on**: Phase 5 +**Requirements**: GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03 +**Success Criteria** (what must be TRUE): + 1. During a drive, the user sees a prominent next-maneuver banner (distance + arrow + street name) with a collapsible full maneuver list (GUID-01), ETA and remaining distance progressing with each location fix without visible whiplash (GUID-03), and a haptic cue at maneuver points (GUID-04) + 2. After a missed turn, the app silently recalculates from the current position — no asking, no blaming — and reroute storms are held back by the debounce/hysteresis state machine (GUID-02, verified via recorded-drive replays plus a real drive) + 3. Minimizing the app mid-drive switches the bot to pushing chat turn-cards (map snapshot + next maneuver + ETA, best-effort projection) for the remainder of the trip (GUID-05, served by the Phase 5-designed ephemeral guidance session); re-opening mid-trip resumes live guidance seamlessly at the progressed position (GUID-06) + 4. The Telegram BackButton walks the full app states (search → routes → guidance → back to search) and never dead-ends (PX-01 — full state graph only exists now); closing during guidance requires passing the "abandon route?" confirmation, with safe areas respected and vertical-swipe-close disabled during guidance (PX-03) + 5. Ending a trip deletes the ephemeral guidance session and shows the "trip ended, data deleted" messaging — completing the in-app half of PRIV-01's promise at the trip boundary +**Plans**: TBD + +Notes: +- Highest behavioral uncertainty (reroute triggers, ETA smoothing, battery) — research recommends `/gsd-research-phase` (backgrounded turn-card "best-effort projection" framing + static map snapshot generation; product decision needed for what "good enough" means minimized). +- Schedule slack budgeted here per research; backgrounded turn-cards are folded into this phase per roadmap instructions with the session contract pre-designed upstream (Phase 5). +**UI hint**: yes + +### Phase 7: Hardening + Private Launch +**Goal**: Real KL drivers get an honest, robust experience: every failure state designed, the privacy promise holding under audit, performance within free-tier budgets, and a known-limitations document that tells the truth — then the launch. +**Depends on**: Phase 6 +**Requirements**: PX-04 +**Success Criteria** (what must be TRUE): + 1. Guidance supports fullscreen and remains usable in landscape (driving posture) across the full real device matrix — Android, iOS, Desktop, browser (PX-04) — folded into the phase's device-matrix QA pass including the battery drain target (<10%/hr during guidance) + 2. Every empty/error/timeout/off-road/no-geometry state renders gracefully (no blank screens, no broken layouts); version-gating fallbacks behave sanely on older Telegram clients + 3. Privacy verification passes: an architecture audit shows no persistent per-user location history or profile anywhere — coordinates exist only in TTL-expiring KV, and logs carry no coordinate data (re-verifies PRIV-02, GEO-03 end-to-end) + 4. The golden-route regression pass is green, Worker budgets audit clean (subrequests/CPU, cache hit-rate), and the "known limitations" doc (OSM data gaps, no traffic confidence, no lane guidance) ships before the first real drivers +**Plans**: TBD + +Notes: +- No exclusive feature requirements beyond PX-04 — this phase hardens the outcomes of Phases 1–6 and is the last chance to catch the "looks done but isn't" failures for a navigation tool whose empty states ARE the polish surface. +**UI hint**: no + +## Requirements Coverage + +| Phase | Requirements | +|-------|--------------| +| 1 | DSGN-01, DSGN-02 | +| 2 | ONBD-01, PRIV-01, PRIV-02 | +| 3 | GEO-01, GEO-02, GEO-03, PX-02 | +| 4 | SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03 | +| 5 | RTNG-01, RTNG-02 | +| 6 | GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03 | +| 7 | PX-04 | + +**Coverage:** 22/22 v1 requirements mapped — no orphans, no duplicates. (PRIV-01's in-app trip-boundary messaging and PX-01/PX-03 groundwork are noted where they're staged, but each requirement maps to its owning phase exactly once.) + +## v1.x Candidates (post-v1, not roadmap phases) + +Per research: voice guidance (gated on iOS WKWebView TTS spike), live trip share via `sendLocation(live_period)`, toll vs toll-free toggle (Valhalla `use_tolls`), speed-limit display where OSM `maxspeed` exists. These hang off validated routing + guidance — plan a v1.x milestone after user validation, do not pull into the spine above. + +## Progress + +**Execution Order:** +Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 + +| Phase | Plans Complete | Status | Completed | +|-------|----------------|--------|-----------| +| 1. Design Tokens + Rams Foundation | 0/TBD | Not started | - | +| 2. Bot Skeleton + initData Security | 0/TBD | Not started | - | +| 3. Mini App Shell + Geolocation | 0/TBD | Not started | - | +| 4. Destination Search + KL Gazetteer | 0/TBD | Not started | - | +| 5. Routing + Route Display | 0/TBD | Not started | - | +| 6. Turn-by-Turn Guidance (Live Driving) | 0/TBD | Not started | - | +| 7. Hardening + Private Launch | 0/TBD | Not started | - | + +--- +*Roadmap created: 2026-10-22* diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md new file mode 100644 index 0000000..67cbcc3 --- /dev/null +++ b/.planning/codebase/ARCHITECTURE.md @@ -0,0 +1,151 @@ + +# Architecture + +**Analysis Date:** 2026-10-21 + +## System Overview + +This is a **pre-implementation / design-phase project**. There is no backend, runtime code, package manifest, build tooling, or test suite yet. The current "architecture" consists of: + +1. **Planning documents** at repo root (`DESIGN.md`, `IDEAS.md`) describing the product vision and target stack. +2. **Static HTML UI mockups** (one directory per screen) under `stitch_minimalist_route_navigator/`, each self-contained and openable directly in a browser. + +```text +┌──────────────────────────────────────────────────────────────┐ +│ Current State: Static UI Mockups │ +├──────────────────┬──────────────────┬────────────────────────┤ +│ Mockup screens │ Design system │ Planning docs │ +│ stich_.../*/ │ telemetry_rams/ │ DESIGN.md │ +│ code.html │ DESIGN.md │ IDEAS.md │ +└──────────────────┴──────────────────┴────────────────────────┘ + +┌──────────────────────────────────────────────────────────────┐ +│ Implied Target Architecture (from IDEAS.md) │ +├───────────────────┬──────────────────────┬───────────────────┤ +│ Frontend │ Backend │ Data / Infra │ +│ Telegram bot + │ OSRM routing │ Neon Postgres │ +│ optional PWA │ (traffic weighting) │ (PostGIS) │ +│ (Cloudflare │ RabbitMQ queue │ Cloudflare R2 │ +│ Pages) │ Resend email │ Maptiler tiles │ +└───────────────────┴──────────────────────┴───────────────────┘ +``` + +## Component Responsibilities + +| Component | Responsibility | File | +|-----------|----------------|------| +| `active_route_guidance/` | Turn-by-turn navigation HUD mockup: maneuver strip, incident telemetry band, map corridor viewport | `stitch_minimalist_route_navigator/active_route_guidance/code.html` | +| `navigate_map_overview/` | Full-map navigation screen mockup: route rendering, layer toggles, recenter control | `stitch_minimalist_route_navigator/navigate_map_overview/code.html` | +| `telegram_live_traffic_feed/` | Telegram-bot-styled traffic feed mockup: inline commands (`/traffic`, `/hazard`, `/status`, `/clear`), dispatch confirm | `stitch_minimalist_route_navigator/telegram_live_traffic_feed/code.html` | +| `community_incident_reporter/` | Incident-report flow mockup: hazard drawer, modal report, incident type selection | `stitch_minimalist_route_navigator/community_incident_reporter/code.html` | +| `telemetry_rams/DESIGN.md` | Formal design system spec (design tokens: colors, typography, spacing, breakpoints, component rules) | `stitch_minimalist_route_navigator/telemetry_rams/DESIGN.md` | +| `DESIGN.md` | High-level Rams design philosophy: palette, typography, iconography, interaction flows | `DESIGN.md` | +| `IDEAS.md` | Product vision, core principles, target stack outline, gamification and future ideas | `IDEAS.md` | + +## Pattern Overview + +**Overall:** Design-system-driven static mockup pattern (no application architecture exists yet). + +**Key Characteristics:** +- Each mockup screen is a **single self-contained HTML file** (`code.html`) with inline `