Skip to main content

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

FieldValue
Issue typeStory
SummaryClinician creates a care plan linked to patient and encounter
Epic linkCAREPL-EPIC-01
StatusTo Do
PriorityMust
Story points5
Labelsservice:care-plan, type:backend, type:api, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-001
Legacy FR refsFR-CP-001
DependenciesREG-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:write scope and the tenant has ehr.care_plans entitlement, when I POST to /api/v1/care-plans with a valid patientId and title, then a care plan is created with status: draft and version: 1 and a 201 is 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_plans entitlement, when I POST, then 403 MODULE_NOT_LICENSED is returned.

Technical notes:

  • patientId validated against registration-service (async; non-blocking for v1).
  • encounterId is 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.v1 registered; schema conformance test green.
  • Telemetry spans added.
  • Documentation updated.

CAREPL-US-002 — Activate a care plan

FieldValue
Issue typeStory
SummaryClinician activates a draft care plan making it operational
Epic linkCAREPL-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-002
Legacy FR refsFR-CP-001
DependenciesCAREPL-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 draft status, when I POST to /api/v1/care-plans/:id/activate with correct version, then status transitions to active and version increments.
  • Given a care plan in active status, when I attempt to activate again, then 422 INVALID_STATUS_TRANSITION is returned.
  • Given a stale version, when I activate, then 409 VERSION_CONFLICT is returned.

Technical notes:

  • Emits care_plan.care_plan.updated.v1 with previousStatus: draft, newStatus: active.

Definition of Done: Standard DoD applies.


CAREPL-US-003 — Review a care plan

FieldValue
Issue typeStory
SummaryClinician records a formal care plan review with next review date
Epic linkCAREPL-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-002
Legacy FR refsFR-CP-005
DependenciesCAREPL-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/review with reviewNote and nextReviewDue, then lastReviewedAt is updated and version increments.
  • Given a closed care plan, when I attempt to review, then 409 CARE_PLAN_CLOSED is returned.

Technical notes:

  • Emits care_plan.care_plan.reviewed.v1.
  • nextReviewDue drives communication-service reminders.

Definition of Done: Standard DoD applies.


CAREPL-US-004 — Close a care plan

FieldValue
Issue typeStory
SummaryAdmin closes a care plan as completed or revoked; plan becomes read-only
Epic linkCAREPL-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-002
Legacy FR refsFR-CP-001, FR-CP-005
DependenciesCAREPL-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/close with closeReason: completed, then status is completed and all subsequent mutations return 409 CARE_PLAN_CLOSED.
  • Given a closed plan, when a clinician attempts a PATCH, then 409 CARE_PLAN_CLOSED is returned.

Technical notes:

  • Only care_plan:admin role may close plans (BR-CP-001).

Definition of Done: Standard DoD applies.


CAREPL-US-005 — Add a goal to a care plan

FieldValue
Issue typeStory
SummaryClinician adds a measurable goal with a coded target and due date
Epic linkCAREPL-EPIC-02
StatusTo Do
PriorityMust
Story points5
Labelsservice:care-plan, type:backend, type:api, slice:S1
Componentscare-plan-service, terminology-service
FR referencesFR-CAREPL-003
Legacy FR refsFR-CP-002
DependenciesCAREPL-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/goals with description, targetDetail, and dueAt, then the goal is created with status: proposed and a 201 returned.
  • 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_CLOSED is returned.

Technical notes:

  • targetDetail.measure coded 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

FieldValue
Issue typeStory
SummaryCare team updates goal status through the lifecycle
Epic linkCAREPL-EPIC-02
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-003
Legacy FR refsFR-CP-002
DependenciesCAREPL-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 proposed status, when I PATCH with status: in_progress, then the transition succeeds.
  • Given an achieved goal, when I attempt to move it back to in_progress, then 422 INVALID_STATUS_TRANSITION is returned.

Technical notes:

  • Emits care_plan.goal.updated.v1.

Definition of Done: Standard DoD applies.


CAREPL-US-007 — Detect and surface overdue goals

FieldValue
Issue typeStory
SummarySystem flags goals past due date not yet achieved
Epic linkCAREPL-EPIC-02
StatusTo Do
PriorityShould
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service, communication-service
FR referencesFR-CAREPL-003
Legacy FR refsFR-CP-002
DependenciesCAREPL-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 dueAt in the past and status not achieved or cancelled, when I GET the care plan, then the goal has isOverdue: true in 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

