Files
familysync/.planning/phases/18-auto-timezone-detection-and-ability-to-change-timezone/18-PLAN-INDEX.md
T

4.4 KiB

Phase 18 — Plan Index & Coverage Audit

Created: 2026-06-15 Plans: 4 (3 waves) Mode: standard · TDD mode ON · MVP off


Wave Structure

Wave Plans Autonomous Files (disjoint per wave)
1 18-01 (accessor + IANA validator, TDD) yes lib/householdTimezone.ts (+test)
2 18-02 (admin endpoints, TDD), 18-03 (broker wiring, TDD) yes, yes 02: routes/admin.ts (+test); 03: broker/reminderScheduler.ts + broker/outboxWorker.ts (+tests) — no overlap with 02
3 18-04 (PWA picker UI) no (human-verify checkpoint) pwa/api/client.ts, pwa/routes/AdminPage.tsx

Dependency rationale: 02 and 03 both depend only on the Wave-1 accessor and touch disjoint files → parallel in Wave 2. 04 depends on the 02 endpoint contract → Wave 3.


Artifacts This Phase Produces (MANDATORY)

Symbol / Artifact Kind File Plan
getHouseholdTimezone(db) function (async, → Promise) apps/api/src/lib/householdTimezone.ts 01
isValidIanaTimezone(tz) function (→ boolean) apps/api/src/lib/householdTimezone.ts 01
'household_timezone' app_config key string (new additive row, no migration) apps/api/src/db/schema.ts appConfig (existing table) 01/02
GET /api/admin/config/timezone route apps/api/src/routes/admin.ts 02
PUT /api/admin/config/timezone route apps/api/src/routes/admin.ts 02
POST /api/admin/config/timezone/seed route (no-overwrite seed, D-02/D-03) apps/api/src/routes/admin.ts 02
timezoneSchema Zod schema apps/api/src/routes/admin.ts 02
fetchAdminTimezone() client fn apps/pwa/src/api/client.ts 04
setAdminTimezone(timezone) client fn apps/pwa/src/api/client.ts 04
AdminTimezoneResponse interface apps/pwa/src/api/client.ts 04
Timezone section (aria-label="Timezone") UI component/section apps/pwa/src/routes/AdminPage.tsx 04
apps/api/tests/lib/householdTimezone.test.ts new test file 01

Test files extended (not new): apps/api/tests/routes/admin.test.ts (02), apps/api/tests/broker/reminderScheduler.test.ts + apps/api/tests/broker/outboxWorker.test.ts (03).


Multi-Source Coverage Audit

GOAL (ROADMAP Phase 18 goal)

"Auto-detect the household timezone and allow changing it" → COVERED: detection seed (D-02, Plans 02 seed endpoint + 04 detected-zone affordance); change (D-04, Plans 02 PUT + 04 picker); behavioral wiring (D-05, Plan 03).

REQ (phase_req_ids from REQUIREMENTS.md)

No REQ-IDs are mapped to Phase 18 in ROADMAP.md (confirmed: "Requirements: TBD"). Per the planning context, the D-01..D-07 decision set is the coverage contract — see CONTEXT below. Not a gap.

RESEARCH (18-RESEARCH.md features/constraints)

  • Single accessor getHouseholdTimezone + IANA validator → Plan 01.
  • GET/PUT endpoints on adminRouter, no new router → Plan 02.
  • Seed endpoint, additive/non-blocking (Phase 12 not yet executed) → Plan 02.
  • Rewire reminderScheduler:247 + outboxWorker:501,607 → Plan 03.
  • PWA picker, no new package, Intl-based → Plan 04.
  • No new npm installs (Package Legitimacy Audit: zero) → honored across all plans; T-18-SC = no-op.

CONTEXT (D-01..D-07 — the trackable decision contract)

Decision Covered by Where
D-01 single household app_config key household_timezone Plan 01 (key literal), Plan 02 (upsert) accessor + endpoints
D-02 browser-detect + seed at first run Plan 02 (seed endpoint), Plan 04 (detected-zone affordance) endpoints + UI
D-03 no auto-overwrite after seed Plan 02 (seed writes only if unset) seed endpoint
D-04 change via role-gated /admin Settings Plan 02 (requireAdmin endpoints), Plan 04 (Timezone section) endpoints + UI
D-05 stored TZ = source of truth, single accessor at both scheduler sites Plan 01 (accessor), Plan 03 (both sites route through it) accessor + broker
D-06 fallback chain when unset Plan 01 (verbatim fallback), Plan 03 (existing tests stay green) accessor + broker
D-07 do not touch display/timed-write path Plan 03 + Plan 04 (boundary as acceptance criterion) broker + UI

No unplanned items. Deferred Ideas (per-member timezones; driving display/timed off stored TZ) are correctly absent from all plans.