remarkbox/docs/tickets/10.md
russell@unturf.com f1cffe2e79 Resolve all 14 tracked tickets (T0-T13)
High priority fixes:
- T0: Profile page now filters comments by namespace (was leaking cross-site)
- T1: URI hostnames and namespace names normalized to lowercase (was causing
  duplicate threads and "stock comments" bug). Includes merge script.
- T2: Thread detail API now paginated with SQL-side filtering (was 502 on
  267+ reply threads)

Features:
- T3: GDPR account deletion (tombstone user with scrubbed PII) and data export
- T4: Customizable button text and comment labels per namespace
- T5: Self-service namespace deletion for owners
- T6: @mention notifications with profile links
- T7: Webmention receiving endpoint with h-card extraction
- T8: Configurable max nesting depth and collapse depth per namespace
- T9: AJAX thread title search to prevent duplicates
- T10: Browser push notification support (VAPID/service worker)

Docs and housekeeping:
- T11: Documented thread_uri behavior when moving embeds
- T12/T13: Drafted community replies for resolved feature requests
- Collapse depth defaults to infinite (load-more disabled unless configured)

364 tests pass, 4 skipped.
2026-02-01 20:02:47 -05:00

3.3 KiB

T10: Browser push notifications

Status: resolved Priority: low Source: meta 9b970f14-b1cd-11e7-8fca-040140774501 Filed: 2026-02-01

Problem

Users and moderators want browser push notifications in addition to email notifications, particularly for pending comments that need moderation approval.

Resolution

Implemented Web Push API with VAPID key support, service worker, subscription management, and integration with the existing notification system.

New files

  • remarkbox/lib/push.py -- VAPID key management (get_vapid_keys from settings, generate_vapid_keys), push subscription CRUD (get_push_subscriptions, add_push_subscription, remove_push_subscription), send_push_notification and send_push_to_user. Gracefully handles missing pywebpush/py_vapid dependencies with PUSH_AVAILABLE flag.
  • remarkbox/views/push.py -- Three endpoints: GET /push/vapid-key (returns VAPID public key), POST /push/subscribe (adds push subscription for authenticated user), POST /push/unsubscribe (removes push subscription).
  • remarkbox/static/js/push-sw.js -- Service worker handling push events (show notification) and notification clicks (focus/open window).

Modified files

  • remarkbox/models/user.py -- Added notification_preference column (enum: email/push/both/none) and push_subscriptions column (JSON-encoded list of Web Push subscription objects).
  • remarkbox/routes.py -- Added push routes: /push/vapid-key, /push/subscribe, /push/unsubscribe.
  • remarkbox/lib/notify.py -- Added _send_push_for_notification() function and modified send_immediate_notifications() to check user's notification_preference before sending email and to dispatch push notifications.
  • remarkbox/templates/user-settings.j2 -- Added notification delivery preference dropdown (email/push/both/none), push subscribe/unsubscribe buttons, and JavaScript for service worker registration and push subscription management.
  • remarkbox/views/authenticated/authenticated.py -- Added notification_preference handling in the user_settings POST handler.
  • remarkbox/models/meta.py -- Added "push" to NOTIFICATION_METHODS set.

How it works

  1. Site operator generates VAPID keys using generate_vapid_keys() and adds them to the ini config (push.vapid_private_key, push.vapid_public_key, push.vapid_contact).
  2. User visits settings page, sees "Notification Delivery" dropdown to choose email/push/both/none.
  3. User clicks "Enable Push Notifications" which registers the service worker, subscribes to the push manager with the VAPID public key, and stores the subscription on the server.
  4. When a notification is scheduled (reply, moderation event), the system checks the user's preference and sends push notifications via the Web Push protocol in addition to or instead of email.
  5. Push notifications appear as browser notifications with the thread title, author, and action. Clicking opens the relevant thread.

Dependencies

Push notifications require optional packages: pywebpush and py_vapid. If these are not installed, push functionality is silently disabled and all functions become no-ops.

Acceptance Criteria

  • Users can subscribe to browser push notifications
  • Push notifications sent for replies and moderation events
  • Users can choose between email, push, or both