# Architect — F-024 Notifications: transactional email ## Feature F-024 sends transactional emails driven by domain events with idempotency per event id and a swappable provider. ## Design ### Module boundaries Create `project/src/modules/notifications/` with domain/application/infrastructure/api/tests. Notifications owns message persistence and provider dispatch; domain code uses only the `EmailProvider` interface. ### Data model Add migration `018_notifications.js`: - `notifications_messages`: id, event_id text unique, channel text default 'email', template text, recipient text, subject text, body text, status text default 'sent', created_at timestamptz. - UNIQUE `event_id` for idempotency. ### Templates - `order_confirmation`, `payment_failed`, `order_shipped` mapped to events `OrderPaid`, `PaymentFailed`, `OrderShipped`. ### API - Internal `/notifications/dispatch` (admin/test) to trigger a dispatch by template and recipient. - Internal `/notifications/messages/:eventId` to inspect dispatch status. ## Acceptance trace - PaymentSucceeded -> order_confirmation email queued, idempotent on event_id. - Replay same event -> no duplicate row. - Provider swap touches only infrastructure.