openehr 0.7.0

openEHR Reference Model types, validation, paths, AQL parsing, and change-control security primitives
Documentation
# 11. Security

Requirement prefix: `X11`.

openEHR fixes the audit model and deliberately leaves access control open.
This section says what the crate supplies on top, and — at least as
importantly — what it does not.

## The trust boundary

- **X11.1** The crate MUST NOT authenticate, and MUST document that the
  deployment supplies authentication, group membership, transport security, key
  storage, consent capture, and log retention.
- **X11.2** The crate MUST record **who acted** on every version (`V8.13`).
  Authentication is outside on purpose; attribution is not — a perimeter knows
  the identity and only the record knows which nodes were touched, so neither
  can answer an access complaint alone.

## Access control

- **X11.3** `EHR_ACCESS` settings in a scheme the crate does not implement MUST
  be carried unchanged through a read-modify-write, and MUST NOT be evaluated.
- **X11.3a** Dispatch between schemes MUST be by the declared scheme name and
  never by object shape. A shape-based reader would match a foreign policy as
  the reference scheme and discard its attributes, turning an intact
  un-evaluatable policy into an empty one that denies and looks deliberate.
- **X11.4** Every access decision MUST default to deny. There MUST be no
  "unknown" outcome a caller might read as permissive.
- **X11.5** Denial reasons MUST be distinguishable — no policy recorded, scheme
  not implemented, principal not in a permitted group — because each calls for a
  different response, and "denied" leaves an operator nothing to act on.
- **X11.5a** Reading the audit trail MUST be expressible as an operation
  separate from reading clinical content. An information-governance officer
  investigating an access complaint needs the trail and not the record.

## PHI in output

- **X11.6** No `Display` implementation may render PHI. `DV_IDENTIFIER` renders
  its type and issuer; `DV_MULTIMEDIA` has no `Display` and a `Debug` that
  prints shape only.
- **X11.7** No error may echo a submitted value. An error message is the one
  place a value reaches a log, a response, and a support ticket at once.
- **X11.7a** The single exception is a lexical rejection of **design-time
  vocabulary** — an archetype id, a terminology id, a code — where an error that
  will not name the identifier is unactionable. Even there the echoed text MUST
  be truncated, so that a document passed to a parser by mistake is not logged.
- **X11.8** A wrapper MUST be provided for values that must pass through code
  that logs, hiding them from `Display` and `Debug` while keeping them for
  serialization. Protecting serialization would corrupt the record rather than
  protect it; the accidents happen in logs.

## The audit chain

- **X11.9** The chain MUST digest each entry over its predecessor, so that
  altering any entry invalidates every entry after it.
- **X11.10** Documentation MUST state plainly what an **unkeyed** chain buys: it
  detects careless or unaware modification and supports an external witness, and
  it does not stop an informed attacker with write access, because the digests
  are unkeyed over a published pre-image.
- **X11.11** A keyed tag (`HMAC-SHA-256`) MUST be available, and the key MUST
  live in the process rather than in the store it protects.
- **X11.12** Tag comparison MUST be constant-time. A timing oracle lets an
  attacker with write access recover a valid tag byte by byte.
- **X11.13** Only a **tag mismatch** is a tampering finding. A missing tag, a
  tag naming a key this process does not hold, and a malformed tag MUST each be
  reported as what they are. Reporting a key-distribution problem as forgery
  burns an incident response.
- **X11.14** Key identifiers MUST travel with tags, so rotation is additive.
  Without the identifier, rotating would invalidate all history at once —
  indistinguishable from mass tampering.
- **X11.15** Chains MUST NOT be backfilled. A chain assembled after the fact
  attests only that the rows look consistent now, which is exactly what an
  attacker who rewrote them would produce. Beginning late MUST be recordable and
  recorded.
- **X11.16** Chain keys MUST be at least 32 bytes and MUST be zeroized on drop.
- **X11.17** A `Debug` on a key MUST NOT print its material.
- **X11.18** SHA-256, not SHA-1 (`D3.27`).
- **X11.19** A checkpoint form MUST be available that carries **no** patient
  data — counts and digests only — so it can be shipped to a long-retention log
  where clinical data must not go. That separation is what makes a log-based
  witness practical.

## Redaction

- **X11.20** Withheld content MUST be **masked**, not deleted:
  `272|masked|` (`R4.7`). Deleting turns "the patient has withheld their sexual
  health history" into "the patient has no sexual health history", which is a
  clinical statement nobody made.
- **X11.21** A redacted document MUST still satisfy validation. A filter that
  produced something the receiving system rejects has achieved nothing.
- **X11.22** Redaction MUST report **how much** it withheld and MUST NOT name
  **what**. An access log saying "12 elements withheld" is auditable; one saying
  "HIV status withheld" is a disclosure inside the audit trail.
- **X11.23** A recorded redaction reason is written into the document and MUST
  therefore not name the withheld value or its clinical category.
- **X11.24** Redaction MUST fail closed: on error nothing is returned, so a
  caller cannot forward the unredacted original by mistake.
- **X11.25** Redaction rules address `ELEMENT`s. Composer, participations, and
  the audit trail are not withheld by an element rule, and the documentation
  MUST say so — stripping those is de-identification, a different operation with
  different rules.