Files
Lucas Berger 982438dc10 style(13-03): apply Prettier formatting across repo
Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
2026-06-11 20:35:18 -04:00

8.7 KiB

phase, slug, status, nyquist_compliant, wave_0_complete, created
phase slug status nyquist_compliant wave_0_complete created
5 web-push-notifications planned true false 2026-06-09

Phase 5 — Validation Strategy

Per-phase validation contract for feedback sampling during execution.


Test Infrastructure

Property Value
Framework vitest 4.x (API + PWA)
Config file apps/api/vitest.config.* / apps/pwa/vitest.config.* (existing)
Quick run command pnpm --filter @familysync/api test
Full suite command pnpm --filter @familysync/api test && pnpm --filter @familysync/pwa test
Estimated runtime ~30 seconds

Sampling Rate

  • After every task commit: Run quick run command for the touched workspace
  • After every plan wave: Run full suite command
  • Before /gsd-verify-work: Full suite must be green
  • Max feedback latency: 30 seconds

Per-Task Verification Map

Populated by the planner from PLAN.md tasks. Each task with <automated> verify maps to a row.

Task ID Plan Wave Requirement Threat Ref Secure Behavior Test Type Automated Command File Exists Status
05-01-T1 05-01 1 NOTIF-01/02/03 T-05-SC package legitimacy gate before install check node -e "...deps present..." pending
05-01-T2 05-01 1 NOTIF-01 T-05-01 VAPID private key never committed check grep VAPID_* .env.example pending
05-01-T3 05-01 1 NOTIF-01/02/03 T-05-02 safe generate+migrate (no db:push) check grep pushSubscriptions schema.ts; ls migrations/0003_*.sql pending
05-01-T4 05-01 1 NOTIF-01/02/03 RED scaffolds + setup truncation unit vitest run tests/lib/* tests/broker/* tests/routes/push.test.ts (RED) pending
05-02-F1 05-02 2 NOTIF-01/02/03 T-05-03/05 VAPID send + 410/404 prune unit vitest run tests/lib/pushDispatcher.test.ts W0 pending
05-03-F1 05-03 2 NOTIF-02 T-05-06/07 coalesce burst, suppress actor unit vitest run tests/lib/pushCoalescer.test.ts W0 pending
05-04-T1 05-04 3 NOTIF-01/02/03 T-05-09/10/13 user-scoped subscribe/unsubscribe integration vitest run tests/routes/push.test.ts W0 pending
05-04-T2 05-04 3 NOTIF-01/02/03 T-05-11/12 SW waitUntil + denylist build/grep pnpm --filter @familysync/pwa build + sw.ts greps pending
05-04-T3 05-04 3 NOTIF-01/02/03 T-05-09 tap-gated subscribe (desktop) human-verify (playwright-cli) playwright-cli subscribe round-trip pending
05-05-T1 05-05 4 NOTIF-02 T-05-14/15/16 access-scoped, self-suppressed unit vitest run tests/lib/listChangeDispatcher.test.ts W0 pending
05-05-T2 05-05 4 NOTIF-02 T-05-15 reorder-silent, check-notifies unit vitest run tests/routes/lists.test.ts partial pending
05-06-F1 05-06 4 NOTIF-01 T-05-17/18/19 shared-only (query), all-day excl, dedup unit vitest run tests/broker/reminderScheduler.test.ts W0 pending
05-07-F1 05-07 5 NOTIF-03 T-05-20/21/22 meaningful-only, actor-suppressed unit vitest run tests/lib/eventChangeDispatcher.test.ts tests/broker/sync.test.ts W0 pending
05-08-T1 05-08 6 NOTIF-01/02/03 T-05-23 silent re-subscribe (granted only) build/grep pnpm --filter @familysync/pwa build + hook greps pending
05-08-T2 05-08 6 NOTIF-01/02/03 T-05-25 master toggle drives DELETE build/grep SettingsSheet greps + build pending
05-08-T3 05-08 6 NOTIF-01/02/03 T-05-24 denied-banner OS-revoked-only (desktop) human-verify (playwright-cli) playwright-cli banner show/hide pending

Status: pending · green · red · ⚠️ flaky

Nyquist: no run of 3+ consecutive tasks lacks an automated verify. Every task carries an <automated> block; UI-only tasks pair a build/grep gate with a desktop playwright-cli human-verify (iOS-standalone is the only genuinely device-only check, deferred to the phase gate).


Wave 0 Requirements

  • web-push + @types/web-push installed in apps/api before any push-dispatch task (Plan 05-01 Task 1)
  • workbox-precaching / workbox-core / workbox-routing installed in apps/pwa before the SW migration (Plan 05-01 Task 1)
  • Test stubs: reminderScheduler, pushDispatcher (410/404 prune), pushCoalescer, eventChangeDispatcher, push route (Plan 05-01 Task 4)
  • VAPID test keypair fixture for unit tests — no network (apps/api/tests/fixtures/vapid.ts, Plan 05-01 Task 4)
  • push_subscriptions added to test/setup.ts afterEach truncation (Plan 05-01 Task 4)

Existing vitest infrastructure covers the rest.


Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
iOS standalone-PWA push delivery + visible notification NOTIF-01/02/03 iOS Safari standalone push cannot be driven by playwright-cli (device-only) Install PWA on iPhone (Home Screen), grant permission, trigger event reminder + list change, confirm visible notification
iOS subscription survives inactivity (health-check) NOTIF (success criterion 4) Requires real APNs + elapsed time on device Leave PWA idle, fire push after extended inactivity, confirm still delivered
iOS permission-denied banner + re-enable flow NOTIF (D-10) iOS standalone Settings deep-link is device-only Revoke notifications in iOS Settings, confirm banner + instruction sheet

Desktop/Chromium push flows (permission prompt, subscribe, dispatch, notificationclick deep-link, settings toggle, denied banner) ARE automatable via playwright-cli — Plans 05-04 Task 3 and 05-08 Task 3.


Validation Sign-Off

  • All tasks have <automated> verify or Wave 0 dependencies
  • Sampling continuity: no 3 consecutive tasks without automated verify
  • Wave 0 covers all MISSING references
  • No watch-mode flags
  • Feedback latency < 30s
  • nyquist_compliant: true set in frontmatter

Approval: planned