4.4 KiB
patient-records — the care plan and visit records
Client seam
client/src/services/patientRecords/·USE_PATIENT_RECORDS_MOCK = true(mock is primary) · 5 server ops Last verified: 2026-07-30 against commitd3ec723and swagger.v1.json (2026-07-29).
The clinical content: a family-owned care plan (medications, routine, tasks) and the append-only visit records nurses write against it. The patient rows themselves are patients.md.
Endpoints
| Method | Path | Verdict |
|---|---|---|
| GET | /api/v1/patients/{patientId}/care_record |
wired — the care plan |
| PUT | /api/v1/patients/{patientId}/care_record |
wired — the only PUT in the API |
| GET | /api/v1/patients/{patientId}/care_records |
wired · paginated (page/pageSize) — visit history |
| POST | /api/v1/patients/{patientId}/care_records |
wired — a nurse writes one visit record |
| GET | /api/v1/patients/{patientId}/record_access |
wired — ask before you read |
All [Authorize]. No phantoms — every route the client calls exists. The seam is mocked for UI
completeness, not because the contract is missing.
Singular vs. plural is load-bearing here:
care_record(nos) is the plan;care_recordsis the visit history. They are different resources on adjacent paths.
Two different ownership models on one path
care_record (plan) |
care_records (visits) |
|
|---|---|---|
| Owner | the family (the customer) | the nurse who performed the visit |
| Write | PUT — upsert, replaces |
POST — append only |
| Edit after the fact | yes, it is a living plan | no |
| Delete | no | no |
A nurse can never edit or delete a visit record. It is a clinical record: append-only is the whole point, and there is no endpoint that would allow otherwise. Do not add one.
record_access — check before you read
GET record_access answers "may this caller read this patient's records, and if not, why". The client
calls it first and renders the denial state rather than firing a read and interpreting an error.
Two reasons come back, and they are deliberately hard to tell apart from outside:
RecordAccessDeniedReason |
Means |
|---|---|
no_access |
The patient exists; you are not authorised |
not_found |
No such patient — or a tenancy mismatch |
That second row is the platform's tenancy rule: a row you do not own is a 404, never a 403, because a 403 confirms it exists. See ../api-contract.md.
Shape rules the JSON does not express
- Every record body is encrypted at rest and decrypted only for an authorised caller. Care content is never projected into a list, never logged, and never included in a search index.
- Nurse read access is scoped by an active booking, not by having ever cared for the patient. The two-stage clinical disclosure rule applies: full care content is readable only post-confirmation, only by the assigned nurse and admin. See bookings.md.
CarePlanDtois{ patientId, medications, routine, tasks }— three structured lists, not free text, so the client can render a schedule and a checklist rather than a blob.CareRecordDto.taskResultsis structured (REQ-027, delivered): each visit reports per-task outcomes against the plan's tasks, which is what lets the family see whether the routine was actually followed.nurseNameis on the visit record so the history is attributable without a per-row lookup.- Dose units, frequency presets and times-of-day are codes; the UI labels are i18n keys. Never render the code, and never parse a frequency into a schedule client-side.
Enums
| Vocabulary | Values |
|---|---|
DoseUnit |
tablet capsule drop cc unit |
FrequencyPreset |
once_daily twice_daily three_times_daily every_8_hours as_needed |
TimeOfDayCode |
morning noon evening night |
RecordAccessDeniedReason |
no_access not_found |
CareRecordTab (client UI only) |
medications routine history tasks |
as_needed (PRN) has no time-of-day and must not be rendered on a schedule grid.
Open REQs
| REQ | Status | Effect |
|---|---|---|
| REQ-027 | delivered | The family-owned care record (medications/routine/tasks), record_access, and structured task results are all served |