Enhancement Proposal

Proposal: Notification delivery (email and SMS)

Verification codes (proposal 0003), reset links, MFA one-time-passwords (ADR-0020), and security/admin alerts all need a delivery channel — and there is none. This adds a pluggable delivery provider following the project's established trait-pluggability pattern (ADR-0013, exactly as KeyCustody and Authorizer do), so it does not invent a new architectural style.

Motivation

Several already-specced flows (recovery, MFA) assume a way to reach a user out-of-band. Operators must be able to choose their provider (SMTP, a hosted email service, an SMS gateway) rather than being locked to one.

Design

  • A NotificationDelivery provider trait (ADR-0013 pluggability pattern): email and SMS, with implementations (SMTP, hosted-email, SMS gateways); the dev profile uses a log/dev sink and needs no real provider.
  • Templated, localized messages (localization ownership: proposal 0007 — templates reuse the hosted-login localization mechanism, not a second one); per-realm sender identity and branding (ADR-0012).
  • Sends are events (ADR-0022) and rate-limited (proposal 0006); messages carry no secrets/PII beyond what the flow requires.
  • SMS is treated as a weak channel (SIM-swap, interception): fine for notifications and contact verification, discouraged as a primary MFA factor (ADR-0020).
  • SMS abuse is bounded at the delivery layer. SMS is also an outbound-cost attack surface — toll fraud / SMS pumping, where an attacker drives floods of verification messages toward premium or attacker-controlled number ranges to extract carrier revenue. The delivery layer therefore enforces per-destination and per-prefix velocity limits, a destination-country allow/deny list, and a per-realm send-cost cap, and feeds the adaptive-auth risk pipeline (ADR-0031) so a suspicious send pattern raises risk rather than silently burning budget. These are delivery-side controls layered on top of the flow-level rate limits (proposal 0006).

Alternatives considered

  • A single hard-coded provider — rejected; operator choice is the project's pluggability principle (ADR-0013, ADR-0008 control-resilience).
  • No SMS at all — rejected (some flows need it), but de-emphasised in favour of passkeys/TOTP.

Graduation criteria

Email and SMS send through a pluggable provider behind the trait; messages are templated and localized; the dev profile needs no real provider; sends are rate-limited and audited; SMS toll-fraud / pumping is bounded by per-destination velocity limits, a destination-country allow/deny list, and a per-realm send-cost cap.

Backward compatibility

Adds one pluggable provider trait per the established ADR-0013 pattern; no other architecture change.

Open questions

  • Whether the single new trait warrants a one-line ADR (it follows the existing pattern).
  • Bounce/deliverability handling and provider failover.