12a. Which identifier routes what
The four identifiers (node_id, endpoint_id, system_id, creating_system_id) are defined in § The four identifiers. This section is the normative part: which one governs which request. Getting it wrong produces the worst class of bug in this architecture, a follow-up write delivered to the wrong CDR, and that bug succeeds silently.
12a.1 Routing rules (normative)
-
A follow-up read of a specific
VERSIONis EHR-scoped in ITS-REST ({base}/v1/ehr/{ehr_id}/composition/{uid},{base}/v1/ehr/{ehr_id}/versioned_composition/{versioned_object_uid}/version/{version_uid}) and MUST be routed per route-ehr, on the pathehr_id.creating_system_idis a routing source only at step 4 of §12.5.1, after the explicit target, the binding and the index have named no node (§12.3, N22). If the located node holds an imported copy, the client receives that copy, and can tell because theopenEHR-federation-system-idresponse header (§7a.3) then differs from thecreating_system_idin the uid it requested. -
A versioned write MUST be located per route-ehr and then committed only at the CDR that controls the target object. Control is established by
system_id == creating_system_idof the target version - i.e. the CDR where the version was created, not merely a CDR that holds a copy of it. If the located node’ssystem_iddiffers, the gateway MUST reject the write with409 Conflictnaming the controlling system, and MUST NOT redirect it to the owner under the holder’sehr_id(§12.4, N23, and the imported-copy hazard in §10.3). -
An EHR-scoped request (
{base}/v1/ehr/{ehr_id}/…), including a version read and a versioned write, MUST be routed on the pathehr_id: on theehr_id→ node binding established during resolution (§5.2) or carried explicitly by the client (§12.5), in the order of §12.5.1.creating_system_iddescribes versions, not EHRs, so it enters that order only at step 4, when the path carries anOBJECT_VERSION_IDand the earlier steps named no node. -
A fan-out query is dispatched per
endpoint_id(§8), and every contributing endpoint MUST be reported inmeta.federation.endpoints[]under that same identifier (§9.5). -
A result row that will be used for follow-up SHOULD carry both
endpoint_id(where the row came from) and the uid (which carriescreating_system_id). They answer different questions:endpoint_idsays who told me,creating_system_idsays who owns it. When they disagree, the row is a copy - see §10.3. -
node_id,endpoint_idandsystem_idMUST be distinct namespaces. A gateway MUST NOT accept asystem_idwhere anendpoint_idis expected (or vice-versa) merely because the strings happen to coincide, and the registry MUST be able to answer each lookup unambiguously. (N32.)
12a.2 Summary table for implementers
| Question | node_id |
endpoint_id |
system_id |
creating_system_id |
|---|---|---|---|---|
Where do I send this fan-out query? |
- |
✔ |
- |
- |
Which node contributed this row? |
✔ (via endpoint) |
✔ |
✔ |
- |
Where do I read this VERSION from? |
- |
✔ (from the |
via registry (step 4) |
step 4 / copy test |
Where do I commit a new version of this object? |
- |
✔ (located by the |
✔ (must equal) |
✔ (must equal) |
Where do I send |
- |
✔ (from the |
- |
- |
Who is accountable / audited? |
✔ |
- |
- |
- |
Who is admitted to the federation? |
✔ |
- |
- |
- |