Conformance levels

Non-normative in itself; the levels it defines are normative for every engine crate's documentation.

A crate MUST NOT claim a level it has not earned, and its README MUST state its level in the first screenful. This exists because the sibling FHIR monorepo in this repository shipped six READMEs claiming a working store, a CLI, and 7,399 losslessly round-tripped resources — in ports where two had no store at all and none had ever had a CLI (F-01).

The levels#

Level Means Evidence required
Dialect Emits DDL for the shared schema. The golden DDL tests, and [conformance::check_dialect].
Schema The engine itself has executed that DDL. A transcript against that engine's own server: the script applied cleanly, applied again cleanly, and the append-only tables were observed refusing UPDATE and DELETE with a row present.
Store Implements Store against a real database. [conformance::run] passing against that engine.
Verified Store level, run in CI against the engine's own server on every commit. A CI job that provisions the engine and fails — not skips — without it.

Schema is a level because the step from Dialect to Schema found three defects that no golden test could have found; see A-13, A-14, and A-15 in the register.

A level is a claim about the present, not about an afternoon in the past. The schema job in .github/workflows/openehr.yml runs scripts/verify-schema.sh for PostgreSQL and MySQL on every change under openehr*/, so both crates' Schema claims are continuously checked rather than attested once. The job provisions its own container instead of using GitHub's services:, so the command in CI is byte-for-byte the command a contributor runs locally — two ways of doing the same check drift, and the one that drifts is always the one nobody runs.

The same job must fail, never skip, when a database is absent. The sibling monorepo carries F-06 for two ports whose database jobs invoked a test target that did not exist, so they could not have passed and did not say so.

The "with a row present" clause is not pedantry. The first enforcement run looked like a pass and proved nothing: the DELETE matched zero rows, and a FOR EACH ROW trigger on zero rows never fires. A test whose subject is absent reports the silence as success.

Where each crate stands today#

Assessed 2026-08-01. Anything not in this table is not claimed.

Crate Level What is verified What is not
openehr-sqlite Store The full suite against a real in-process database: every commit rule, every read, the archetype index, the append-only triggers, DDL idempotence. Nothing runs in CI yet, so the level is Store and not Verified.
openehr-postgresql Schema DDL executed against PostgreSQL 18: 5 tables, 7 indexes, idempotent across repeated runs, foreign keys enforced, and both append-only tables refused UPDATE and DELETE with the row surviving unmodified. No driver and no Store.
openehr-mysql Schema The same, against MySQL 8.4. as above
openehr-mssql Dialect DDL emission, type distinctness, quoting, identifier coverage, and that the declared catalogue guard is actually emitted. No server has parsed it. SQL Server 2022 segfaults under qemu on arm64, so it could not be run on the machine available; this is a gap in evidence, not a judgement that it works.
openehr-oracle Dialect as above, plus Oracle's identifier-length limit. as above; the Oracle images additionally require registry authentication.

What "Dialect" deliberately does not mean#

It does not mean the DDL runs, and the two crates still at this level should be read accordingly. The golden tests assert what the emitter produces, not that a parser accepts it — those are different claims, and the sibling monorepo has two findings (F-25, F-26) for a migration path that could never have executed in a port with no store to notice.

The distance between the two claims is now measured rather than asserted. Both crates that moved to Schema were wrong at Dialect level, and passed every golden test while being wrong.

Why the shared logic being verified once is worth something anyway#

The commit rules, the projection onto rows, the ordering semantics, and the conformance suite live in openehr-store and are shared by all five. Running them against SQLite exercises that logic for every engine. What stays unverified per engine is the DDL against a real parser and the driver glue — which is narrow, but is exactly where an untested engine crate will fail.

View this page's source on GitHub — the crates are the source of truth; this site renders them.