# Roadmap — what V3 onwards might include

Planning document, not a delivery commitment. It frames where V2 sits today, what modern notification platforms typically provide, and which capabilities are plausible next steps for this service if product demand appears.

For architecture of the current system, see DESIGN.md. For resilience options already sketched, see High availability.


# Where we are (V2)

V2 is a standalone in-app notification inbox:

Capability Status
Server/API-key publish to a user inbox Done
User list / unread / mark read / delete Done
Idempotent publish (dedupeKey) Done
OIDC auth + publisher scopes / API keys Done
Typed npm client (retry, ETag polling, React hooks) Done
Legacy product V1 HTTP compatibility Done (/api/Notification/*)
Email, SMS, push, WhatsApp, Slack Out of scope
User preferences / mute / digest Out of scope
Realtime push (WebSocket / SSE) Out of scope (polling + ETag)
Pre-built bell UI / preference centre Out of scope
Workflows, templates, campaigns Out of scope

That is intentional. V2 fixed the embedded Video Library inbox (auth, dedupe, standalone service, client reliability). It is product notification infrastructure for an in-app feed, not a full multi-channel engagement suite.

Current HTTP surface: /v2/notifications…. A future major API would likely live under /v3 (or stay compatible and version capabilities behind feature flags) — naming is TBD when the first breaking change is real.


# What “modern notification platforms” are

Industry products fall into two layers people often confuse:

┌─────────────────────────────────────────────────────────────┐
│  Notification infrastructure (orchestration)                │
│  Knock · Novu · Courier · SuprSend · similar                │
│  workflows · preferences · templates · in-app feed ·        │
│  fan-out · digests · provider failover · observability      │
└───────────────────────────┬─────────────────────────────────┘
                            │ hands off delivery to
┌───────────────────────────▼─────────────────────────────────┐
│  Channel providers (pipes)                                  │
│  Email: SES / Resend / Postmark / SendGrid                  │
│  SMS: Twilio / MessageBird                                  │
│  Push: FCM / APNs / OneSignal                               │
│  Chat: Slack / Teams / WhatsApp Business                    │
└─────────────────────────────────────────────────────────────┘

Orchestration platforms (Knock, Novu, Courier, etc.) typically sell:

  1. One trigger API — fire an event; the platform decides channels, order, and fallbacks.
  2. Workflows — delays, conditions, batching/digests, cancel-on-read, branch on open/click.
  3. Templates — per-channel copy/layout; often editable by non-engineers.
  4. Preferences — per-user (and often per-tenant) channel and category opt-in/out, quiet hours.
  5. In-app feed + UI kits — bell, feed, preference centre components.
  6. Multi-channel delivery — email, SMS, push, chat, webhooks — via your provider accounts.
  7. Observability — per-message timeline: queued → sent → delivered → opened → failed.
  8. Tenancy / environments — sandbox vs prod, tenant branding, RBAC for operators.

Engagement / marketing platforms (Braze, OneSignal journeys, Klaviyo-style) emphasise campaigns, segments, and growth metrics more than transactional product events. Inovus products are closer to the transactional / product-notification side (case updates, assessments, reviews) than broadcast marketing.

V2 today is roughly the in-app feed + publish API slice of an orchestration platform — without channels, workflows, or preference UI.


# Capability map — us vs typical platforms

Capability Typical platforms Inovus V2 Candidate for V3+?
In-app inbox CRUD Yes Yes Extend (archive, categories)
Idempotent / deduped events Common Yes (dedupeKey) Keep as core contract
Multi-channel send Core product No High interest if apps need email/push
Workflows / journeys Core product No Medium — only if producers outgrow code
User preference centre Core product No High — before any second channel
Digests / batching Common No Medium — reduces noise
Realtime inbox updates Common Polling Medium — SSE when latency matters
Drop-in React bell UI Common Data hooks only Medium — optional package
Templates (email/push) Common No With channels
Delivery receipts / activity log Common API logs only Medium — ops + support
Batch / bulk publish Common Loop + dedupe Low until a producer needs it
Tenant branding / isolation B2B focus Multi-issuer ready; one DB Later — true multi-tenant
Marketing campaigns / segments Engagement tools No Likely never (wrong product)

# Guiding principles for V3+

  1. Stay the system of record for the inbox — even if email/push are added, the in-app row should remain the durable “what the user was told” record unless we deliberately split concerns.
  2. Preferences before channels — shipping email without mute/category controls creates support load and compliance risk (especially in healthcare-adjacent products).
  3. Orchestrate, don’t own every pipe — prefer adapters to SES/FCM/Twilio over building SMTP or APNs ourselves.
  4. Demand-driven milestonesDESIGN.md’s YAGNI list still applies; build when a named producer or product has a concrete need.
  5. Don’t become a marketing cloud — segments, A/B campaigns, and growth analytics belong elsewhere unless the business explicitly pivots.

# Candidate themes (V3 onwards)

Themes are ordered by how often real products hit them, not by a fixed release train. Several can ship as additive V2.x features; only breaking contract changes need a hard /v3.

# 1. Richer inbox semantics

Why: Users and apps outgrow binary read/unread.

Possible additions:

  • Categories / topics (assessment, system, billing) for filtering and preferences
  • Archive / snooze (soft state; retention still applies)
  • Severity-driven sorting or “needs attention” views
  • Actor / subject fields (who did what to which entity) beyond opaque metadata
  • Expiry / TTL per notification (in addition to global retention cron)

Trigger: Multiple apps need shared filter UI, or support asks for “hide without delete”.

# 2. User preferences and quiet hours

Why: Table stakes once anything leaves the in-app feed; also useful for in-app-only mute of noisy categories.

Possible model:

  • Per user: global mute, per-category channel matrix (in-app / email / push)
  • Quiet hours + timezone
  • Default policies per source or category (e.g. security alerts cannot be fully muted)

Trigger: Before first outbound email/SMS/push goes live.

# 3. Multi-channel delivery (email → push → chat)

Why: Users aren’t always in the SPA; clinical and ops workflows often need email or mobile push.

Possible shape:

Publish event
    → create/update in-app notification (always, if preference allows)
    → enqueue channel jobs (email / push / …) honouring preferences
    → provider adapters + retries + dead-letter

Phased rollout that matches industry practice:

Phase Channels Notes
A Email (transactional) Highest value for B2B SaaS; SES/Resend/Postmark
B Web Push / mobile push Needs device token registry
C Slack / Teams Useful for staff tools, not patients
D SMS / WhatsApp Costly; reserve for high-urgency

Keep provider failover and per-message delivery status in mind from day one of channel work, even if v1 of channels is email-only.

Trigger: A product owner requires “email me when X” with a real volume estimate.

# 4. Workflows, digests, and cancellation

Why: Modern platforms differentiate on logic, not just send.

Examples relevant to Inovus:

  • Digest: “N new assessment comments in the last hour” → one email + one inbox item
  • Delay + cancel: remind in 24h unless the case was already opened
  • Escalation: in-app first; email if still unread after N hours
  • Fan-out: one domain event → many recipients (batch API or queue)

Implementation options:

  • Code-owned workflows in producer apps (simplest; stays YAGNI-friendly)
  • Declarative workflows in this service (Knock/Novu-style) when many apps need the same patterns

Trigger: Three or more producers re-implement the same delay/digest/escalate logic.

# 5. Realtime delivery

Why: Polling is proven and cheap; some UX wants sub-second bell updates.

Options already noted in DESIGN.md / HA docs:

  • SSE or WebSocket via Cloudflare Durable Objects (or similar), behind the existing client subscribe() API
  • Supabase Realtime only if we accept coupling and Cognito≠Supabase JWT constraints

Trigger: Measured UX requirement for < a few seconds latency, not “realtime because platforms have it”.

# 6. Client and UI kit

Why: Competitors ship embeddable inbox + preference centre; we ship data hooks only.

Possible packages:

  • Headless hooks stay default
  • Optional @inovus-medical/notifications/ui (or similar): accessible bell, feed, empty states, preference panel — themeable, no hard Totum branding lock-in
  • Better multi-tab sync (BroadcastChannel) and visibility-aware polling

Trigger: Two or more apps copy-paste the same bell implementation.

# 7. Producer DX and throughput

Why: Platforms invest heavily in the send path.

Possible additions:

  • POST /v2/notifications/batch (or /v3) for fan-out
  • Queue-backed publish (Cloudflare Queues) for spikes and channel fan-out
  • Idempotent workflow keys (cancel/replace in-flight digests)
  • Official server SDKs beyond the isomorphic fetch client (if non-TS producers appear)
  • Richer OpenAPI examples and contract tests for channel payloads

Trigger: Sustained publish rate or fan-out size that makes per-row HTTP loops painful (DESIGN.md already cites ~>10/sec sustained as a revisit point).

# 8. Observability and support tooling

Why: “Did the user get it?” is the first question in production incidents.

Possible additions:

  • Per-notification delivery timeline (inbox created, email queued/sent/bounced)
  • Admin/support lookup by userGuid + dedupeKey (strictly audited)
  • Metrics: publish rate, unread age, channel failure rate, preference opt-out rates
  • Correlation IDs from producer → inbox → channel send

Trigger: Support cannot answer delivery questions from existing Worker/Supabase logs.

# 9. Tenancy, environments, and compliance hardening

Why: B2B notification platforms treat tenancy as a first-class object.

Possible additions:

  • Explicit tenant/org dimension on notifications and preferences
  • Separate staging/prod notification projects (already partly true via Worker envs)
  • Data residency / retention policies per tenant
  • Stronger audit trails for publish and preference changes
  • Align with whatever Inovus needs for SOC2 / clinical safety narratives

Trigger: A second business unit or customer requires isolation beyond “different Cognito issuers”.


# Suggested sequencing (if we pursue V3 broadly)

A pragmatic order that matches how Knock/Novu/Courier-shaped systems grow, while respecting our medical/B2B context:

1. Categories + preferences (+ quiet hours)
2. Email channel + delivery status (transactional only)
3. Digests / delay-and-cancel for the noisiest producers
4. Optional UI kit (bell + preference centre)
5. Realtime subscribe transport
6. Push / chat channels as demand appears
7. Declarative workflows only if code-owned flows proliferate
8. Deeper tenancy / compliance as org structure requires

Items can be skipped or reordered. A thin batch publish or SSE slice can jump the queue if a single producer is blocked.


# Explicit non-goals (unless strategy changes)

  • Replacing company-wide marketing automation (newsletters, cart-style journeys, ad audiences)
  • Owning email/SMS provider infrastructure end-to-end (we should wrap vendors)
  • Guaranteeing mobile OS-level push without app teams owning FCM/APNs credentials and consent UX
  • Pixel-perfect parity with Knock/Novu/Courier feature matrices — we should stay right-sized for Inovus products

# How to use this document

Audience Use
Product Prioritise themes against real user/producer pain; ignore shiny multi-channel until preferences exist
Engineering Treat sections as option sketches; new work still needs DESIGN updates + changesets for the client
Agents / implementers Do not build from this file alone — wait for an explicit implementation brief

When a theme is green-lit, update DESIGN.md (scope + trade-offs), add acceptance criteria, and decide whether the HTTP API stays on /v2 (additive) or needs a /v3 break.


  • DESIGN.md — current V2 architecture and explicit out-of-scope list
  • Why V2 — why the standalone inbox exists
  • High availability — resilience options that overlap with scale/realtime work
  • App integration — how producers and SPAs use V2 today
  • Industry references for vocabulary (not endorsements): Knock, Novu, Courier, OneSignal (push/engagement-leaning)