Repository navigation
feat(mobile): retry queued notifications for up to 30 minutes #200
Description
Current status (2026-10-16)
Completed within this ticket's written implementation and automated-test boundary. Checked criteria below refer to that boundary, not full physical-device acceptance. Real SQLite integration covers durable retries/restart, original expiry, deduplication, revoked recipients, revision fencing and independent installations. The live targeted receipt confirms accepted status, not live outage recovery.
Evidence: implementation merged in #206; acceptance checkpoint merged in #218. Candidate Server CI passed 90 mobile-push integration and 95 mobile-router tests. iOS CI passed 473 tests, zero skipped, including all three actual Rust ciphertext consumers. The unchanged Worker has 73 workerd plus one native ingress test; unchanged bilingual guidance has passing documentation CI. Local zh-Hans verification passed 64/64 and all six native redirect-boundary checks passed. Earlier-SHA Worker/docs results are reused evidence, not a fresh candidate-wide run.
The dedicated ServerBee Worker is deployed. One authorized real APNs sandbox test reached a dedicated Simulator: registration revision 2, persisted Server receipt accepted/Accepted, NSE-decrypted background presentation, and opening the existing notification from a terminated app into Settings. No simctl push injection was used. The system required side-swipe to open; earlier failed harness attempts remain recorded. Initial enqueue and raw APNs HTTP responses were not separately captured; the Server receipt reports the Relay/APNs verdict and still correctly says presentation=unobserved. The dedicated session was revoked and confirmed absent. This is not physical-device or production evidence.
Remaining live acceptance is retained in #205 and #196: Authorized isolated outage/restart/recovery and expiry observation. Closing this implementation ticket does not close or waive those gates.
Dated checkpoints below are historical. This status supersedes earlier statements that the Worker is undeployed or that all live APNs checks are unrun; production and physical-device gates remain pending.
Parent
Architecture decision update (2026-10-03)
The public stateless Worker decision in #196 and #206 removes Relay grants and their eligibility/renewal/revocation from this ticket. The durable outbox remains on the authenticated Server, with all account/session/installation, subscription, revision, and original-expiry checks retained. This update changes requirements; it does not mark any unchecked acceptance criterion complete.
What to build
A user's encrypted test notification survives a Server restart or temporary Relay outage, retries only while still eligible, and expires after 30 minutes. Turning off delivery or revoking the account prevents queued work from being sent.
Acceptance criteria
- Route the existing test-message operation through a durable encrypted outbox with stable logical event/installation identity, duplicate-enqueue protection, registration revision, and expiry 30 minutes after event creation.
- Resume pending deliveries after restart and retry transient network, rate-limit and provider failures with bounded backoff, timeouts, and concurrency; do not block event evaluation.
- Immediately before sending, revalidate user existence, current role, mobile-session validity, subscription, installation ownership, and registration revision; discard revoked, superseded, or otherwise ineligible work.
- Disabling notification delivery or logging out stops later eligible sends, including queued work; an already accepted APNs notification is not represented as retractable.
- Expose accepted, retryable, permanent, and expired status for the targeted test in iOS; distinguish provider acceptance from device presentation and do not promise exactly-once display.
- Invalidate device registration only for a classified terminal device condition and matching sending revision; token/key replacement survives late responses.
- Persist ciphertext rather than a second plaintext message history, and avoid leaking tokens, content keys, signing material or notification content through diagnostic output.
- Use the Server integration harness with real SQLite and a controllable external Relay boundary to verify restart, expiry, duplicate enqueue, revocation, token replacement, retries, and independent multiple-device outcomes.
Blocked by
- feat(mobile): deliver an encrypted test notification to one installation #199: feat(mobile): deliver an encrypted test notification to one installation
Implementation verification checkpoint (2026-10-03)
At ae5add35bb8b26c005b7a3d4c5dc173d22e949ee, main Server CI and Rust-to-Worker/iOS integration CI passed. The mobile push integration suite passed all 88 tests with none ignored, including identical_registration_preserves_retryable_test_and_alert_until_delivery and registration_identity_changes_bump_revision_but_exact_retries_do_not. The final registration regression preserves original queued ciphertext, registration revision and the original 30-minute expiry when an identical installation/token/environment/key/deployment tuple is registered again; changed tuples still fence stale work. Server-owned session/installation/subscription/revision and expiry checks remain independent of the removed Relay grants.
PR #206 records all 17 green checks. Live APNs provider acceptance/delivery, physical-device behavior and Worker deployment remain NOT RUN; acceptance checkboxes remain unchanged.
Activity