# 14. Backend Router — Email, Push, and SMS Notifications

meta:
  id: shieldai-unified-restructure-14
  feature: shieldai-unified-restructure
  priority: P1
  depends_on: [shieldai-unified-restructure-11]
  tags: [backend, notifications, email, push, sms, api]

objective:
- Build the tRPC router and service layer for sending notifications across all channels: email (Resend), push (FCM/APNs), and SMS (Twilio). Port logic from `packages/shared-notifications/` into a unified `notifications` router.

deliverables:
- `web/src/server/api/routers/notification.ts` — Notification router:
  - `notification.sendEmail` — `adminProcedure` (or internal service use) sending transactional email
  - `notification.sendPush` — `protectedProcedure` sending push to user's devices
  - `notification.sendSMS` — `protectedProcedure` sending SMS
  - `notification.registerDevice` — `protectedProcedure` registering FCM/APNs token
  - `notification.unregisterDevice` — `protectedProcedure` removing device token
  - `notification.listDevices` — `protectedProcedure` listing registered devices
  - `notification.getPreferences` — `protectedProcedure` getting notification preferences
  - `notification.updatePreferences` — `protectedProcedure` updating preferences
- `web/src/server/services/notification.service.ts` — Business logic:
  - `sendEmail(to, subject, html, text?)` — via Resend API
  - `sendPush(deviceTokens, title, body, data?)` — via FCM for Android, APNs for iOS
  - `sendSMS(phoneNumber, message)` — via Twilio
  - `registerDevice(userId, token, platform, deviceType)` — save to DB
  - `unregisterDevice(userId, token)` — soft-delete or mark inactive
  - `getPreferences(userId)` — read from DB
  - `updatePreferences(userId, prefs)` — write to DB
- `web/src/server/services/email.templates.ts` — Email template renderer:
  - Welcome email
  - Alert notification email
  - Password reset email
  - Family invite email
  - Billing receipt email
- Provider clients:
  - `web/src/server/lib/resend.ts` — Resend client
  - `web/src/server/lib/fcm.ts` — Firebase Admin SDK initialization
  - `web/src/server/lib/twilio.ts` — Twilio client

steps:
1. Install dependencies in `web/`:
   - `resend` (email)
   - `firebase-admin` (push notifications)
   - `twilio` (SMS)
2. Create provider client files:
   - `resend.ts`: initialize with `RESEND_API_KEY`
   - `fcm.ts`: initialize Firebase Admin with service account JSON
   - `twilio.ts`: initialize with `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN`
3. Create `web/src/server/services/email.templates.ts`:
   - Each template is a function returning `{ subject, html, text }`
   - Use simple HTML with inline CSS (or a minimal template engine)
   - Include ShieldAI branding (logo, colors)
4. Create `web/src/server/services/notification.service.ts`:
   - `sendEmail`: call Resend, log result, handle errors
   - `sendPush`: iterate device tokens, call FCM for Android tokens, APNs for iOS tokens (or use Firebase Admin which handles both)
   - `sendSMS`: call Twilio Messages API, validate E.164 phone format
   - `registerDevice`: upsert into `DeviceToken` table
   - `unregisterDevice`: set `isActive = false`
   - `getPreferences` / `updatePreferences`: read/write a `NotificationPreferences` table (add to schema if missing)
5. Create `web/src/server/api/routers/notification.ts`:
   - Define Zod schemas for all inputs
   - `sendEmail`: restricted to admin or internal service calls
   - `sendPush`: accepts `title`, `body`, `data` payload; sends to all active user devices
   - `sendSMS`: accepts `phoneNumber`, `message`
   - Device registration/unregistration procedures
   - Preference get/update procedures
6. Wire router into `web/src/server/api/root.ts`.
7. Write unit tests with mocked providers.

steps:
- Unit: `sendEmail` calls Resend with correct parameters
- Unit: `sendPush` iterates tokens and calls FCM
- Unit: `sendSMS` validates E.164 format before calling Twilio
- Unit: `registerDevice` creates DeviceToken record
- Unit: `unregisterDevice` marks token inactive
- Integration: `notification.registerDevice` persists token to DB

acceptance_criteria:
- [ ] Email can be sent via Resend with branded templates
- [ ] Push notifications can be sent to registered Android and iOS devices via FCM
- [ ] SMS can be sent via Twilio to valid E.164 numbers
- [ ] Device tokens can be registered and unregistered per user
- [ ] Notification preferences are persisted and respected (e.g., user can disable SMS alerts)
- [ ] All provider errors are caught and logged without crashing the app
- [ ] Email templates include ShieldAI branding

validation:
- Send a test email via Resend to your own address and verify receipt
- Register a test device token and send a push (use Firebase Console or API)
- Send a test SMS via Twilio (use test credentials for free)
- Run `cd web && pnpm test` for notification service tests

notes:
- Reference legacy: `packages/shared-notifications/src/`, `packages/api/src/routes/notifications.routes.ts`
- For FCM, Firebase Admin SDK requires a service account JSON. Store path in `FIREBASE_SERVICE_ACCOUNT_PATH` env var.
- For APNs, Firebase Admin can proxy to APNs if configured correctly. Alternatively, use `apn` npm package for direct APNs integration.
- Twilio test credentials (`TWILIO_TEST_*`) can be used for integration tests without sending real SMS.
- Resend has a generous free tier (100 emails/day) perfect for development.
- Consider adding a `notification.queue` table for reliable delivery (retry failed sends). This can be a follow-up task.
- The `NotificationPreferences` model may need to be added to the Drizzle schema if not already present. Add it as part of this task.
