# Notification integrations — setup and current limits

## SMS (including OTP for feature phones)

No provider is selected or represented as live. Firebase Cloud Messaging is not SMS. Before selection, review official provider documentation and confirm +255 delivery, sender-ID approval, delivery receipts/webhook signing, pricing/quotas, privacy/security, Tanzanian legal and communications requirements, and support process.

The replaceable adapter currently expects `POST SMS_API_URL` with a bearer token and JSON shaped as `{ "to": "+255…", "message": "…", "sender_id": "…", "idempotency_key": "…" }`. Provider-specific request/response mapping must be checked against the chosen gateway. A generic HTTP 2xx means only provider acceptance; the outbox status is `submitted`, not `delivered`. Timeout outcomes are `unknown` and are not blindly retried, avoiding duplicate messages when provider outcome is uncertain. Definite failures retry up to five times with delay.

A generic signed callback is implemented at `POST /api/v1/provider/sms/status`. Configure `SMS_WEBHOOK_SECRET`; send `X-SMS-Signature` as the lowercase hex HMAC-SHA256 of the exact raw request body. JSON requires `event_id`, `idempotency_key`, and `status` (`submitted`, `delivered`, or `failed`), with optional provider reference and observed timestamp. This contract is not a provider integration: verify the provider's canonical signing scheme, event mapping, timestamp/replay protections, and callback behavior; implement a provider-specific adapter if it differs. Test duplicates, out-of-order events, retries, and forged callbacks before launch.

Phone verification and password-reset codes are generated as one-time, expiring challenges with hashed code verification and attempt limits. SMS outbox payloads for those two templates are encrypted at rest and are decrypted only by the delivery adapter. Registration does not mark phone verified; the user must complete the authenticated OTP flow. Default `SMS_DRIVER=log` sends nothing and the API must not be represented as delivering SMS until a real gateway is configured and tested.

Configuration: `SMS_DRIVER=log` (safe default), `SMS_API_URL`, `SMS_API_KEY`, `SMS_SENDER_ID`, `SMS_WEBHOOK_SECRET`, `SUPPORT_PHONE`. Keep values in server environment/secret store only. In production, first test with provider sandbox/test numbers. Essential messages should be tested in Kiswahili and English on actual phones, including Unicode multipart behavior and cost.

Queue processing: `php artisan notifications:process --limit=100`, scheduled each minute using Laravel scheduler. Cron: `* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1`. Do not expose scheduler publicly. Use a persistent worker/supervisor if appropriate for the target VPS; test database locking/idempotency under concurrent workers.

## Firebase Cloud Messaging

1. Create a Firebase project and Android app with package `com.sokokilimo.app`; review Firebase terms, quotas and availability.
2. Place the downloaded `google-services.json` at `android/app/google-services.json` (excluded from the repository). Gradle applies Google's Services plugin when this file exists. Without it, the app builds without Firebase initialization; push token registration will not be active.
3. Create a restricted service account for server-side FCM sends. Store its JSON outside the public web root; configure `FCM_PROJECT_ID` and `FCM_CREDENTIALS_PATH` on the server. Never package server credentials in the APK.
4. Build and test on a real device: sign in/register, token registration, token refresh/removal, notification permission denied/granted, foreground/background delivery, tap-through and language. Server API supports authenticated `POST /api/v1/devices` and `DELETE /api/v1/devices`; the app attempts registration after authentication and token refresh.
5. Provider response status is `submitted`; FCM acceptance is not proof a user saw a notification. Push and ordinary SMS are separate channels.

FCM and SMS credentials are not present in this workspace. No provider messages were sent or verified.
