Changes from the 2025-08-20 proposal
This note accompanies Proposal for Federation Tier with AQL - revised and records what changed relative to the original openEHR International Federation Working Group proposal "Proposal for Federation Tier with AQL" (2025-08-20). The revised specification stands on its own and does not narrate this history; this note does.
Headline (breaking) changes
| # | Change | Where in the revised spec | Rationale |
|---|---|---|---|
C1 |
Federation is keyed on the per-node local |
MPI advisory §3 (storing an identifier in |
|
C2 |
The federated example that filtered |
§7 (before→after) |
Internal consistency: the old example keyed federation on |
C3 |
The gateway is defined as a transparent façade - a client can query and follow up without knowing it is federated; the API is a conformant openEHR Query API. |
HL7 Intermediaries White Paper (transparency). |
|
C4 |
Storing a directly identifying patient identifier in |
MPI advisory §3; RSO’s own "Hide"/external-ref migration note. |
|
C5 |
Identity / localization / addressing are bound to IHE profiles (PIXm, PDQm, XCPD, PMIR, mCSD) as the proposed binding, with the Dutch Generic Functions as a regional alternative in an informative annex. |
Consolidated design decision; MPI advisory §4. |
|
C6 |
Follow-up read and write routing is specified, provenance-honest: rows carry an endpoint identifier and routing uses the |
Intermediaries White Paper (routing follow-ups); Exchange-Routing IG (self-routing base URL). |
|
C7 |
Four previously-absent areas are added: authN/authZ handoff (§13), localization vs record-locator split (§14) and addressing (§15), follow-up routing (§12), and a Connectathon-style test guide (§16–§17). |
§12–§17 |
Gaps flagged in the change brief. |
C8 |
The federation surface is the whole ITS-REST API, read and write - not AQL alone - with the unsupported parts named (DEMOGRAPHIC; Definition management is single-node in v1 - stored queries have since gained an optional gateway registry, The SEC review amendments (0.9.x, no version bump)), the vendor |
Review meeting: transparency has to cover reads and writes, and the prefix is vendor-specific. |
|
C9 |
Identifier hygiene is specified beyond |
Review meeting: the |
|
C10 |
Completeness, timeouts and cross-node result shaping are made normative. Best-effort is the declared default with a |
§11.4–§11.6 (N37–N39) |
Review meeting: timeouts and the limit/order/aggregate interaction were left to implementers and are not safely inferable. |
C11 |
The four identifiers are pinned down. |
§ Terminology, §12a, §12b, §10.3, §12.5 (N36, N41, N42, N42a) |
Review meeting: these four were being conflated, and the failure mode is a mis-routed write. |
C12 |
Endpoint targeting is supported both in and outside the AQL. The gateway must accept |
Review meeting: stored and user-authored AQL should not have to be rewritten to retarget it; and writes have no |
Requirement mapping (old numbers → new N-numbers)
The 2025-08-20 proposal had 14 numbered requirements. The revised spec renumbers them as N1–N27 and adds N28–N43 (all new, from the review meeting - see C8–C12 above; none maps to an old requirement). The table below maps old→new and marks the change.
| New | Change | Old | Note |
|---|---|---|---|
new |
- |
Transparent façade: no indication it is federated. |
|
new |
- |
Accept |
|
new |
- |
Resolve |
|
new |
- |
Undirected queries get their candidate nodes from a localization service (candidates only - not consent). |
|
new |
- |
No directly identifying identifier required in |
|
new |
- |
|
|
changed |
#1 |
Dispatch standard AQL keyed on |
|
changed (SHOULD→MUST) |
#3 |
Dispatch only to nodes where the patient is resolved (plus any optional consent pre-filter, N27a). |
|
kept |
#13 |
|
|
changed |
#6 |
Accept an undirected query identifying only the patient. |
|
changed (merge) |
#7 + #8 |
Accept a directed query naming Endpoints (SHOULD: Organizations); directive is independent of patient resolution. |
|
kept |
#2 |
Add Endpoint/Organization attributes to rows when selected. |
|
changed (SHOULD→MUST) |
#14 |
|
|
changed |
#12 |
Block undirected aggregates unless cross-node-correct; directed single-node aggregate allowed. |
|
new |
- |
Default no dedup + provenance; opt-in |
|
kept (extended) |
(Unresponsive) |
Unresponsive nodes in |
|
kept |
(result format) |
|
|
kept |
(aliasing) |
ENDPOINT aliases resolve collisions with EHR columns. |
|
changed (merge) |
#9 + #11 |
FHIR |
|
kept |
#10 |
Every Endpoint has exactly one managing Organization (1..1). |
|
changed |
#4 |
Registry also maps |
|
new |
- |
Follow-up reads route to the owning CDR by |
|
new |
- |
Versioned writes route to the single controlling CDR; new objects target one chosen node. |
|
new |
- |
Convey authenticated client identity on every routed follow-up. |
|
new |
- |
Client authenticates to the Tier; the Tier propagates identity onward (OAuth 2.0 client-credentials with an RFC 7523 signed JWT client assertion). |
|
new |
- |
Delegate access decisions needing gateway-invisible information to the source CDR. |
|
new |
- |
Consent enforcement is the node’s obligation, performed regardless of upstream filtering. |
|
new |
- |
Step-1 consent pre-filtering is OPTIONAL, where a deployment has a consent service. |
|
new |
- |
ITS-REST at a deployment-chosen base URL; no mandated prefix ( |
|
new |
- |
Canonical path form and AQL predicate form both supported. |
|
new |
- |
|
|
new |
- |
Acting-endpoint response headers on routed requests; |
|
new |
- |
DEMOGRAPHIC not federated; unsupported areas declared; identifier namespaces distinct. |
|
new |
- |
In the composed query, a node is located by |
|
new |
- |
Node invocable on |
|
new |
- |
Targeting supported both in AQL and via the |
|
new |
- |
Post-dedup writes route to the originator; never to a holder of a copy. |
|
new |
- |
Best-effort default with |
|
new |
- |
Per-node and overall timeout budgets, discoverable and reported. |
|
new |
- |
Correct cross-node |
|
new |
- |
|
|
new |
- |
Path |
|
new |
- |
|
|
new |
- |
Identifier-integrity conditions a node must satisfy to be admitted (federation operator, at admission; §12b). |
|
new |
- |
Definitions single-node-routed; optional, explicit, non-atomic template broadcast. Now the template rule and the no-registry fallback - see The SEC review amendments (0.9.x, no version bump). |
|
new |
- |
Optional gateway-held stored-query registry: authoritative, immutably versioned, expanded into a fan-out when invoked by name. Added by The SEC review amendments (0.9.x, no version bump). |
Dropped / folded: old #5 (standalone Record Locator Service requirement) is split into localization (N4), addressing (N21/§15) and cross-reference (N3). The old federated WHERE …/subject example is replaced by the §7 before→after rewrite.
0.4.0: alignment with openEHR ITS-REST, and published schemas
Answering the question "is the federated AQL response not standard openEHR?" surfaced a gap no earlier review had noticed: most of the result envelope was already normatively defined by openEHR ITS-REST, and this specification never said so. §9 asserted a {q, columns, rows} + meta envelope as though it were new, and 0.3.1 went further by declaring its own example and table "jointly normative" for the whole structure, which this specification has no authority to do.
Each finding below has the same remedy: cite the standard that already exists, and scope this specification’s contract to what it actually adds. The bound release is ITS-REST Release-1.1.0 (19 July 2026), pinned by name so that the citation fixes one wire format; a latest pointer would not.
| # | Finding | Where in the spec | Disposition |
|---|---|---|---|
F1 |
|
Stated. The reassuring finding, and the one most worth writing down. |
|
F2 |
|
Adopted by reference. N17 now cites the ITS-REST member list in place of its own enumeration, so the list cannot drift from ITS-REST again. |
|
F3 |
The §9 example contradicted ITS-REST on |
Resolved in favour of ITS-REST; the example was wrong and is corrected. The |
|
F4 |
The underscore convention was unstated. Standard |
Stated normatively. The |
|
F5 |
|
Scoped to dispatch. Required for |
|
F6 |
Two |
Added to the example, and |
|
F7 |
The membership status vocabulary was undefined. §7a.2 said what the |
Declared open. It is a free-form string, and |
Two JSON Schemas are now published and enforced in CI (§18 previously promised them):
-
federated-result-set.schema.json- the result envelope. It does not restateRESULT_SET; it inlines a constrained subset of the ITS-REST definitions, each commented with its source, and adds the federation’smetaconstraints. The definitions are inlined instead of$ref-ed by URL so that validation is self-contained and CI does not depend on a third-party site being reachable. -
options-root.schema.json- theOPTIONSbody, which has no upstream standard and is therefore normative in this specification alone.
tools/check-schemas.sh validates every whole-instance [source,json] block in the specification against the schema that governs it, and compiles both schemas. It would have caught F3 automatically, and did catch F5 and F6 while being written.
This release is 0.4.0, not 0.3.2: correcting rows changes the wire contract, so federation.spec_version moves from "0.3" to "0.4".
0.9.0: validated by implementation
This release changes no normative requirement, no wire structure and no schema. It changes the specification’s standing: every section of the normative body has now been built against real openEHR CDRs by a reference implementation whose conformance suite mirrors §17 one-to-one. The version number moves because a text that has been implemented end to end is a different artifact from one that has only been reviewed.
Why 0.9.0 and not 0.5.0. The number measures remaining distance from 1.0 and says nothing about the volume of change in this release. The document is feature-complete for its stated scope and has survived implementation, and 0.5.0 would have understated that. The remaining work before 1.0 is external: working-group review, a second independent implementation, and settling the items §18 defers.
Implementation findings are recorded where they apply and are not repeated here. The 0.4.0 findings above (F1-F7) came from building the reference implementation, and the corrections they describe shipped in 0.4.0 as they were found, so this release records no new findings.
Status moves from "Draft for review" to "Release candidate". The new status describes stability and does not claim finality: the specification remains open for comment, nothing in it is frozen, and a release candidate can still be withdrawn.
federation.spec_version moves from "0.4" to "0.9". The move is the only client-visible consequence. The field is major.minor and tracks minor releases (§7a.2), so it moves even though no structure changed. It reports which release a gateway was built against, and a client pinned to "0.4" should learn the document has moved on. Clients matching that value exactly will stop matching. Per §7a.2 they were already forbidden from matching a patch component, and a client needing to accept both should compare the minor version and not the literal string.
The SEC review amendments (0.9.x, no version bump)
A review with SEC raised four points. Three change the wire contract, and one closes a guidance gap. All four landed in the 0.9.x line.
|
These changes landed without a version bump on purpose, and that is a known hazard
The consequence is a real hazard, accepted knowingly: two different wire contracts now exist under the marker The bump is owed before any release. It is recorded as an open item in §18 so it cannot be lost, and A fifth site sits in another repository. The reference implementation ( |
| # | Change | Where in the spec | Rationale |
|---|---|---|---|
S1 |
The federation’s |
§9.1, §9.4, §9.5, N17, CP-35, |
SEC: nothing on the wire said which |
S2 |
All-or-nothing becomes the default completion strategy; best-effort becomes opt-in. A query in which an in-scope node was asked and did not answer now fails - |
§11.4, §11.3, §11.2, N37, CP-30, CP-12, |
SEC: best-effort is the wrong default for clinical data. An incomplete answer that looks complete is a safety hazard, because a clinician who does not know a node was missing may conclude the data does not exist. The mode is retained because a flagged partial answer can beat no answer. |
S3 |
A gateway MAY hold federated stored queries in an authoritative registry. The gateway stores the definition, versions it immutably on ITS-REST’s own semver path segment, and expands it into an ordinary fan-out when it is invoked by name - which makes a federated query invocable by name at all. Distribution of the definition to nodes is a further option on §12.6’s template-upload terms, and an endpoint-targeted definition MUST NOT be distributed. Drift between the registry’s copy and a node’s is named as a new hazard the facility creates. Additive: §12.6/N43’s single-node rule is unchanged and is the fallback. |
§12.7, §7a.1, §7a.2, N44, CP-40, §9.1, |
SEC: stored queries had no federation story. A definition lived at one node, so invoking it by name got one node’s answer, and two nodes could hold different definitions under one name with nothing to detect the drift. |
S4 |
§13.4 states what a deployment MUST settle about authentication - a checklist of obligations, not mechanisms: which identity crosses the trust boundary and against which authentic source, who authenticates the end user and where that trust stops, how purpose of use is conveyed, what the token is bound to (and whether transport identity is being read as organization identity), and which risks are carried by agreement and which by technique. The federated trust model is named as the model behind the checklist. Annex B gains §B.4a, documenting the VWS Harmonisatie track (concept v0.9, 13 July 2026) as a distinct national track from the Nuts GF profile of §B.4. |
SEC: §13 did not say what a deployment must decide, nor that it must decide it. The normative body still cannot prescribe a concrete solution, being deployment- and region-specific, so the obligation is to answer the questions, with the Dutch answers kept informative in the annex. |
What is left out, and why. No specific authentication profile was hoisted into the normative body, because FAPI 2.0 and RAR are §B.4a’s answers to two of §13.4’s questions and other programmes may answer them differently. The _-prefix rule was not relaxed to carry the grouping: prefixing is openEHR’s namespace and S1 does not borrow it.
Corrections found while aligning the reference implementation (2026-09-28)
Implementing S2 in syntaric/openehr-federation-ref exposed three gaps in the amended text. All three are in the 0.9.x line, under the same no-bump hazard as the SEC amendments above.
| # | Change | Where in the spec | Rationale |
|---|---|---|---|
R1 |
A |
§11.1, §11.2, §11.4, §9.5, N16, N37, N40, CP-11, CP-30, |
S2 split the failure into |
R2 |
Reporting out-of-scope members is now a SHOULD. §11.1 required every in-scope node to appear and defined |
A gateway that dropped directive-excluded members from the list was conformant by the letter and contradicted the example. §14.1’s fail-closed MUST for |
|
R3 |
§10 names the dedup members. |
Editorial; no wire change. |
Other notable edits
-
Result set:
system_idadded to the selectable ENDPOINT attribute set, so a row can carry the openEHR-native routing key (§9). -
Deduplication: the imported-composition case (same
object_id, two `creating_system_id`s) is now handled by an opt-in VERSION-identity dedup (§10). -
Partial results: the endpoint status set is extended and mapped to HTTP status codes aligned with the Exchange-Routing IG; "patient found nowhere" is a
200with empty rows, not a404(§11). -
Diagrams: the two reference-flow sequence diagrams are authored in PlantUML (
diagrams/*.puml) and embedded as rendered images. -
Spec vs regional realisation: all Dutch-specific detail (Mitz/OTV, NVI, LRZa,
did:web/VC/DPoP, Rego/mitz_consent, pseudonymised-BSN localization) and the ACP/Vitaly worked example stay in the informative Annex B. The normative body names only abstract roles and their proposed IHE binding (§2.4).