- New: docs/ARCHITECTURE.md, docs/GETTING-STARTED.md, docs/DEVELOPMENT.md, docs/TESTING.md, docs/CONFIGURATION.md (colored mermaid diagrams, quoted labels) - Regenerated README.md (arah² / arah2bot naming, canonical clone URL) - New per-package READMEs: theme/, bot/, web/ - Verified 13 docs against the live codebase (2 fix iterations + 2 residual corrections); corrected 56 stale claims across AGENTS/DESIGN/IDEAS/GSD_FIX
215 lines
19 KiB
Markdown
215 lines
19 KiB
Markdown
# 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
|
||
- [x] **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 (completed 2026-10-23)
|
||
- [ ] **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:
|
||
- [x] 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)
|
||
- [x] 01-02-PLAN.md — Component sheet: `theme/src/components.css` + `sheet.html` consuming tokens only (D-03/D-11)
|
||
- [x] 01-03-PLAN.md — Rams basemap: token-derived OpenFreeMap liberty fork + KL preview (D-08/09/10)
|
||
- [x] 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**: 3 plans
|
||
|
||
Plans:
|
||
- [x] 02-01-PLAN.md — bot workspace scaffold + Wave-0 test harness (RED initdata suite)
|
||
- [x] 02-02-PLAN.md — initData HMAC validator (rejection classes) + TTL-only KV sessions (GREEN)
|
||
- [x] 02-03-PLAN.md — command surface (en/ms, aliases) + Worker wiring (/telegram/webhook, /api/session) + deploy checkpoint
|
||
|
||
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**: 4 plans
|
||
|
||
Plans:
|
||
|
||
**Wave 1** (baseline):
|
||
- [x] 03-01-PLAN.md — `web/` workspace + Wave-0 test runner; TTL-only location-pin KV, GEO-02 chat keyboard handler, and the `GET /api/location` relay route
|
||
|
||
**Wave 2** *(blocked on Wave 1 completion)*:
|
||
- [x] 03-02-PLAN.md — Location chain: three source adapters normalizing to one `Fix`, the D-04 state machine with freshness as a separate axis, memory-only session store, Telegram platform wrappers, Mock-Telegram harness, and the GEO-01/02/03 + PX-02 gates
|
||
|
||
**Wave 3** *(blocked on Wave 2 completion)*:
|
||
- [x] 03-03-PLAN.md — Rams shell: UI-SPEC copy module, token-only stylesheet, MapLibre v6 bootstrap with the WebGL2 gate, marker/follow/recenter, status strip and state cards, and the map-first boot choreography
|
||
|
||
**Wave 4** *(blocked on Wave 3 completion)*:
|
||
- [x] 03-04-PLAN.md — Worker `[assets]` binding + one-command deploy + D-14 build-artifact gate; Playwright capture harness with the GEO-03 runtime probe; blocking device-matrix exit gate
|
||
|
||
Cross-cutting constraints (truths appearing in 2+ plans, binding at every wave):
|
||
- denied/blank is forbidden — every dependency-failure state renders a deliberate Rams surface (03-02, 03-03, 03-04)
|
||
- zero coordinate persistence — TTL-ephemeral KV only; grep gate + runtime probe (03-01, 03-02, 03-03, 03-04)
|
||
- Rams token-only styling — Telemetry Rams tokens binding over skill defaults (03-02, 03-03, 03-04)
|
||
|
||
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.
|
||
- Research findings that shaped the plan: `getLiveData()` does not exist (D-05's gated streaming is our own `Fix`-shaped abstraction with a pluggable cadence — Phase 6 picks poll vs `watchPosition`); the Android stale-fix inverts the naive D-04 chain reading, so freshness is a separate axis from availability; Desktop Telegram has no geolocation at all (issue #77), making the chat-keyboard path the only Desktop origin; `GET /api/location` is required scope; MapLibre v6 is ESM-only and WebGL2-only (the map-less shell state is a deliberate `--color-surface-dim` field, not a crash); Bot API 10.2's origin restriction is enforced as of 2026-07-20.
|
||
- 03-04 task 3 is a **blocking human checkpoint**: real Android, iOS, and Telegram Desktop are listed in RESEARCH as required with no fallback. If no device is available, Success Criterion 5 is recorded UNVERIFIED and the phase is held open rather than silently closed.
|
||
**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/4 | Ready to execute | - |
|
||
| 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*
|