Skip to main content

Virtual Care Service — Security Model

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 13 security-compliance-tenancy

1. RBAC / ABAC Matrix

PermissionRolesConditions
virtual_care:session:createclinician, scheduler, nurse_practitioner, adminTenant licensed; patient consent on file
virtual_care:session:readAll authenticatedOwn sessions or assigned patient
virtual_care:session:endclinician, adminSession must be active or waiting
virtual_care:session:admitclinician, nurse_practitioner, adminProvider must be in session
virtual_care:config:readadmin, tenant_adminOwn tenant only
virtual_care:config:writetenant_admin, platform_adminOwn tenant; or platform admin
virtual_care:async_visit:createclinician, patient (via portal)Patient consent on file
virtual_care:ai:transcribeclinicianSession in active state
virtual_care:ai:accept_summaryclinicianSession in active or ended
GateRequired before
Telehealth consentAny virtual session creation
Recording consent (separate)Setting recordingEnabled=true; Jibri activation
AI transcriptionEnabling STT; patient and clinician must both consent

Consent records are checked via the ConsentCheckPort → access-policy service. Fail-closed: if consent service is unavailable, session creation is blocked.

3. Join Token Security

PropertyValue
AlgorithmHMAC-HS256
SecretPer-tenant, stored in KMS (never in DB)
Expiry15 min before scheduled start (configurable)
PayloadsessionId, participantId, role, iat, exp
RotationNew token issued on each /join-token call; previous token invalidated
ValidationServer-side only; client cannot validate

The join token endpoint (GET /sessions/join) is configured in Kong to bypass JWT auth and use HMAC token only.

4. Encryption Classes

DataClassMechanism
Jitsi JWT secretSecretKMS; never stored in DB
Zoom/Webex/Teams credentialsSecretKMS-encrypted column
Session metadata (IDs, timestamps)StandardPostgreSQL AES-256 at rest
Audio streams (STT)In-transit onlyTLS 1.2+ via Kong
Recording filesPHI-StandardEncrypted in document-service object storage
Chat contentPHI-StandardOwned by communication-service; not stored here

5. Audit Events

Audit EventTrigger
SESSION_CREATEDSession created
SESSION_STARTEDProvider joins; session active
PARTICIPANT_ADMITTEDPatient admitted from waiting room
PARTICIPANT_REMOVEDParticipant removed
SESSION_ENDEDSession ends
SESSION_CANCELLEDSession cancelled
SESSION_FAILEDSession failed (grace expired)
FALLBACK_INITIATEDAsync messaging fallback triggered
RECORDING_ENABLEDRecording consent recorded + recording activated
CONFIG_UPDATEDTenant config changed (no credentials)
AI_SUMMARY_ACCEPTEDClinician accepted AI draft into chart
CONSENT_GATE_BLOCKEDSession creation blocked due to missing consent
TOKEN_INVALIDInvalid join token attempt logged
CROSS_TENANT_VIOLATIONCross-tenant access attempt

6. PHI Controls

  • Session metadata (IDs, timestamps, status, participant counts) are not PHI.
  • Clinical content (chat, audio, notes) is PHI — never stored in virtual-care-service tables.
  • Chat content lives in communication-service.
  • Audio transcripts and summaries pass through ai-gateway-service and are written to patient-chart-service after HITL acceptance; never persisted in this service's DB.
  • Recording files stored in document-service with patient consent reference.

7. GDPR / Data Protection Participation

RightHandling
Right to erasureSession rows soft-deleted; patientId pseudonymized; audit trail retained
Purpose limitationJoin tokens are scoped to specific sessions and expire
Data minimizationMinimal metadata in event payloads; no session content in events

8. Tenant Isolation

  • PostgreSQL RLS on virtual_sessions, virtual_session_participants, async_visits.
  • tenant_id extracted from JWT; set as app.tenant_id session variable at connection time.
  • Cross-tenant violations logged as security events and returned as 403.