Virtual Care Service — User Stories
Service: virtual-care-service Story prefix: VCARE-US Last updated: 2026-04-18
Stories
VCARE-US-001 — Create a virtual care session
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Create virtual session with Jitsi room provisioning; enforce consent + license |
| Epic link | VCARE-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 8 |
| Labels | service:virtual-care, type:backend, type:api, slice:S1 |
| Components | session-lifecycle, jitsi-adapter |
| FR references | FR-VCARE-001 |
| Legacy FR refs | FR-VC-001, FR-VC-008, FR-VC-011 (TELEMED-VC) |
| Dependencies | VCARE-US-005 (consent gate must exist first) |
User story: As a clinician, when I create a virtual care session for a patient, I want the system to provision a Jitsi Meet room and return session details so that the patient and I can join at the scheduled time.
Acceptance criteria (Gherkin):
- Given the tenant has virtual care licensed and the patient has telehealth consent on file, when I
POST /api/v1/virtual-care/sessionswith validpatientIdandscheduledStart, then I receive 201 with aVirtualSessionDtocontainingroomUrl,roomName,status: scheduled, andversion: 1. - Given the Jitsi health check returns 503, when I attempt to create a session, then I receive 503
VIDEO_PROVIDER_UNAVAILABLEand no session row is created in the database. - Given the patient does not have telehealth consent on file, when I attempt to create a session, then I receive 403
CONSENT_REQUIREDand no session row is created. - Given a successfully created session, when
POST /api/v1/virtual-care/sessionsis called, thenvirtual_care.session.created.v1is published to NATS.
Technical notes:
CreateVirtualSessionUseCasemust callVideoProviderHealthPortbeforeVideoProviderPort.createRoom().- Session row created only after
createRoom()succeeds. - Optimistic lock:
version = 1on creation.
Definition of Done:
- Unit + integration tests added; coverage ≥ thresholds.
- OpenAPI contract updated; Pact consumer tests green.
- Event schema registered; schema conformance test green.
- Telemetry spans/metrics added.
- Documentation updated in relevant 17 docs.
VCARE-US-002 — Join session and enter waiting room
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Patient joins via HMAC join token; enters waiting room state |
| Epic link | VCARE-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:virtual-care, type:backend, type:api, slice:S1 |
| Components | waiting-room, join-token |
| FR references | FR-VCARE-002 |
| Legacy FR refs | FR-VC-002 (TELEMED-VC) |
| Dependencies | VCARE-US-001 |
User story: As a patient, when I click the join link from my appointment notification, I want to enter the waiting room so that the provider can admit me when ready.
Acceptance criteria (Gherkin):
- Given a valid, non-expired join token, when I call
GET /api/v1/virtual-care/sessions/join?token=<token>, then I receive{ destination: "waiting_room", url: "...", sessionStatus: "scheduled" }. - Given an expired join token, when I call the join endpoint, then I receive 401
TOKEN_EXPIRED. - Given a join token for a cancelled session, when I call the join endpoint, then I receive 409
INVALID_STATUS_TRANSITION. - Given a patient successfully validates their token, when they enter the waiting room, then
virtual_care.session.participant.joined.v1is published withrole: patientandparticipantStatus: waiting.
Technical notes:
- Join endpoint configured in Kong to bypass JWT auth; uses HMAC token only.
JoinTokenSignerPortvalidates HMAC signature + expiry +participantIdclaim.
Definition of Done: Standard DoD applies.
VCARE-US-003 — Admit patient from waiting room
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Provider admits patient from waiting room; session transitions to active |
| Epic link | VCARE-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | waiting-room |
| FR references | FR-VCARE-003 |
| Legacy FR refs | FR-VC-003 (TELEMED-VC) |
| Dependencies | VCARE-US-002 |
User story: As a clinician, when a patient is in the waiting room, I want to admit them to the active session so that the consultation can begin.
Acceptance criteria (Gherkin):
- Given a patient in
waitingstatus and a provider in the session, when IPOST /api/v1/virtual-care/sessions/:id/admit/:participantId, then the patient's status transitions toadmittedand I receive{ videoJoinUrl: "..." }. - Given a participant NOT in
waitingstatus, when I attempt to admit them, then I receive 409PARTICIPANT_NOT_IN_WAITING_ROOM. - Given the admit succeeds and this is the first provider join, when the session transitions to
active, thenvirtual_care.session.started.v1is published. - Given
virtual_care.session.participant.admitted.v1is emitted, when audit-service receives it, then the event is logged withactorId,participantId, and timestamp.
Technical notes: AdmitParticipantUseCase applies FSM transition on the VirtualSession aggregate.
Definition of Done: Standard DoD applies.
VCARE-US-004 — End a session and trigger Encounter creation
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | End session; create FHIR Encounter; emit billing event |
| Epic link | VCARE-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | session-lifecycle, fhir-integration, billing-events |
| FR references | FR-VCARE-004 |
| Legacy FR refs | FR-VC-006, FR-VC-031 (TELEMED-VC) |
| Dependencies | patient-chart-service (FHIR Gateway), billing-service |
User story: As a clinician, when I end a virtual care session, I want the system to automatically create a FHIR Encounter in the patient's chart and emit a billing event so that the visit is documented and can be claimed.
Acceptance criteria (Gherkin):
- Given a session in
activestatus, when IPOST /api/v1/virtual-care/sessions/:id/end, then the session transitions toendedandencounterIdis populated. - Given the session ends, when FHIR Gateway creates the Encounter, then the Encounter has
class: VR,subject: Patient/{patientId}, andappointment: Appointment/{appointmentId}. - Given the session ends, when
virtual_care.billing.session_chargeable.v1is emitted, thendurationSeconds,patientId, andencounterIdare included. - Given FHIR Gateway is temporarily unavailable when session ends, when it recovers within 5 min, then the retry job creates the Encounter and updates
encounterIdon the session. - Given an already-ended session, when I call end again, then I receive 200 with the current session state (idempotent).
Technical notes:
EndSessionUseCasecalls FHIR Gateway; on failure, session is still markedendedand retry job is enqueued.- Version optimistic lock checked on end.
Definition of Done: Standard DoD applies.
VCARE-US-005 — Enforce telehealth consent before session creation
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Block session creation if patient telehealth consent not on file |
| Epic link | VCARE-EPIC-02 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | consent-gate |
| FR references | FR-VCARE-020 |
| Legacy FR refs | FR-VC-020 (TELEMED-VC) |
| Dependencies | access-policy service |
User story: As a compliance officer, when a clinician attempts to create a virtual care session for a patient without telehealth consent, I want the system to block the session and record an audit event so that the platform never initiates telehealth without documented patient consent.
Acceptance criteria (Gherkin):
- Given the patient has no telehealth consent record, when
POST /api/v1/virtual-care/sessionsis called, then I receive 403CONSENT_REQUIREDand aCONSENT_GATE_BLOCKEDaudit event is emitted. - Given the consent service is unreachable (503), when
POST /api/v1/virtual-care/sessionsis called, then the session is blocked (fail-closed) with 503CONSENT_SERVICE_UNAVAILABLE. - Given the patient has valid telehealth consent, when session creation proceeds, then no consent-related error is returned.
Technical notes:
ConsentCheckPort→ access-policy service; fail-closed on network error.- Consent audit event logged regardless of source of block.
Definition of Done: Standard DoD applies.
VCARE-US-006 — Enforce recording consent separately
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Recording consent required separately before enabling session recording |
| Epic link | VCARE-EPIC-02 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | consent-gate, recording |
| FR references | FR-VCARE-022 |
| Legacy FR refs | FR-VC-022, FR-VC-028 (TELEMED-VC) |
| Dependencies | VCARE-US-005 |
User story: As a patient, when a provider tries to record my session, I want the system to verify that I have specifically consented to recording (separate from general telehealth consent) so that my privacy is respected.
Acceptance criteria (Gherkin):
- Given a session creation request with
recordingEnabled: trueand no recording consent on file, when the request is processed, then 403CONSENT_REQUIREDis returned withgate: recording_consent. - Given recording consent IS on file and
recordingEnabled: trueis requested, when the session is created, thenrecordingEnabled: trueis set on the session row. - Given a session ends with recording, when
virtual_care.session.ended.v1is emitted, thenrecordingRefis included if Jibri recording was completed.
Definition of Done: Standard DoD applies.
VCARE-US-007 — Jitsi Meet room provisioning and health check
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Jitsi adapter: room creation, JWT auth, health check before session create |
| Epic link | VCARE-EPIC-03 |
| Status | To Do |
| Priority | Must |
| Story points | 8 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | jitsi-adapter |
| FR references | FR-VCARE-030 |
| Legacy FR refs | FR-VC-008, FR-VC-011, FR-VC-035–036 (TELEMED-VC) |
| Dependencies | Jitsi Meet self-hosted deployment |
User story: As a platform engineer, when virtual care sessions are created, I want Jitsi Meet rooms provisioned automatically with tenant-branded configuration and JWT authentication so that providers and patients join a fully configured video environment.
Acceptance criteria (Gherkin):
- Given Jitsi is healthy, when
CreateRoomis called with tenant branding config, then a room with tenantroomSlugPrefix,brandingLogoUrl, andbrandingPrimaryColoris created. - Given Jitsi returns 503, when the health check fails, then
CreateVirtualSessionUseCasedoes not persist a session row and returns 503. - Given a session is created, when a join token is issued, then the token is a valid HS256 JWT signed with the tenant's Jitsi secret from KMS.
Technical notes:
jitsiJwtSecretis retrieved from KMS; never stored in DB.- Room slug:
{roomSlugPrefix}-{random-8-chars}. - Tenant branding fields validated (HTTPS only, CSS hex color) before use in Meet config.
Definition of Done: Standard DoD applies.
VCARE-US-008 — Bandwidth fallback: video → audio → async messaging
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Automatic degradation from video to async messaging on persistent connectivity loss |
| Epic link | VCARE-EPIC-03 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | bandwidth-fallback |
| FR references | FR-VCARE-032 – FR-VCARE-034 |
| Legacy FR refs | FR-VC-023–024 (TELEMED-VC) |
| Dependencies | communication-service (messaging thread), VCARE-US-004 |
User story: As a clinician in Afghanistan, when the patient's video connection drops and cannot be restored within the grace period, I want the system to automatically offer an async messaging fallback so that the consultation can continue.
Acceptance criteria (Gherkin):
- Given a session in
failedstatus (grace reconnect expired), when IPOST /api/v1/virtual-care/sessions/:id/fallback-message, then a messaging thread is created incommunication-serviceand{ messagingThreadId: "..." }is returned. - Given the fallback is initiated, when
virtual_care.session.fallback.initiated.v1is emitted, thencommunication-servicesubscribes and creates the thread linked to the session. - Given a session NOT in
failedoractivestatus, when fallback is requested, then 409INVALID_STATUS_TRANSITIONis returned.
Technical notes:
- Grace reconnect window is tenant-configurable (default 60s via
sessionGraceMinutesAfter). - Fallback threshold detection may be implemented at client or backend signaling layer; this story covers the server-side fallback API.
Definition of Done: Standard DoD applies.
VCARE-US-009 — FHIR Encounter and billing event on session end
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | FHIR Encounter class=VR created on session end; billing event emitted |
| Epic link | VCARE-EPIC-04 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:virtual-care, type:backend, slice:S1 |
| Components | fhir-integration, billing-events |
| FR references | FR-VCARE-040 |
| Legacy FR refs | FR-VC-031 (TELEMED-VC) |
| Dependencies | patient-chart-service (FHIR Gateway), billing-service |
User story: As a health records administrator, when a telehealth session ends, I want a FHIR R4 Encounter resource automatically created in the patient's chart so that the virtual visit is documented in the EHR without manual entry.
Acceptance criteria (Gherkin):
- Given a session ends with
durationSeconds > 0, when FHIR Gateway responds 201, thenencounterIdis stored on the session row. - Given FHIR Gateway is down at session end, when the retry job runs within 5 min, then Encounter is created and
encounterIdupdated. - Given Encounter is created, when
virtual_care.billing.session_chargeable.v1is emitted, then billing-service receivesencounterId,patientId,durationSeconds.
Technical notes: EndSessionUseCase → FhirGatewayPort.createEncounter() → POST /fhir/Encounter.
Definition of Done: Standard DoD applies.
VCARE-US-010 — Tenant virtual-care configuration management
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Admin configures video backend, Jitsi branding, recording policy, participant limits |
| Epic link | VCARE-EPIC-05 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:virtual-care, type:api, type:backend, slice:S1 |
| Components | tenant-config |
| FR references | FR-VCARE-050 – FR-VCARE-054 |
| Legacy FR refs | FR-VC-018–019, FR-VC-035–036 (TELEMED-VC) |
| Dependencies | KMS |
User story: As a tenant administrator, when I configure virtual care for my facility, I want to set the Jitsi server URL, branding, recording policy, and participant limits so that sessions reflect our organization's identity and policies.
Acceptance criteria (Gherkin):
- Given
tenant_adminrole, when IPUT /api/v1/virtual-care/configwithjitsiServerUrl,brandingLogoUrl, andmaxParticipants, then the config is saved andvirtual_care.config.updated.v1is emitted with onlychangedFields(no credentials). - Given I
GET /api/v1/virtual-care/config, when the response is returned, thenjitsiJwtSecret,zoomApiKey, and any other credential fields are returned as"****". - Given I
POST /api/v1/virtual-care/config/test-connection, when Jitsi responds healthy, then{ healthy: true, latencyMs: N }is returned.
Technical notes: Credentials stored via SecretStorePort → KMS. Config field changedFields computed as diff between old and new config.
Definition of Done: Standard DoD applies.
VCARE-US-011 — AI speech-to-text transcription during session
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician initiates STT transcription; transcript shown in review panel |
| Epic link | VCARE-EPIC-06 |
| Status | To Do |
| Priority | Should |
| Story points | 8 |
| Labels | service:virtual-care, type:backend, slice:S2 |
| Components | ai-integration |
| FR references | FR-VCARE-060 |
| Legacy FR refs | FR-VC-029 (TELEMED-VC) |
| Dependencies | ai-gateway-service |
User story: As a clinician, during an active session, I want to activate speech-to-text transcription so that I have a running transcript I can review before accepting it into the patient chart.
Acceptance criteria (Gherkin):
- Given an active session and
clinicianrole, when IPOST /api/v1/virtual-care/sessions/:id/ai/transcribewith an audio chunk, then a transcript is returned and is NOT automatically added to the chart. - Given ai-gateway is unreachable, when the STT request is made, then I receive a user-friendly error and the session continues normally.
- Given the STT returns a transcript, when it is displayed, then no PHI appears in service logs.
Technical notes:
- Audio content never persisted in virtual-care-service DB.
- PHI (transcript content) must not appear in logs; log only metadata.
Definition of Done: Standard DoD applies.
VCARE-US-012 — AI visit summary draft with mandatory HITL acceptance
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Generate visit summary draft; clinician must explicitly accept before chart entry |
| Epic link | VCARE-EPIC-06 |
| Status | To Do |
| Priority | Should |
| Story points | 5 |
| Labels | service:virtual-care, type:backend, slice:S2 |
| Components | ai-integration, clinical-documentation |
| FR references | FR-VCARE-061 – FR-VCARE-062 |
| Legacy FR refs | FR-VC-029–030 (TELEMED-VC) |
| Dependencies | ai-gateway-service, patient-chart-service |
User story: As a clinician, after the session transcript is available, I want to generate a visit summary draft and review it before deciding to add it to the patient's chart so that I maintain full control over documented clinical content.
Acceptance criteria (Gherkin):
- Given a session transcript is available, when summary generation is triggered, then a draft is returned to the clinician in the review panel (not yet in the chart).
- Given the clinician reviews and accepts the summary, when
POST /api/v1/virtual-care/sessions/:id/ai/accept-summaryis called withaccepted: true, then the summary is pushed topatient-chart-servicewith AI provenance metadata. - Given the clinician declines the summary, when
accepted: falseis submitted, then no content is written to the chart. - Given a refused AI completion from ai-gateway, when the summary endpoint is called, then the clinician is notified and can document manually.
Technical notes:
- No auto-push path exists;
AcceptAiSummaryUseCaseis the only path to chart. - AI provenance:
aiGenerated: true,aiModel,aiAcceptedBy,aiAcceptedAtwritten to note metadata.
Definition of Done: Standard DoD applies.
VCARE-US-013 — Async store-and-forward visit (offline support)
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Patient submits async visit content offline; provider reviews and responds |
| Epic link | VCARE-EPIC-07 |
| Status | To Do |
| Priority | Should |
| Story points | 8 |
| Labels | service:virtual-care, type:backend, type:api, slice:S2 |
| Components | async-visits, offline-support |
| FR references | FR-VCARE-070 – FR-VCARE-072 |
| Legacy FR refs | — (synthesized) |
| Dependencies | communication-service, patient-chart-service |
User story: As a patient in a remote area with limited connectivity, when I cannot join a live video session, I want to submit my chief complaint and photos offline and have my provider review and respond asynchronously so that I still receive care.
Acceptance criteria (Gherkin):
- Given an async visit drafted offline, when I
POST /api/v1/virtual-care/async-visitswith aclientMutationId, then the visit is created andvirtual_care.async_visit.submitted.v1is emitted. - Given the same
clientMutationIdis submitted twice (offline retry), when the second request arrives, then the server returns 200 with the originalAsyncVisitDto(idempotent; no duplicate created). - Given a provider responds to the async visit, when the response is saved, then a FHIR Encounter is created in
patient-chart-serviceand the visit transitions toresponded.
Technical notes:
clientMutationId: stable UUID set at draft creation time; carried through offline queue to server.UNIQUE (tenant_id, client_mutation_id)DB constraint enforces idempotency.
Definition of Done: Standard DoD applies.