FieldValue
Issue typeStory
SummaryClinician adds an intervention with assignee and schedule
Epic linkCAREPL-EPIC-03
StatusTo Do
PriorityMust
Story points5
Labelsservice:care-plan, type:backend, type:api, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-004
Legacy FR refsFR-CP-003
DependenciesCAREPL-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/activities with description, assigneeId, and scheduleDetail, then the activity is created with status: 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.
  • assigneeId is a practitionerId soft reference.

Definition of Done: Standard DoD applies.


CAREPL-US-009 — Complete an activity

FieldValue
Issue typeStory
SummaryTeam member marks an activity complete with a completion note
Epic linkCAREPL-EPIC-03
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:backend, slice:S1
Componentscare-plan-service
FR referencesFR-CAREPL-004
Legacy FR refsFR-CP-003
DependenciesCAREPL-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_progress or not_started status, when I POST to /:id/activities/:actId/complete, then status becomes completed, completedAt is set.
  • Given an already completed activity, when I attempt to complete again, then 422 INVALID_STATUS_TRANSITION is returned.

Technical notes:

  • Emits care_plan.activity.completed.v1.

Definition of Done: Standard DoD applies.


CAREPL-US-010 — Manage care team members

FieldValue
Issue typeStory
SummaryAdmin assigns practitioners to care plan with roles and effective periods
Epic linkCAREPL-EPIC-04
StatusTo Do
PriorityMust
Story points5
Labelsservice:care-plan, type:backend, type:api, slice:S2
Componentscare-plan-service, provider-directory-service
FR referencesFR-CAREPL-005
Legacy FR refsFR-CP-004
DependenciesCAREPL-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-team with a list of members, then the team is replaced atomically and care_plan.care_team.updated.v1 is emitted.
  • Given a practitioner ID that does not exist in provider-directory-service, when I update the team, then 422 INVALID_PRACTITIONER is returned.

Technical notes:

  • Provider-directory-service validates practitionerId references.
  • 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

FieldValue
Issue typeStory
SummaryClinician views the current care team with roles
Epic linkCAREPL-EPIC-04
StatusTo Do
PriorityMust
Story points2
Labelsservice:care-plan, type:api, slice:S2
Componentscare-plan-service
FR referencesFR-CAREPL-005
Legacy FR refsFR-CP-004
DependenciesCAREPL-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 includes careTeam[] with practitionerId, role, and effectiveFrom.
  • Given a FHIR read, when I GET /fhir/R4/CareTeam?patient=Patient/:patientId, then a valid FHIR R4 CareTeam resource is returned.

Definition of Done: Standard DoD applies.


CAREPL-US-012 — FHIR CarePlan read for chart integration

FieldValue
Issue typeStory
Summarypatient-chart-service reads care plans via FHIR R4 CarePlan resource
Epic linkCAREPL-EPIC-05
StatusTo Do
PriorityMust
Story points5
Labelsservice:care-plan, type:fhir, slice:S1
Componentscare-plan-service, fhir-gateway
FR referencesFR-CAREPL-006
Legacy FR refs
DependenciesCAREPL-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 FHIR Bundle with conformant CarePlan resources 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.json validated in CI.
  • FHIR search parameters: patient, status, _count, _offset.

Definition of Done: Standard DoD applies.


CAREPL-US-013 — FHIR Goal read for portal integration

FieldValue
Issue typeStory
SummaryPatient portal reads goals via FHIR R4 Goal resource
Epic linkCAREPL-EPIC-05
StatusTo Do
PriorityShould
Story points3
Labelsservice:care-plan, type:fhir, slice:S4
Componentscare-plan-service, patient-portal-service
FR referencesFR-CAREPL-006
Legacy FR refs
DependenciesCAREPL-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:read scope, when querying, then 403 is returned.

Definition of Done: Standard DoD applies.


CAREPL-US-014 — Module entitlement gate

FieldValue
Issue typeStory
SummaryUnlicensed tenants receive 403 on all write operations
Epic linkCAREPL-EPIC-06
StatusTo Do
PriorityMust
Story points2
Labelsservice:care-plan, type:backend, type:security, slice:S0
Componentscare-plan-service, identity-service
FR referencesFR-CAREPL-007
Legacy FR refs
DependenciesIDENT-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_plans entitlement, when any write endpoint is called, then 403 MODULE_NOT_LICENSED is 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

FieldValue
Issue typeStory
SummaryZero cross-tenant data leakage proven by adversarial integration test
Epic linkCAREPL-EPIC-06
StatusTo Do
PriorityMust
Story points3
Labelsservice:care-plan, type:security, type:test, slice:S0
Componentscare-plan-service
FR referencesFR-CAREPL-007
Legacy FR refs
DependenciesCAREPL-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 carePlanId owned by Tenant A, then 404 CARE_PLAN_NOT_FOUND is returned (not a 403 that 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).