openehr 0.2.0

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

Requirement prefix: `S1`.

## What the crate is

- **S1.1** The crate MUST implement the openEHR **Reference Model** — the BASE
  identification and foundation types, and the RM Data Types, Data Structures,
  Common, EHR, and Demographic packages — as Rust types with construction-time
  invariant checking.
- **S1.2** The crate MUST implement openEHR **canonical JSON** (ITS-JSON)
  serialization and deserialization for every type it models (§9).
- **S1.3** The crate MUST implement the openEHR **support terminology** groups
  that the Reference Model refers to by code (§3, §4, §6, §8).

## What the crate is not

The exclusions below are decisions, not omissions. Each names why, because a
reader deciding whether to use this crate needs the reason more than the fact.

- **S1.4** The crate MUST NOT implement the **Archetype Model** — ADL, AOM2,
  templates, or archetype-constraint validation. An archetype is a constraint
  language with its own parser and its own conformance rules; implementing a
  partial one would let "valid" mean "the parts I understood were satisfied".
  Consequence: [validation]10-validation.md is Reference-Model-level only,
  and `L10.2` requires that to be stated wherever validation is offered.
- **S1.5** The crate MUST NOT execute AQL. Executing means resolving archetype
  paths against a repository of versioned objects, and the crate has no
  repository. It parses and statically checks AQL instead (§12).
- **S1.6** The crate MUST NOT implement the **EHR Extract** model or the
  **Integration** package. Both exist to move data between systems, which is a
  service concern; the crate is a library.
- **S1.7** The crate MUST NOT implement an HTTP service, a persistence layer, or
  a command-line tool. Nothing in this repository builds any of them, and no
  documentation may suggest otherwise (`C0.11`).
- **S1.8** The crate MUST NOT interpret HL7 `GTS`, `PIVL`, or `EIVL`
  expressions inside `DV_TIME_SPECIFICATION`. It validates the wrapper and
  carries the expression opaquely. A partial timing engine produces a dosing
  schedule that is right most of the time.
- **S1.9** The crate MUST NOT convert units. `DV_QUANTITY` comparison is by
  exact units match (`D3.15`). A silent `mg`-to-`g` conversion is a
  thousand-fold dosing error that nothing downstream detects.
- **S1.10** The crate MUST NOT resolve external terminologies. `SNOMED-CT`,
  `LOINC`, and `ICD-10` codes are carried opaquely and checked only for
  `CODE_PHRASE` well-formedness (`D3.5`).
- **S1.11** The crate MUST NOT encrypt, and MUST NOT verify the `OpenPGP`
  signature in `ATTESTATION.proof`. Both require key management that belongs to
  the deployment (§11).

## How an exclusion behaves

- **S1.12** Where openEHR defines an operation that this crate does not
  implement, the operation MUST return an explicit `Unsupported` error naming
  what is missing and the specification section that records the exclusion. It
  MUST NOT return a plausible default, a zero value, or a silent success.
- **S1.13** A type whose openEHR definition includes an unimplemented operation
  MUST still round-trip that type's data losslessly (§9). Not interpreting a
  value is not a licence to lose it.

## Boundaries the caller must supply

- **S1.14** The crate MUST NOT authenticate. It records who acted; establishing
  who they are is the deployment's (`X11.1`).
- **S1.15** The crate MUST NOT bound recursion depth on deserialization, and its
  documentation MUST state that a caller reading untrusted documents has to.
  Unbounded nesting is a denial-of-service vector in every recursive reader, and
  a limit chosen by a library is either too low for a legitimate document or too
  high to be a limit.

## Versions of openEHR

- **S1.16** The crate targets openEHR **Reference Model 1.1.0** and the
  terminology published in `openEHR/specifications-TERM`. `ARCHETYPED.rm_version`
  is carried and not enforced: data authored against 1.0.2 is readable, and the
  version it declares is preserved so a caller can decide.
- **S1.17** Where the current terminology disagrees with the older
  `openEHR/terminology` repository, the current one governs, and the divergence
  MUST be recorded where the codes are defined (see `src/terminology.rs`).

- **S1.18** *Departure from `COMPOSITION.Territory_valid` and
  `COMPOSITION.Language_valid`.* The crate MUST NOT validate `territory` against
  ISO 3166-1 or `language` against ISO 639-1. It checks `CODE_PHRASE`
  well-formedness only (`D3.5`), so `ISO_639-1::zz` is accepted although `zz` is
  not a language.

  **What openEHR requires.** RM 1.1.0 states both as invariants on `COMPOSITION`:
  `code_set(Code_set_id_countries).has_code(territory)` and
  `code_set(Code_set_id_languages).has_code(language)`. These are code sets
  openEHR names, so `S1.10` — which excludes *external* terminologies like
  SNOMED CT — does not cover them. This is a genuine departure and is declared
  here because an undeclared one is a defect rather than a decision (`C0.12`,
  `C0.14`).

  **What survives.** Structural validity: the code is well-formed and names the
  right terminology id. What is lost is membership — a caller may store a
  syntactically valid code that denotes no country or language, and nothing here
  will say so.

  **Why declared rather than implemented.** Both code sets are closed, small, and
  *mutable*: ISO 3166-1 gains and retires codes, and a table compiled into a
  library is wrong from the day a country changes. Validating against a stale
  copy would reject conformant data, which `D3.5`'s own reasoning calls the worse
  failure. A deployment that needs the check should do it where the tables can be
  updated. Recorded as `A-19`; implementing it remains open.