Tests 1 & 2 pass (subscribe + scheduled reminder delivery proven on-device). Gap resolved via quick tasks 260610-hbu (catch-up scan) and 260610-i4x (node-cron→setInterval). Tests 3/4/5 still pending (elapsed time / Android / two devices).
5.8 KiB
status, phase, source, started, updated
| status | phase | source | started | updated | |
|---|---|---|---|---|---|
| testing | 05-web-push-notifications |
|
2026-06-10T02:46:43Z | 2026-06-10T17:14:00Z |
Current Test
number: 3 name: iOS subscription health-check keeps subscription alive after 1+ week of inactivity expected: | After a week without opening the app, opening it again silently re-subscribes (if permission still granted) and notifications continue to be delivered. awaiting: user response
Tests
1. iOS PWA install → push subscription → 15-min reminder receipt
expected: After adding FamilySync to the Home Screen on an iOS 16.4+ device and tapping "Enable Notifications", a push notification appears on the lock screen ~15 minutes before a shared Family-calendar timed event starts. why_human: iOS-Safari standalone push delivery cannot be driven by playwright-cli per CLAUDE.md — requires a physical iOS device + Home Screen install. result: pass note: "PASS confirmed on a real iPhone via the SCHEDULED path (no manual trigger). Initially failed; two root causes found and fixed: (1) node-cron 4.2.1 skipped EVERY scheduled execution in the long-running API process ('missed execution' each tick) → replaced node-cron with setInterval in all 3 broker workers (quick 260610-i4x). (2) The reminder scan only checked a fixed [now+14,now+16] window with no catch-up, so a missed/late tick dropped the reminder permanently → added a catch-up window (now, now+16min] + per-uid exactly-once dedup (quick 260610-hbu). After redeploy, a shared-calendar timed event triggered a push reminder on its own (setInterval → catch-up scan → VAPID sign → Apple 201 → SW showNotification on the iPhone). Also required fixing a truncated VAPID private key in .env earlier." fix_commits: ["260610-hbu (catch-up + per-uid dedup)", "260610-i4x (node-cron→setInterval)"]
2. iOS push subscription does not receive NotAllowedError
expected: Tapping "Enable Notifications" on iOS in the installed PWA (or the Settings toggle) successfully calls pushManager.subscribe() without throwing NotAllowedError. Both vapidKey and swRegistration are pre-resolved in state before the tap. why_human: NEW-CR-01 fix is verified in code (zero awaits between tap and subscribe()), but runtime confirmation on a physical iOS device is the only way to close this. result: pass note: "Confirmed on a real iPhone (installed standalone PWA). Enable Notifications succeeded with no NotAllowedError; subscription persisted (push_subscriptions id 176, user 3, web.push.apple.com endpoint). Required first fixing a truncated VAPID private key in .env (was 30 bytes → restored to a valid matched 32-byte pair)."
3. iOS subscription health-check keeps subscription alive after 1+ week of inactivity
expected: After a week without opening the app, opening it again silently re-subscribes (if permission still granted) and notifications continue to be delivered. why_human: Requires real elapsed time and a physical iOS device. Cannot be simulated. result: [pending]
4. Android FCM: event-change push arrives after the other member modifies a calendar event
expected: When member A modifies a shared event title/time/location, member B receives a push notification on Android within the next 5-minute poll cycle, showing "A updated an event" with the event title. why_human: End-to-end push delivery through FCM to a real Android device with a subscribed session cannot be driven by playwright-cli. result: [pending] note: "Delivery chain to a real device (VAPID → push service → SW showNotification) is now proven via the iOS path; the Android-specific leg (FCM endpoint + a subscribed Android session) is still untested."
5. List-change push coalescing is observable
expected: Member B making 5 rapid grocery-list edits results in a SINGLE push notification to member A (not 5), naming the actor and the list, arriving after the 45-second coalesce window. why_human: Requires two devices/sessions, real timing, and real push delivery. Playwright-cli can exercise the API hooks but not multi-device push receipt. result: [pending]
Summary
total: 5 passed: 2 issues: 0 pending: 3 skipped: 0 blocked: 0
Notes
- Delivery pipeline PROVEN on a real iOS device (2026-06-10): iOS standalone-PWA subscribe →
push_subscriptionsrow → VAPID-signedweb-pushsend →web.push.apple.com201 → service-workerpushhandlershowNotification()→ notification on the iPhone lock screen. This is the core of Phase 5 and de-risks tests 4 and 5 (same chain, different trigger/endpoint). - Prereq fix applied: VAPID
.envprivate key was truncated (30 bytes); restored to a valid 32-byte key that pairs with the public key (verified via ECDH derivation). - Shared calendar wired: operator's "FamilySync" Fastmail calendar synced as
calendars.id=10, markedis_shared=1(D-16), giving reminders a real target.
Gaps
- truth: "A shared-calendar timed event triggers a push reminder ~15 min before start, delivered to subscribed devices"
status: RESOLVED 2026-06-10
reason: "Originally failed (scheduled reminder never fired). Two root causes found + fixed: (a) node-cron 4.2.1 skipped EVERY scheduled execution in the long-running API process → replaced with setInterval in all 3 broker workers (quick 260610-i4x, commit
d9efbc1); (b) reminder scan had no catch-up so a missed/late tick dropped the reminder → added catch-up window (now, now+16min] + per-uid exactly-once dedup (quick 260610-hbu, commit19d92c6). After redeploy, a real shared-calendar event triggered a push on the iPhone via the SCHEDULED path with no manual trigger." severity: major test: 1 artifacts: [apps/api/src/broker/reminderScheduler.ts, apps/api/src/broker/poller.ts, apps/api/src/broker/outboxWorker.ts] note: "Side benefit: the node-cron→setInterval fix also restores the CalDAV poller (5-min sync) and outbox drain (15s), which were ALSO being skipped by node-cron in the long-running process."