Care Plan Service — User Stories
Service: care-plan-service Story prefix: CAREPL-US Last updated: 2026-04-18
Stories
CAREPL-US-001 — Create a care plan for a patient
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician creates a care plan linked to patient and encounter |
| Epic link | CAREPL-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:care-plan, type:backend, type:api, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-001 |
| Legacy FR refs | FR-CP-001 |
| Dependencies | REG-US-001 |
User story: As a clinician, when I open a patient's chart, I want to create a new care plan with a title, category, and optional encounter link so that the care team has a structured plan to follow.
Acceptance criteria (Gherkin):
- Given I have
care_plan:writescope and the tenant hasehr.care_plansentitlement, when I POST to/api/v1/care-planswith a validpatientIdandtitle, then a care plan is created withstatus: draftandversion: 1and a201is returned. - Given a duplicate request with the same
Idempotency-Key, when I retry the POST, then the same care plan ID is returned without creating a duplicate. - Given the tenant lacks
ehr.care_plansentitlement, when I POST, then403 MODULE_NOT_LICENSEDis returned.
Technical notes:
patientIdvalidated against registration-service (async; non-blocking for v1).encounterIdis optional; include if linked to a visit.- Idempotency-Key stored in outbox record.
Definition of Done:
- Unit + integration tests added; coverage ≥ thresholds.
- OpenAPI contract updated; Pact consumer tests green.
- Event schema
care_plan.care_plan.created.v1registered; schema conformance test green. - Telemetry spans added.
- Documentation updated.
CAREPL-US-002 — Activate a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician activates a draft care plan making it operational |
| Epic link | CAREPL-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-002 |
| Legacy FR refs | FR-CP-001 |
| Dependencies | CAREPL-US-001 |
User story: As a clinician, when a care plan is ready for execution, I want to activate it so that the care team can begin working the goals and activities.
Acceptance criteria (Gherkin):
- Given a care plan in
draftstatus, when I POST to/api/v1/care-plans/:id/activatewith correctversion, then status transitions toactiveandversionincrements. - Given a care plan in
activestatus, when I attempt to activate again, then422 INVALID_STATUS_TRANSITIONis returned. - Given a stale
version, when I activate, then409 VERSION_CONFLICTis returned.
Technical notes:
- Emits
care_plan.care_plan.updated.v1withpreviousStatus: draft,newStatus: active.
Definition of Done: Standard DoD applies.
CAREPL-US-003 — Review a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician records a formal care plan review with next review date |
| Epic link | CAREPL-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-002 |
| Legacy FR refs | FR-CP-005 |
| Dependencies | CAREPL-US-002 |
User story: As a clinician, when I conduct a periodic care plan review, I want to record the review date and next review due date so that continuity of care review is auditable.
Acceptance criteria (Gherkin):
- Given an active care plan, when I POST to
/:id/reviewwithreviewNoteandnextReviewDue, thenlastReviewedAtis updated andversionincrements. - Given a closed care plan, when I attempt to review, then
409 CARE_PLAN_CLOSEDis returned.
Technical notes:
- Emits
care_plan.care_plan.reviewed.v1. nextReviewDuedrives communication-service reminders.
Definition of Done: Standard DoD applies.
CAREPL-US-004 — Close a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Admin closes a care plan as completed or revoked; plan becomes read-only |
| Epic link | CAREPL-EPIC-01 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-002 |
| Legacy FR refs | FR-CP-001, FR-CP-005 |
| Dependencies | CAREPL-US-002 |
User story: As a care plan admin, when a patient's care goals are met or the plan is no longer applicable, I want to close the plan so that it becomes read-only while remaining permanently visible in the patient's history.
Acceptance criteria (Gherkin):
- Given an active plan, when I POST
/:id/closewithcloseReason: completed, then status iscompletedand all subsequent mutations return409 CARE_PLAN_CLOSED. - Given a closed plan, when a clinician attempts a PATCH, then
409 CARE_PLAN_CLOSEDis returned.
Technical notes:
- Only
care_plan:adminrole may close plans (BR-CP-001).
Definition of Done: Standard DoD applies.
CAREPL-US-005 — Add a goal to a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician adds a measurable goal with a coded target and due date |
| Epic link | CAREPL-EPIC-02 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:care-plan, type:backend, type:api, slice:S1 |
| Components | care-plan-service, terminology-service |
| FR references | FR-CAREPL-003 |
| Legacy FR refs | FR-CP-002 |
| Dependencies | CAREPL-US-002, TERM-US-001 |
User story: As a clinician, when building a care plan, I want to add measurable goals with coded targets (e.g., HbA1c < 7%) and due dates so that goal achievement can be tracked and reported.
Acceptance criteria (Gherkin):
- Given an active care plan, when I POST to
/api/v1/care-plans/:id/goalswithdescription,targetDetail, anddueAt, then the goal is created withstatus: proposedand a201returned. - Given a goal with a LOINC-coded target, when I GET the goal, then the FHIR Goal resource includes the target measure coding.
- Given a closed care plan, when I add a goal, then
409 CARE_PLAN_CLOSEDis returned.
Technical notes:
targetDetail.measurecoded via LOINC or SNOMED CT; terminology-service validates coding.- Emits
care_plan.goal.created.v1.
Definition of Done: Standard DoD applies.
CAREPL-US-006 — Update goal status
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Care team updates goal status through the lifecycle |
| Epic link | CAREPL-EPIC-02 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-003 |
| Legacy FR refs | FR-CP-002 |
| Dependencies | CAREPL-US-005 |
User story: As a care team member, when a patient makes progress, I want to update the goal status (e.g., proposed → in_progress → achieved) so that the plan reflects current clinical reality.
Acceptance criteria (Gherkin):
- Given a goal in
proposedstatus, when I PATCH withstatus: in_progress, then the transition succeeds. - Given an achieved goal, when I attempt to move it back to
in_progress, then422 INVALID_STATUS_TRANSITIONis returned.
Technical notes:
- Emits
care_plan.goal.updated.v1.
Definition of Done: Standard DoD applies.
CAREPL-US-007 — Detect and surface overdue goals
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | System flags goals past due date not yet achieved |
| Epic link | CAREPL-EPIC-02 |
| Status | To Do |
| Priority | Should |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service, communication-service |
| FR references | FR-CAREPL-003 |
| Legacy FR refs | FR-CP-002 |
| Dependencies | CAREPL-US-005 |
User story: As a care coordinator, when I view a patient's care plan, I want overdue goals to be highlighted so that I can prioritize follow-up with the patient.
Acceptance criteria (Gherkin):
- Given a goal with
dueAtin the past and status notachievedorcancelled, when I GET the care plan, then the goal hasisOverdue: truein the response. - Given a scheduled nightly job, when overdue goals are detected, then a notification event is emitted to communication-service.
Technical notes:
- Overdue detection runs at query time and via daily scheduled task.
- Notification event:
care_plan.goal.overdue.v1(consumed by communication-service).
Definition of Done: Standard DoD applies.
CAREPL-US-008 — Add an activity to a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician adds an intervention with assignee and schedule |
| Epic link | CAREPL-EPIC-03 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:care-plan, type:backend, type:api, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-004 |
| Legacy FR refs | FR-CP-003 |
| Dependencies | CAREPL-US-002 |
User story: As a clinician, when planning care, I want to add specific interventions (e.g., monthly dietitian visit) with an assignee and schedule so that the team knows what is expected and when.
Acceptance criteria (Gherkin):
- Given an active care plan, when I POST to
/:id/activitieswithdescription,assigneeId, andscheduleDetail, then the activity is created withstatus: not_started. - Given an activity, when I GET the care plan, then the FHIR Task resource is returned for the activity.
Technical notes:
- Emits
care_plan.activity.created.v1. assigneeIdis apractitionerIdsoft reference.
Definition of Done: Standard DoD applies.
CAREPL-US-009 — Complete an activity
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Team member marks an activity complete with a completion note |
| Epic link | CAREPL-EPIC-03 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:backend, slice:S1 |
| Components | care-plan-service |
| FR references | FR-CAREPL-004 |
| Legacy FR refs | FR-CP-003 |
| Dependencies | CAREPL-US-008 |
User story: As a nurse or care coordinator, when I complete a scheduled intervention, I want to mark the activity complete with a note so that the care record reflects what was done.
Acceptance criteria (Gherkin):
- Given an activity in
in_progressornot_startedstatus, when I POST to/:id/activities/:actId/complete, then status becomescompleted,completedAtis set. - Given an already completed activity, when I attempt to complete again, then
422 INVALID_STATUS_TRANSITIONis returned.
Technical notes:
- Emits
care_plan.activity.completed.v1.
Definition of Done: Standard DoD applies.
CAREPL-US-010 — Manage care team members
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Admin assigns practitioners to care plan with roles and effective periods |
| Epic link | CAREPL-EPIC-04 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:care-plan, type:backend, type:api, slice:S2 |
| Components | care-plan-service, provider-directory-service |
| FR references | FR-CAREPL-005 |
| Legacy FR refs | FR-CP-004 |
| Dependencies | CAREPL-US-002, PROVDIR-US-001 |
User story: As a care coordinator, when assembling a multidisciplinary team, I want to assign practitioners with their roles (primary physician, specialist, nurse) and effective dates so that care responsibilities are explicit.
Acceptance criteria (Gherkin):
- Given an active plan, when I PUT to
/:id/care-teamwith a list of members, then the team is replaced atomically andcare_plan.care_team.updated.v1is emitted. - Given a practitioner ID that does not exist in provider-directory-service, when I update the team, then
422 INVALID_PRACTITIONERis returned.
Technical notes:
- Provider-directory-service validates
practitionerIdreferences. - Team is replaced in full (no partial patch for v1).
Definition of Done: Standard DoD applies.
CAREPL-US-011 — View care team for a care plan
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Clinician views the current care team with roles |
| Epic link | CAREPL-EPIC-04 |
| Status | To Do |
| Priority | Must |
| Story points | 2 |
| Labels | service:care-plan, type:api, slice:S2 |
| Components | care-plan-service |
| FR references | FR-CAREPL-005 |
| Legacy FR refs | FR-CP-004 |
| Dependencies | CAREPL-US-010 |
User story: As a care team member, when I view a care plan, I want to see all assigned practitioners and their roles so that I know who to contact for each aspect of care.
Acceptance criteria (Gherkin):
- Given a plan with care team members, when I GET
/:id, then the response includescareTeam[]withpractitionerId,role, andeffectiveFrom. - Given a FHIR read, when I GET
/fhir/R4/CareTeam?patient=Patient/:patientId, then a valid FHIR R4CareTeamresource is returned.
Definition of Done: Standard DoD applies.
CAREPL-US-012 — FHIR CarePlan read for chart integration
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | patient-chart-service reads care plans via FHIR R4 CarePlan resource |
| Epic link | CAREPL-EPIC-05 |
| Status | To Do |
| Priority | Must |
| Story points | 5 |
| Labels | service:care-plan, type:fhir, slice:S1 |
| Components | care-plan-service, fhir-gateway |
| FR references | FR-CAREPL-006 |
| Legacy FR refs | — |
| Dependencies | CAREPL-US-002, INTEROP-US-001 |
User story: As the patient-chart-service, when rendering the clinical chart, I want to query active care plans via FHIR R4 so that care plan data is displayed without bespoke integration.
Acceptance criteria (Gherkin):
- Given a patient with active care plans, when I GET
/fhir/R4/CarePlan?patient=Patient/:patientId&status=active, then a FHIRBundlewith conformantCarePlanresources is returned. - Given a care plan in the response, when it is validated against R4 base profile, then it passes validation.
Technical notes:
- Golden FHIR fixtures in
test/fixtures/fhir/care-plan.jsonvalidated in CI. - FHIR search parameters:
patient,status,_count,_offset.
Definition of Done: Standard DoD applies.
CAREPL-US-013 — FHIR Goal read for portal integration
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Patient portal reads goals via FHIR R4 Goal resource |
| Epic link | CAREPL-EPIC-05 |
| Status | To Do |
| Priority | Should |
| Story points | 3 |
| Labels | service:care-plan, type:fhir, slice:S4 |
| Components | care-plan-service, patient-portal-service |
| FR references | FR-CAREPL-006 |
| Legacy FR refs | — |
| Dependencies | CAREPL-US-005 |
User story: As a patient, when I view my care plan in the patient portal, I want to see my health goals so that I understand what I am working towards.
Acceptance criteria (Gherkin):
- Given a patient with care plan goals, when the portal queries
/fhir/R4/Goal?patient=Patient/:patientId, then a FHIR Bundle of R4 Goal resources is returned. - Given the patient does not have
care_plan:readscope, when querying, then403is returned.
Definition of Done: Standard DoD applies.
CAREPL-US-014 — Module entitlement gate
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Unlicensed tenants receive 403 on all write operations |
| Epic link | CAREPL-EPIC-06 |
| Status | To Do |
| Priority | Must |
| Story points | 2 |
| Labels | service:care-plan, type:backend, type:security, slice:S0 |
| Components | care-plan-service, identity-service |
| FR references | FR-CAREPL-007 |
| Legacy FR refs | — |
| Dependencies | IDENT-US-001 |
User story: As a platform operator, when a tenant has not licensed the care plan module, I want all write operations to be blocked with a clear error so that the billing boundary is enforced.
Acceptance criteria (Gherkin):
- Given a tenant without
ehr.care_plansentitlement, when any write endpoint is called, then403 MODULE_NOT_LICENSEDis returned. - Given a licensed tenant, when the same write endpoint is called with valid auth, then the operation proceeds normally.
Definition of Done: Standard DoD applies.
CAREPL-US-015 — Tenant isolation validation
| Field | Value |
|---|---|
| Issue type | Story |
| Summary | Zero cross-tenant data leakage proven by adversarial integration test |
| Epic link | CAREPL-EPIC-06 |
| Status | To Do |
| Priority | Must |
| Story points | 3 |
| Labels | service:care-plan, type:security, type:test, slice:S0 |
| Components | care-plan-service |
| FR references | FR-CAREPL-007 |
| Legacy FR refs | — |
| Dependencies | CAREPL-US-001 |
User story: As a security engineer, when running adversarial tests, I want to verify that Tenant A cannot read or write Tenant B's care plans so that PHI cross-tenant leakage is provably impossible.
Acceptance criteria (Gherkin):
- Given Tenant A has care plans, when a Tenant B JWT is used to query all care plans, then zero results are returned.
- Given Tenant B tries to GET a specific
carePlanIdowned by Tenant A, then404 CARE_PLAN_NOT_FOUNDis returned (not a403that confirms existence).
Technical notes:
- Implemented as mandatory
tenant-isolation.integration.spec.ts. - Must pass as CI gate for every PR.
Definition of Done: Standard DoD applies. Test in CI gate (never removable).