openehr 0.2.0

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

Requirement prefix: `L10`.

## Two gates

- **L10.1** Constructors MUST enforce the invariants of the class they build, so
  that data the program **builds** cannot be invalid.
- **L10.1a** Validation MUST enforce them on data the program **receives**.
  `serde` writes fields directly and never calls a constructor, so a document
  read from a wire has passed no gate but this one.
- **L10.1b** Documentation MUST state that a service which deserializes and
  stores without validating has no invariant checking at all, whatever its
  constructors do.

## What validation means, and what it does not

- **L10.2** Validation is **Reference-Model-level only**. Wherever it is
  offered, the documentation MUST state that a passing composition can still
  violate its archetype, because archetypes are out of scope (`S1.4`).
- **L10.3** Validation MUST collect every violation, not the first. A caller
  fixing a rejected composition wants the whole list; one violation per round
  trip turns a five-minute fix into five deployments.
- **L10.4** Every violation MUST name the path to the offending node, the RM
  class, and the invariant **using openEHR's own invariant name**, so a reader
  can find it in the class definition without a translation step.
- **L10.5** No violation may include node content (`X11.7`). Paths, class names,
  and invariant names only.
- **L10.5a** A violation MUST be attributed to the class whose invariant it
  actually breaks. An empty `LOCATABLE.name` breaks `DV_TEXT.Value_valid`, not
  `LOCATABLE.Name_valid` — openEHR's `Name_valid` is only `name /= Void` — and
  the wrong attribution sends a reader to the wrong class definition.

## The checks

- **L10.6** Validation MUST check, at minimum: `ELEMENT`'s value/null-flavour
  exclusivity (`R4.3`) and null-reason rule (`R4.4`); the null flavour's
  membership of the openEHR group (`R4.5`); `CLUSTER` non-emptiness (`R4.8`);
  `ITEM_TABLE` regularity (`R4.9`); `HISTORY` non-emptiness (`R4.11`) and event
  ordering against origin (`R4.13`); `INTERVAL_EVENT` width sign (`R4.15`);
  `LOCATABLE` node id and name (`M5.2`); `ARCHETYPED` class agreement (`M5.7`);
  `DV_CODED_TEXT` rubric agreement for openEHR codes (`D3.7`); `DV_QUANTITY`
  finiteness, units, and precision (`D3.19`, `D3.20`); `DV_PROPORTION`
  denominator and integrality (`D3.23`); `DV_MULTIMEDIA` content presence and
  integrity (`D3.26`); `PARTY_IDENTIFIED` basic validity (`M5.14`);
  `COMPOSITION.category` group membership (`E6.6`); `EVENT_CONTEXT.setting`
  group membership (`E6.11`); `ISM_TRANSITION.current_state` group membership
  (`E6.21`).
- **L10.7** Violation order MUST be stable across runs — depth-first, document
  order — so that a report diffed between two runs shows real change.
- **L10.8** Where a check cannot be performed, the result MUST be reported as
  *not checked* rather than as a pass (`D3.7`).