Skip to main content

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

EndpointCallerAuth method
/internal/*admin-dashboardX-Internal-Token
/health/*, /metricsK8s probes + PrometheusNo auth (cluster-internal)

No RBAC within this service — all /internal/* callers are considered trusted admin-dashboard.

3. PII Handling

PII typeWhere it appearsProtection
Email addressnotification_log.recipient_addressStored as ***@domain.tld (masked on write)
Phone numberSMS delivery call bodyNever persisted; providerMessageId only stored
Invoice contentEmail bodyRendered and sent; not stored in service; S3 URL only
User nameTemplate variablesHandlebars substitution; not stored in log

Raw recipient addresses appear only in:

  1. The in-flight delivery request (SendGrid / sms-orchestrator).
  2. In-memory during rendering.

Never logged, never stored in plaintext. Enforced by Pino transport redaction.

4. Encryption

ClassMechanism
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 keyVault secret/notif/sendgrid_api_key
sms-orchestrator API keyVault secret/notif/sms_api_key

5. Threat Model

ThreatControl
Notification spam via replayed NATS eventsDedup on source_event_id in notification_log; duplicate → SUPPRESSED
Unintended email to wrong recipientRecipient 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 previewPreview endpoint renders with sample data only; no real user data accepted in preview
CRITICAL alert suppressed by opt-outSYSTEM_SECURITY category ignores preferences; enforced in PreferenceResolver
SendGrid credential exposureVault-managed; never in env files or logs

6. GDPR

  • notification_log records: 90-day retention then partitions dropped.
  • On tenant_erased.v1 event: recipient_address already masked; account_id anonymized.
  • notification_preferences deleted on account erasure.