SRV-08 — Jobs & notifications infrastructure
BullMQ queues and scheduler, transactional outbox, notification service (inbox, FCM push, SMS, email adapters with dev simulators), templates and the event → channel matrix.
| Field | Details |
|---|---|
| Task code | SRV-08 |
| Phase | P0 — Foundations (cadrage, UX/UI, architecture & contract) |
| Product scope | V1 |
| Status | Done (Mon 19 Oct 2026) |
| Start | Mon 19 Oct 2026 |
| Due | Mon 19 Oct 2026 |
| Responsible | Anis — Full-stack developer |
| Co-responsible | — |
| Effort | 1.25 person-day(s) planned · 6 from scratch · size S |
| Area · app | Server · server |
| Depends on | SRV-07 |
| Unblocks | SRV-24, SRV-39, SRV-40 |
| Milestones | — |
Summary
BullMQ queues and scheduler, transactional outbox, notification service (inbox, FCM push, SMS, email adapters with dev simulators), templates and the event → channel matrix.
Description
Notifications, SSE, analytics aggregates, CRM automation and scheduled rules all run in the worker process, driven by events (NOT-01…NOT-04, INT-02…INT-04, cahier §8, §11). This task builds the BullMQ queues and the repeatable scheduler, the transactional outbox (OutboxEvent written in the same transaction as the change, dispatched by the worker with retries and a dead-letter state), and the notification service: in-app inbox (Notification), per-channel deliveries (NotificationDelivery), localised templates (NotificationTemplate per event × channel × locale), the event → channel → recipient matrix (NotificationRule), user preferences (NotificationPreference, marketing opt-out) and adapters for FCM push with deep links, SMS (provider closed in PRJ-03) and email, each with a dev simulator. It implements the reseller/delegate inbox endpoints. Out of scope: the SSE streams themselves (SRV-26) and template content for every event (filled by each module).
Subtasks
| # | Subtask | Owner |
|---|---|---|
| 1 | BullMQ setup: queues outbox, notifications, pdf, exports, imports, images, scheduled; retry/backoff policies; Bull Board behind staff auth | Anis |
| 2 | Outbox writer helper (inside Prisma transaction) and dispatcher (poll + LISTEN/NOTIFY) with ordering per aggregate, retries and DEAD state | Anis |
| 3 | Repeatable scheduler registry for module jobs (orders.expireAssisted every 15 min, promotions.applySchedule every minute, support.autoClose daily, purges) | Anis |
| 4 | Notification service: rule resolution (event → channels → recipients), preferences and quiet hours for PROMOTIONAL, inbox write, delivery fan-out | Anis |
| 5 | FCM adapter (firebase-admin) with deep-link payloads, token invalidation on UNREGISTERED, per-device delivery status | Anis |
| 6 | SMS adapter interface + provider implementation + dev simulator; email adapter (SMTP/provider, Mailpit locally) | Anis |
| 7 | Template engine with fr/ar/en variants and variables (order number, status label from enums.json) | Anis |
| 8 | Endpoints notifications.list, unreadCount, markRead, markAllRead, preferences.get/update | Anis |
| 9 | Push payload and deep-link format review for both Flutter apps | Imad |
Deliverables
- apps/server/src/platform/{queues.ts,scheduler.ts,outbox/}
- apps/server/src/modules/notifications/{service.ts,rules.ts,templates/,adapters/{fcm,sms,email}.ts,router.ts}
- Notifications matrix page /docs/srs/notifications-matrix aligned with the seeded rules
Acceptance criteria
- An event written in a rolled-back transaction is never dispatched; a committed event is dispatched at least once and consumers are idempotent by event id
- A failing consumer is retried with backoff and lands in DEAD after the last attempt, visible in Bull Board
- A reseller who opted out of PROMOTIONAL receives no promotional push but still receives TRANSACTIONAL ones (NOT-06)
- An order status event produces an inbox entry and a push with a deep link to the order (NOT-01, NOT-02)
- OTP SMS uses the SMS adapter; in dev the code is printed instead of sent (NOT-03)
Requirements covered
| Requirement | Title | Release |
|---|---|---|
| NOT-01 | In-app notification inbox with read/unread in every app | V1 |
| NOT-02 | Push notifications (FCM) with deep links | V1 |
| NOT-03 | SMS for OTP and critical messages; email for staff and documents; WhatsApp share links | V1 |
| NOT-04 | Event → channel → recipient matrix and localised templates | V1 |
| INT-02 | Firebase Cloud Messaging | V1 |
| INT-03 | SMS gateway for OTP, invitations, confirmations and reminders | V1 |
| INT-04 | Transactional email | V1 |
| NOT-05 | Automatic notifications on order changes, assignments, follow-ups and promotions | V1 |
API surface
| Endpoint group | Operations |
|---|---|
| Notifications & announcements | 10 |
Test measures
- Integration tests with real Redis and Postgres for outbox dispatch, retries and dead-lettering
- Unit tests for rule resolution and preference filtering
- Manual check: push received on an Android test device from staging
Risks
- SMS provider approval and sender-id registration take weeks — start the request right after PRJ-03 and keep the simulator on staging until approved
KPI
- Delivered by Mon 19 Oct 2026 within 1.25 person-day(s).
- Every acceptance criterion above demonstrated before hand-off; linked requirements' acceptance criteria pass.
- Zero open critical defects, permission gaps or data-integrity regressions at sign-off.
Generated from content/plan/tasks.json by scripts/generate-team-tasks.mjs. Dates are computed by the scheduler (Sunday–Thursday weeks, holidays excluded) — change the plan, not this page.
SRV-07 — Platform services — audit, numbering, settings, files, PDF
Audit journal writer, sequential business numbers, typed settings service, S3 pre-signed uploads with thumbnails, PDF rendering base for invoices and delivery notes.
OPS-02 — CI/CD & environments — staging, pre-production, production
GitHub Actions gates, Docker images, Dokploy apps for staging (dev branch) and production (master), domains and TLS, secrets, nightly backups to object storage, docs deployment.