docs(05): create phase 5 web-push plan (8 plans, 6 waves)
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
---
|
||||
phase: 5
|
||||
slug: web-push-notifications
|
||||
status: draft
|
||||
nyquist_compliant: false
|
||||
status: planned
|
||||
nyquist_compliant: true
|
||||
wave_0_complete: false
|
||||
created: 2026-06-09
|
||||
---
|
||||
@@ -40,17 +40,36 @@ created: 2026-06-09
|
||||
|
||||
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|
||||
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
|
||||
| TBD | — | — | NOTIF-01/02/03 | — | — | unit | `pnpm --filter @familysync/api test` | ❌ W0 | ⬜ pending |
|
||||
| 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
|
||||
- [ ] Test stubs for reminder scheduler, push-dispatch (VAPID sign + send), and subscription pruning (410/404)
|
||||
- [ ] VAPID test keypair fixture for unit tests (no network)
|
||||
- [ ] `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.*
|
||||
|
||||
@@ -62,18 +81,19 @@ created: 2026-06-09
|
||||
|----------|-------------|------------|-------------------|
|
||||
| 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) ARE automatable via playwright-cli.*
|
||||
*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
|
||||
- [x] All tasks have `<automated>` verify or Wave 0 dependencies
|
||||
- [x] Sampling continuity: no 3 consecutive tasks without automated verify
|
||||
- [x] Wave 0 covers all MISSING references
|
||||
- [x] No watch-mode flags
|
||||
- [x] Feedback latency < 30s
|
||||
- [x] `nyquist_compliant: true` set in frontmatter
|
||||
|
||||
**Approval:** pending
|
||||
**Approval:** planned
|
||||
|
||||
Reference in New Issue
Block a user