doc clean up phase 2
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# 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 commit `d3ec723` and 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](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` (no `s`) is the **plan**; `care_records` is 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](../api-contract.md#status-codes).
|
||||
|
||||
## 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](bookings.md).
|
||||
- **`CarePlanDto` is `{ 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.taskResults` is 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.
|
||||
- **`nurseName` is 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 |
|
||||
Reference in New Issue
Block a user