Skip to main content

Virtual Care Service — Domain Model

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD

1. Aggregates

1.1 VirtualSession

The central aggregate. Represents a single telehealth session from creation through termination.

Invariants:

  • VirtualSession row is created only after the video room is successfully provisioned (no session row on backend failure).
  • patientId is always required; a session cannot exist without a patient.
  • recordingEnabled can only be set to true if patient recording consent is on file.
  • version is used for optimistic locking; every state transition increments version.
  • An ended session cannot be reactivated.
  • Join tokens expire after sessionGraceMinutesBefore configured value (default 15 min before scheduled start).

State machine:

StateMeaning
scheduledSession created; no participants in room
waitingAt least one participant joined; waiting for provider to admit
activeProvider has admitted patient; session in progress
endedSession ended normally; Encounter creation triggered
cancelledCancelled before becoming active
failedVideo backend lost; grace reconnect expired

1.2 SessionParticipant

Entity within VirtualSession aggregate. One per participant.

Invariants:

  • role must be one of: provider | patient | interpreter | observer
  • At most one patient participant per session at a time.
  • Provider must be present before patient can be admitted from waiting room.
  • A removed participant cannot re-join without a new token.

Participant states: invited → waiting → admitted → active → disconnected → removed


1.3 TenantVirtualCareConfig

Per-tenant configuration aggregate. One record per tenant.

Invariants:

  • jitsiJwtSecret is never returned in GET responses (redacted as ****).
  • maxParticipants must be between 2 and the platform hard limit (default 20).
  • jitsiServerUrl must be HTTPS.
  • brandingLogoUrl and brandingPrimaryColor are validated (HTTPS allowlist, CSS hex color).

1.4 AsyncVisit (store-and-forward)

Represents an asynchronous telehealth encounter where the provider reviews clinical content and responds, rather than conducting a live video session.

Invariants:

  • Content is authored offline and submitted when connectivity restores.
  • Once submitted, content is immutable (new version required for amendments).
  • Provider response triggers Encounter creation in patient-chart-service.

States: draft → submitted → under_review → responded → closed

2. Value Objects

Value ObjectFieldsNotes
JoinTokentoken: string, expiresAt: Date, participantId: stringHMAC-signed; short-lived
VideoBackendjitsi | mediasoup | zoom | webex | teamsBranded enum
SessionStatusstate machine states aboveBranded string
ParticipantRoleprovider | patient | interpreter | observerBranded string
BandwidthProfilevideo | audio_only | async_textFallback tier
ConsentRecordtype: telehealth|recording, capturedAt: Date, version: stringImmutable on capture

3. Domain Events

EventAggregateTrigger
virtual_care.session.created.v1VirtualSessionSession + room provisioned
virtual_care.session.started.v1VirtualSessionFirst provider joins; session → active
virtual_care.session.participant.joined.v1SessionParticipantParticipant validates join token
virtual_care.session.participant.admitted.v1SessionParticipantProvider admits patient from waiting room
virtual_care.session.participant.removed.v1SessionParticipantProvider removes participant
virtual_care.session.ended.v1VirtualSessionSession ends normally
virtual_care.session.cancelled.v1VirtualSessionSession cancelled before active
virtual_care.session.failed.v1VirtualSessionGrace reconnect expired
virtual_care.session.fallback.initiated.v1VirtualSessionAsync messaging fallback triggered
virtual_care.config.updated.v1TenantVirtualCareConfigTenant config changed
virtual_care.recording.ingested.v1VirtualSessionJibri recording reference stored
virtual_care.billing.session_chargeable.v1VirtualSessionSession ended with Encounter ID for billing
virtual_care.async_visit.submitted.v1AsyncVisitStore-and-forward content submitted

4. Ubiquitous Language

TermDefinition
Virtual sessionA telehealth encounter record representing one video or async consultation
Waiting roomThe pre-admission state where patients wait for the provider to admit them
Join tokenA short-lived HMAC-signed credential allowing a specific participant to enter a session
AdmitProvider action that moves a patient from waiting room to active session
Bandwidth fallbackAutomatic degradation: video → audio-only → async text when connectivity is insufficient
Store-and-forwardAsync telehealth: patient submits text/images offline; provider reviews later
Telehealth consentPatient's explicit consent to participate in a telehealth session (required before join)
Recording consentPatient's separate explicit consent for the session to be recorded
FHIR Encounter (VR)The FHIR resource created when a virtual session ends; class=VR (virtual)
Jitsi MeetSelf-hosted open-source WebRTC video conferencing platform
JibriJitsi Broadcasting Infrastructure — handles session recording
Video backendThe underlying video conferencing engine (Jitsi, Mediasoup, Zoom, etc.)
Grace reconnectA configurable window (default 60s) allowing a dropped participant to rejoin before the session transitions to failed