Files
turnosxpress/openspec/changes/notification-redesign/proposal.md
T

5.5 KiB
Raw Blame History

Proposal: Notification System Redesign

Intent

The current notification system has three critical limitations: (1) notifications are sent synchronously during appointment lifecycle operations, blocking the API response; (2) the notification-sender worker only handles today's appointments with a global delay (no per-company throttling for WhatsApp rate limits); and (3) there are no per-company or per-client notification preferences — notifications are either on or off for the entire company. This redesign decouples notification delivery from business operations into a job-based, multi-channel, policy-driven system.

Scope

In Scope

  • New NotificationJob model: per-notification job records with status, channel, payload, retry state
  • New CompanyNotificationPolicy model: org-level defaults for channels, scheduling windows, WhatsApp throttle config
  • New ClientNotificationPreferences model: per-client opt-in/out per channel
  • New ClientCompanyNotificationOverride model: per-client per-org overrides
  • Policy resolution engine: Plan limits → Org override → Client prefs → Org default → System default
  • Redesigned notification-sender worker: MongoDB polling, per-company WhatsApp throttle (816s), multi-channel dispatch
  • Server integration: replace inline notification calls in Appointments with job creation
  • Multi-channel support: WhatsApp (Baileys), Email (DonWeb), System (in-app + Socket.IO)

Out of Scope

  • SMS channel (plan feature exists but not implemented today)
  • Notification templates / content builder
  • Client-facing notification preferences UI
  • Notification analytics / delivery reports
  • Push notifications (mobile)
  • Batch notification operations (e.g., "notify all clients about holiday")

Capabilities

New Capabilities

  • notification-jobs: Job creation, status tracking, retry logic, and lifecycle management for notification delivery
  • notification-policies: Company and client notification preferences, policy resolution hierarchy, channel configuration
  • notification-worker: Multi-channel job processor with per-company throttling and MongoDB polling
  • notification-integration: Server-side hooks that create notification jobs from appointment lifecycle events

Modified Capabilities

None — no existing specs in openspec/specs/.

Approach

Server (job creation): Replace inline NotificationsManager.send*() calls in Appointments.ts with NotificationJobService.createJob(). The service resolves the effective policy, checks plan limits, and persists a NotificationJob document. This makes API calls non-blocking.

notification-sender (worker): Poll MongoDB for status: "pending" jobs. Process per-company with configurable WhatsApp throttle (default 816s between messages for same company). Email and System channels have no throttle. Failed jobs retry up to 3x with exponential backoff.

Policy resolution: Resolve in order: Plan feature flags → ClientCompanyNotificationOverride (per-client per-org) → ClientNotificationPreferences (client global) → CompanyNotificationPolicy (org default) → System defaults (all channels on).

Migration: No data migration needed — no pending notifications exist. New models are additive.

Affected Areas

Area Impact Description
notification-sender/src/ New Complete rewrite: job polling, multi-channel dispatch, throttle
server/src/Models/Notifications/ Modified Add job creation service; existing adapters remain for direct sends
server/src/Models/Appointments/Appointments.ts Modified Replace inline sends with job creation calls
server/src/Models/Plans/Plans.interface.ts Unchanged Plan features already define channel support
New: server/src/Models/NotificationJobs/ New NotificationJob model + adapter
New: server/src/Models/NotificationPolicies/ New Company/Client policy models + resolution engine
New: notification-sender/src/Models/Jobs/ New Job polling model for worker

Risks

Risk Likelihood Mitigation
WhatsApp rate limit hit during high-volume periods High Per-company throttle (816s), exponential backoff on failures
Job queue grows faster than worker processes Medium Monitor queue depth; add alerting on backlog threshold
Policy resolution adds latency to appointment creation Low Resolution is a simple DB query cascade; cache per-request
Breaking existing notification behavior during transition Medium Feature flag: keep inline sends as fallback during rollout

Rollback Plan

  1. Disable job creation in server via feature flag (reverts to inline sends)
  2. Stop notification-sender worker
  3. Existing inline notification paths remain unchanged — no code removal needed until stable
  4. Job collection can be truncated without data loss (jobs are ephemeral)

Dependencies

  • MongoDB (shared across all modules) — already available
  • Baileys (txbot) — existing WhatsApp integration, no changes needed
  • DonWeb email API — existing integration, no changes needed
  • Socket.IO — existing in server, no changes needed

Success Criteria

  • Appointment creation/update/delete returns within normal latency (< 200ms)
  • WhatsApp messages for same company spaced ≥ 8s apart
  • Failed notifications retry up to 3x with exponential backoff
  • Policy resolution correctly cascades through hierarchy
  • Zero missed notifications during 24h soak test
  • notification-sender processes backlog within 5 minutes under normal load