Notification Service — Security Model
Status: populated Owner: Platform Engineering + Security Last updated: 2026-04-18 Companion: 13 Security
1. Authentication
No public-facing endpoints. All internal endpoints protected by X-Internal-Token (Vault-injected shared secret, rotated monthly). Kubernetes NetworkPolicy restricts access to admin-dashboard pod only.
NATS consumer: cluster-internal TLS + Vault-managed credentials.
sms-orchestrator calls: service account API key with scope sms:send injected via Vault.
2. Authorization
| Endpoint | Caller | Auth method |
|---|---|---|
/internal/* | admin-dashboard | X-Internal-Token |
/health/*, /metrics | K8s probes + Prometheus | No auth (cluster-internal) |
No RBAC within this service — all /internal/* callers are considered trusted admin-dashboard.
3. PII Handling
| PII type | Where it appears | Protection |
|---|---|---|
| Email address | notification_log.recipient_address | Stored as ***@domain.tld (masked on write) |
| Phone number | SMS delivery call body | Never persisted; providerMessageId only stored |
| Invoice content | Email body | Rendered and sent; not stored in service; S3 URL only |
| User name | Template variables | Handlebars substitution; not stored in log |
Raw recipient addresses appear only in:
- The in-flight delivery request (SendGrid / sms-orchestrator).
- In-memory during rendering.
Never logged, never stored in plaintext. Enforced by Pino transport redaction.
4. Encryption
| Class | Mechanism |
|---|---|
| In-flight (all channels) | TLS 1.2+ |
| At rest (PG) | Transparent disk encryption |
| Secrets (API keys, tokens) | Vault → env injection at pod start |
| SendGrid API key | Vault secret/notif/sendgrid_api_key |
| sms-orchestrator API key | Vault secret/notif/sms_api_key |
5. Threat Model
| Threat | Control |
|---|---|
| Notification spam via replayed NATS events | Dedup on source_event_id in notification_log; duplicate → SUPPRESSED |
| Unintended email to wrong recipient | Recipient resolution only via auth-service (trusted source); no client-supplied recipient |
| Template injection (malicious Handlebars) | Templates only modified by platform.admin via admin-dashboard; X-Internal-Token protected |
| PII leak via template preview | Preview endpoint renders with sample data only; no real user data accepted in preview |
| CRITICAL alert suppressed by opt-out | SYSTEM_SECURITY category ignores preferences; enforced in PreferenceResolver |
| SendGrid credential exposure | Vault-managed; never in env files or logs |
6. GDPR
notification_logrecords: 90-day retention then partitions dropped.- On
tenant_erased.v1event:recipient_addressalready masked;account_idanonymized. notification_preferencesdeleted on account erasure.