Skip to main content

Communication Service — Security Model

Status: populated Owner: TBD Last updated: 2026-04-17 Companion: Service Template · 13 Security

1. RBAC / ABAC matrix

ActionDOCTORNURSECARE_COORDINATORPATIENTADMINSERVICE
Create threadvia portal BFF only
Send message in thread✓ if participant✓ if participant✓ if participant✓ if patient-linked participant✓ if participant
Read thread (patient-linked)✓ iff chart:read on patient✓ iff chart:read✓ iff chart:read✓ iff own patientId✓ (audit)
Escalate thread
Submit notification intent
DLR callbackprovider-secret
Admit virtual participant✓ (provider role)
View virtual-session list✓ own sessions✓ own✓ own✓ own (identity-bound)✓ all
End virtual session✓ (provider)

ABAC overlays:

  • Patient-link: any thread operation on a patient-linked thread requires chart:read on that patient (FR-COMMS-MSG-003 / BR-MSG-002).
  • Tenant scope: all operations scoped by tid from JWT; cross-tenant thread participants forbidden.
  • Identity-bound PATIENT: PATIENT role can only query sessions / threads where they are a participant (FR-DCOM-018).

2. Encryption

DataAt restIn transit
messages.bodypgcrypto AES-256 (column-level) or PG TDE; key via KMSTLS 1.2+
message_attachments blobsS3/MinIO SSE-KMSTLS 1.2+; presigned URLs ≤ 15 min
notification_intents.variablesAt-rest; must not carry PHITLS 1.2+
virtual_sessions.room_refPlain (no PHI)TLS 1.2+
Join tokensSigned with KMS private key (RS256); embed in URL for ≤ 5 minHTTPS only
DLR callback secretTenant-scoped HMAC signing keyTLS 1.2+; HMAC validated

3. Audit events

EventWhen
audit.communication.thread.accessRead thread
audit.communication.thread.patient_linked.accessRead a patient-linked thread (accounting of disclosures)
audit.communication.message.sentSend
audit.communication.attachment.uploadedUpload finalized
audit.communication.notification.dispatchedIntent dispatched (metadata only)
audit.communication.virtual_session.startedVC started
audit.communication.virtual_session.recording.accessRecording viewed
audit.communication.gdpr.thread.anonymizedGDPR anonymization

4. GDPR / data subject participation

RequestBehavior
ExportReturn all threads where subject is participant + all intents with recipientRef hash matching subject
ErasureAnonymize messages.sender_id and replace body with redaction marker; drop dispatch_records.recipient_ref; preserve structural audit per legal hold
RectificationParticipant metadata updates only; message bodies are immutable (correction via new message + retracted status on old)

5. Data residency

  • Messages and virtual-session metadata stored in the same region as the owning tenant's primary patients schema (Afghanistan / UAE / EU / US zones).
  • SMS dispatch via Ghasi-SMS-Gateway remains in-country for Afghan tenants. International fallback only with tenant opt-in.
  • Email via regional SES where possible.

6. Rate-limiting & abuse prevention

  • Per-user message send: 60/min (burst 120).
  • Per-tenant intent submit: 10000/min.
  • DLR callback endpoint: HMAC + IP allowlist per provider.
  • Failed-send anomaly detection: alert if failed / dispatched > 0.2 over 5 min for any (tenant, channel) pair.

7. Threat model highlights

ThreatMitigation
PHI leak in push payloadTemplate system disallows free-form PHI variables; structured logs sanitized
Enumeration of patient threadsTenant-scoped RLS + participant check; 404 not 403 on non-member
Replay of DLR callbackHMAC + timestamp window + idempotency on providerMessageId
Join-token theftShort TTL, one-time use, bound to session + participant
Cross-tenant participant injectionServer validates every participantId belongs to same tenant