From 24f4589c4e4aa726653cffbe6cb86942b9bc15d8 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Wed, 10 Jun 2026 13:15:22 -0400 Subject: [PATCH] =?UTF-8?q?test(05):=20UAT=20Test=201=20PASS=20=E2=80=94?= =?UTF-8?q?=20scheduled=20reminder=20delivers=20on=20real=20iPhone=20after?= =?UTF-8?q?=20node-cron=E2=86=92setInterval=20+=20catch-up=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- .../05-web-push-notifications/05-UAT.md | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/.planning/phases/05-web-push-notifications/05-UAT.md b/.planning/phases/05-web-push-notifications/05-UAT.md index c1a1c9a..7d138aa 100644 --- a/.planning/phases/05-web-push-notifications/05-UAT.md +++ b/.planning/phases/05-web-push-notifications/05-UAT.md @@ -3,7 +3,7 @@ status: testing phase: 05-web-push-notifications source: [05-VERIFICATION.md] started: 2026-06-10T02:46:43Z -updated: 2026-06-10T16:25:00Z +updated: 2026-06-10T17:14:00Z --- ## Current Test @@ -20,10 +20,9 @@ awaiting: user response ### 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: issue -reported: "Scheduled 15-min reminder did NOT arrive at the window. node-cron logged 'missed execution' at 15:59/16:00/16:01 UTC (exactly the [now+14,now+16] reminder window). A manual scan with injected time found the event and dispatched to the same subscription → Apple 201 → the notification arrived on the iPhone. So delivery works; the scheduled trigger was dropped." -severity: major -root_cause: "Two factors. (1) node-cron missed the every-minute reminder tick during the window (intermittent — measured setInterval drift was negligible afterward and host/container clocks were in sync, so not sustained clock drift; likely transient tick starvation). (2) DESIGN: reminderScheduler scans only the fixed [now+14,now+16] window keyed to one exact tick, with no catch-up — a single missed/late tick drops the reminder permanently. Dispatch chain (VAPID sign → Apple → SW showNotification on iOS) is proven working." +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. @@ -50,8 +49,8 @@ result: [pending] ## Summary total: 5 -passed: 1 -issues: 1 +passed: 2 +issues: 0 pending: 3 skipped: 0 blocked: 0 @@ -65,11 +64,9 @@ blocked: 0 ## Gaps - truth: "A shared-calendar timed event triggers a push reminder ~15 min before start, delivered to subscribed devices" - status: failed - reason: "Scheduled reminder did not fire. node-cron missed the every-minute tick during the [now+14,now+16] window; the scan has NO catch-up, so the reminder was dropped permanently. Underlying dispatch+delivery verified working (manual trigger → Apple 201 → notification on the iPhone)." + 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, commit 19d92c6). 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/index.ts] - missing: - - "Resilient reminder scan: persist a last-scanned-time watermark and scan [lastScanned, now+16min] each run (keep the (uid, minuteBucket) dedup) so a missed/late cron tick is recovered on the next run instead of being lost." - - "Confirm node-cron tick reliability on the real Unraid host (the misses were observed on the WSL2 dev box; need to know if prod is affected)." + 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."