Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Clinical safety risk file

Annex II, point 1.1, of Regulation (EU) 2025/327 on the European Health Data Space (the EHDS Regulation) asks that the harmonised software components of an EHR system “achieve the performance intended by its manufacturer” and be designed and manufactured so that, “during normal conditions of use, they are suitable for their intended purpose and their use does not put at risk patient safety”. This page is FerroFED’s risk management file for its two harmonised components (Art 25(1)): the European logging software component and the European interoperability software component. It names each hazard, the control that answers it, and the test or code that implements the control, by path. A control that is not built is marked planned, with its issue.

The Annex II checklist that #525 builds cites this page for point 1.1, by hazard id. Every quotation of the Regulation is from the Official Journal text, vendored at docs/specs/eu-ehds/reg-eu-2025-327-en.xhtml. This page is not legal advice.

Scope

ComponentWhere it isWhat it does in this release
Logging (Art 2(2)(o))crates/ehds-logging, with the record built in app/ferrofed-server/src/access/records every access to patient data the gateway intermediates (The access log)
Interoperability (Art 2(2)(n))crates/eehrxfa library: the EHDS dataset model and the mapping of one openEHR composition to a FHIR R4 Bundle; the gateway does not serve it

Both components ride on the federated query path: the logging component records what that path did, and the interoperability component will build its documents from what that path returns. The federation hazards the interoperability component inherits are therefore assessed here with it, and their controls on the query path are named.

The file covers the use the intended purpose states and the misuse a deployment can reasonably make of it: a wrong configuration, a client that ignores meta.federation, a member that breaks the conditions of membership. It does not cover a client application’s own presentation, which is that application’s to assess.

Method

The Regulation names no standard for this assessment, so no specification governs the method: our own design. The file follows the risk management process of EN ISO 14971:2019, Medical devices: Application of risk management to medical devices, as a method. FerroFED claims no conformity with that standard, and its documents do not classify it as a medical device (The medical device question). The standard’s text is copyrighted and not vendored; the clauses below are named by the standard’s table of contents.

EN ISO 14971:2019Where this file answers it
4.4 Risk management plan, 4.5 Risk management filethis page, Method and Review and change
5.2 Intended use and reasonably foreseeable misuseScope
5.4 Identification of hazards and hazardous situationsthe hazard tables
5.5 Risk estimationthe severity and occurrence scales below, the “Before” column
6 Risk evaluationthe acceptability rule below
7.1 Risk control option analysisthe order of controls below
7.2 Implementation of risk control measuresthe “Control” and “Implemented by” columns
7.3 Residual risk evaluationthe “After” column
7.5 Risks arising from risk control measuresthe hazards a control itself creates, L-02 and L-05
8 Evaluation of overall residual riskOverall residual risk
9 Risk management review, 10 Production and post-production activitiesReview and change

Sources of hazards. The four hazards a federated summary adds to a CDR’s own, named when this file was opened: duplicate entries across nodes, a silent node, an unmapped code and a demographic mismatch. Then the Federation Tier’s failure statuses (§11.1, §11.2), the serious-incident classes of Complaints and incidents, the threat model, and each point of Annex II, 3.2 to 3.4, read as “what if this field is wrong or missing”.

Severity. The harm the hazardous situation can lead to. Art 2(2)(r) names the serious ones: “the death of a natural person or serious harm to a natural person’s health” and “serious prejudice to a natural person’s rights”.

LevelHarm
S1none to care or rights
S2care is delayed, or a record of access is incomplete in a way the deployment can see and correct
S3a person’s rights are prejudiced: a restriction is shown, an access goes unrecorded, a patient identifier is disclosed; or a clinician decides on information that is incomplete or wrong where the harm is reversible
S4a clinician decides on information that is incomplete or wrong, where the harm to health can be serious

Occurrence. For software, how readily the hazardous situation arises, judged qualitatively.

LevelThe hazardous situation arises
P1only through two independent faults, or a misconfiguration config check refuses
P2through one fault in another system, or one misconfiguration nothing refuses
P3in normal use

Acceptability. A risk is acceptable after control at S1 at any level, at S2 at P2 or P1, and at S3 or S4 at P1 alone. A control counts only when it is built and a test holds it. A hazard whose control is planned keeps its “Before” rating and is open; the component it belongs to is not offered for its Annex II purpose while a hazard of S3 or S4 is open.

The order of controls, after clause 7.1: a design that cannot produce the hazardous situation first; then a protective measure in the software, such as refusing the request or failing closed; then information for safety, which the instructions for use carry.

The logging component

IdHazardous situationHarmBeforeControlImplemented byAfter
L-01An access to patient data leaves no access record: the sink cannot store it, or a path of the gateway hands out data without onethe person cannot learn who read their data (Art 9), and misuse goes unseenS3, P2the record is stored before the answer leaves; when it cannot be, the access is refused 503 access-unrecorded with no data; an answer that carries data and reports no access is withheld; only the server builds a recordapp/ferrofed-server/src/access/mod.rs; app/ferrofed-server/tests/it/access/routed.rs (every_access_whose_record_the_spool_cannot_take_is_refused_with_no_data, a_stored_query_whose_record_the_spool_cannot_take_is_refused_with_no_data); app/ferrofed-server/tests/it/access/gate.rs (a_patient_data_answer_that_reports_no_access_is_withheld); app/ferrofed-engine/tests/it/architecture.rs (no_crate_but_the_server_builds_an_access_record)S3, P1
L-02Failing closed blocks care: a full spool refuses every access to patient data (a risk the L-01 control creates)a clinician gets no answer, care is delayedS2, P2the spool is bounded on disk, so a repository outage alone blocks nothing; alerts fire on the backlog and on refusals; the instructions name the alertapp/ferrofed-server/tests/it/audit_repository.rs (a_full_spool_fails_the_query_closed_and_asks_no_member); app/ferrofed-server/tests/it/feed_audit/pixm.rs (a_repository_that_never_answers_holds_no_query_and_the_records_are_spooled); deploy/observability/ferrofed-alerts.yaml (FerroFEDAuditSpoolBacklog, FerroFEDAuditRefused)S2, P1
L-03The record names the wrong person or provideran access is attributed to someone who did not make it, and the one who did is not foundS3, P2the accessor comes from the token the gateway verified, never from the request; a request refused at authentication, for its person or assurance, or by a limit, writes no record; a console query names the operatorapp/ferrofed-server/tests/it/access/query.rs (a_patient_query_names_the_caller_the_patient_the_origins_and_every_category, a_console_query_names_the_operator); app/ferrofed-server/tests/it/access/professional.rs; app/ferrofed-server/tests/it/access/limits.rs; crates/ehds-logging/tests/it/balp/mod.rs (the_person_the_provider_and_the_client_are_named)S3, P1
L-04The record omits the professional’s identification and assurance level, or the client’s address behind a proxya reviewer cannot tell which professional acted, or from whereS2, P3planned: #742, #722open, S2, P3
L-05An access to priority-category data is recorded as of no category, so it is kept for less time and the person’s view of it is wrong; or the map sends every access to “unclassified” (a risk the control creates)the access is lost to review before its timeS3, P2none only when every object is an exact none key; everything else ehds-unclassified with its ids as evidence, never refused; a map with an unknown code is refused at load; the map’s digest is in every record; the deployment authors the mapcrates/ehds-logging/tests/it/classify.rs (an_unmapped_object_is_unclassified_with_its_ids_and_never_dropped, none_never_erases_a_category_in_a_mixed_result, an_id_differing_by_case_space_or_specialisation_is_unmapped_never_none); crates/ehds-logging/tests/it/property.rs (a_result_is_of_no_category_only_when_every_object_is_an_exact_none, evidence_that_shows_nothing_is_unclassified); crates/ehds-logging/tests/it/map.rs (a_code_that_names_no_category_is_refused)S3, P1 for “no category”; unclassified records are kept, retention by category is L-07
L-06The record names an origin that sent nothing, an ehr_id at a member the query never reached, or the categories of one member’s rows under anotherthe record misstates which CDRs released which dataS2, P3an endpoint is an origin only when the query was sent to it, through the endpoint it was sent through; a query sent to no member writes no record; each origin of a merged answer carries the categories of its own rows; a member past the answer bound is node-error with no rowapp/ferrofed-server/tests/it/access/origins.rs (a_query_every_member_of_which_was_capped_writes_no_record, a_capped_member_is_no_origin_of_the_answer, each_origin_of_a_merged_answer_carries_the_categories_of_its_own_rows); app/ferrofed-server/tests/it/access/query.rs (a_query_no_node_was_sent_is_not_an_access, a_member_answer_past_the_read_bound_is_recorded_as_node_error_with_no_row)S2, P1
L-07The records cannot be reviewed, or are not kept by origin and category (Annex II, points 3.3 and 3.4)misuse is not found, or records go before their timeS3, P2the records go to the deployment’s Audit Record Repository, external software point 3.3 admits; the gateway’s own review, retention and export are planned (#660, #521)[audit] destination = "repository", refused unset or off outside development: app/ferrofed-server/tests/it/feed_audit/config.rs (a_binding_outside_development_needs_a_declared_destination, off_is_refused_outside_development_and_admitted_inside)open, S3, P2
L-08The record discloses the patient or the caller where it must not: to a node, the operator log, a span or a metrica patient identifier leaks (§5.4, N33)S3, P2no record content reaches a node or a log; Debug shows no identifierapp/ferrofed-server/tests/it/access/query.rs (no_patient_template_or_caller_reaches_the_log_a_metric_or_a_node); crates/ehds-logging/tests/it/balp/mod.rs (no_debug_shows_the_patient_the_person_or_an_id); crates/ehds-logging/tests/it/classify.rs (no_debug_shows_an_id)S3, P1
L-09Emergency access to restricted data is not markedthe person cannot see that a restriction was overridden (Art 8)S3, P2a record whose verified token declares a purpose of use the deployment names in [[access_log.emergency_purpose]] carries the ehds-emergency-access entity, stated in words, with the purposes that marked it; the mark is read from the token alone, never inferred, and changes no dispatch and no answer, so the node still decides (N26); config check notes a deployment that names no emergency purpose, and the instructions for use ask for one; whether restricted data were released is the node’s to recordapp/ferrofed-server/tests/it/access/emergency.rs (a_declared_emergency_purpose_marks_the_record, no_access_is_marked_without_a_declared_purpose, a_token_without_the_purpose_is_not_marked, a_nodes_refusal_of_an_emergency_access_stands, config_check_notes_an_access_log_without_an_emergency_purpose); crates/ehds-logging/tests/it/emergency.rs (only_an_exact_match_marks_the_access); crates/ehds-logging/tests/it/balp/emergency.rs (an_emergency_access_is_marked_in_its_own_entity); app/ferrofed-server/tests/it/access/emergency_consent.rs (an_emergency_request_asks_the_denied_member_and_records_the_set_aside, by_default_the_pre_filter_applies_to_an_emergency_request)S3, P1

The interoperability component

The gateway serves this component on its FHIR face: the patient summary and the receipt of a document. Each situation below is open until its control is built, and the component is not offered for its Annex II purpose while any of S3 or S4 is open.

IdHazardous situationHarmBeforeControlImplemented byAfter
I-01A silent node: a member that holds the patient’s data does not answer, and the summary reads as the whole recorda missed allergy or medication leads to a wrong treatmentS4, P3all-or-nothing by default (N37), a partial document only on request and with every silent member named; a section says “no information” (emptyReason nilknown) only when every member in scope answered empty, unavailable otherwisebuilt on the query path: app/ferrofed-server/tests/it/completeness.rs (all_stated_explicitly_is_accepted_and_fails_closed, incompleteness_is_the_complete_flag_and_never_an_operation_outcome), app/ferrofed-server/tests/it/endpoint_report.rs (an_undirected_query_asks_every_member_and_excludes_none); the section queries run on that path, every member asked and named: app/ferrofed-server/tests/it/stored/reserved.rs (each_section_query_runs_by_name_and_no_patient_identifier_reaches_a_node); the document: app/ferrofed-server/tests/it/fhir/summary.rs (a_silent_member_fails_the_summary_and_is_named, under_partial_a_silent_member_is_named_in_every_section), app/ferrofed-eehrxf/tests/it/summary.rs (a_silent_member_is_named_and_its_sections_are_unavailable)open, S4, P3
I-02Duplicate entries across nodes: two members hold the same medication or problem, and the summary lists it twice, or merges two different entries as onea dose counted twice, or a distinct entry lostS4, P3entries are never merged across members; each is listed with its provenance, one Provenance per source composition and each section’s contributing member as its author; version-identity de-duplication on the query path removes only copies of one version; the instructions tell clinicians to expect duplicatescrates/eehrxf/tests/it/mapping.rs (a_composition_maps_to_its_resource_with_one_provenance); app/ferrofed-server/tests/it/dedup.rs (without_the_header_both_copies_come_back_and_none_is_recorded, under_version_identity_one_row_comes_back_and_the_copy_is_named); Reading an answer safely; listed apart, each member a section author with its own Provenance: app/ferrofed-server/tests/it/fhir/summary.rs (the_summary_is_an_eps_document_from_both_members_and_no_identifier_reaches_a_node), crates/eehrxf/tests/it/document.rs (two_runs_over_one_composition_never_share_a_full_url)open, S4, P2
I-03An unmapped code or element: content the mapping does not cover is dropped, so an entry reaches the document without its code or not at allan allergy or a result is missing from the summaryS4, P3a composition of another template, a flat composition and a context the mapping files do not declare are refused; unmapped content is reported, never dropped; every producer element of the dataset is covered by the section catalogue; every emitted document is validated against the vendored profilescrates/eehrxf/tests/it/mapping.rs (a_composition_of_another_template_is_refused, a_flat_composition_is_refused, a_context_the_files_do_not_declare_is_refused_with_diagnostics); crates/eehrxf/tests/it/category.rs (the_patient_summary_producer_populates_its_five_required_sections); the section catalogue: crates/eehrxf/tests/it/crosswalk.rs (the_patient_summary_crosswalk_holds_against_the_pinned_packages, a_producer_shall_element_without_a_row_fails, an_uncovered_required_section_slice_fails), with the medical alert (A.2.1.2), a producer element, and the functional status (A.2.3.4) open because no openEHR content is named to feed them (the patient summary crosswalk); the openEHR content each section is selected by, held to the vendored template: app/ferrofed-eehrxf/tests/it/template.rs (each_section_selects_exactly_the_entry_archetypes_its_template_sections_name), app/ferrofed-eehrxf/tests/it/crosswalk.rs (every_crosswalk_section_has_a_query_or_a_reason_and_never_both) (the section queries); what no mapping covers is counted in the section, never dropped: app/ferrofed-eehrxf/tests/it/summary.rs (a_composition_no_mapping_covers_is_reported_never_dropped); every document held to the vendored EPS profiles in the tests: app/ferrofed-server/tests/it/fhir/summary.rs (the_summary_is_an_eps_document_from_both_members_and_no_identifier_reaches_a_node); planned: #687, #688open, S4, P3
I-04A code translated to one that is not equivalent: a broader or narrower code presented as the samea clinician reads a more or less specific diagnosis than was recordedS3, P2the original code is kept; only an RM TERM_MAPPING with match '=', or a terminology server answer of equivalent or equal, adds a coding; without a terminology server the component fails closed where one is requiredplanned: #687open, S3, P2
I-05A demographic mismatch: the summary carries another patient’s data, or a header naming another patienta decision for one patient made on another’s recordS4, P2the patient is resolved by identifier through the identity binding and never matched by demographics in the gateway; an ambiguous match is never chosen; an ehr_id two members claim is refused and raised as an incident; a PMIR merge drops the bindings it makes stale; the header comes from the identity bindingapp/ferrofed-server/tests/it/pdqm/flow.rs (several_matched_patients_refuse_the_resolution_and_fail_the_query); app/ferrofed-identity/tests/it/session.rs (two_members_with_one_ehr_id_are_ambiguous_and_never_chosen_between); app/ferrofed-server/tests/it/ehr_id_collision.rs (a_probe_collision_is_a_409_naming_both_with_one_incident_and_neither_is_read); app/ferrofed-server/tests/it/pmir/feed.rs (an_authenticated_merge_drops_the_bindings_of_the_merged_ehr_ids); header planned: #663open, S4, P2; a wrong link at the identity service stays the deployment’s (threat model, risk 7)
I-06A restriction shows through the document: a section marked withheld, or a member’s absence that only a restriction explainsthe patient’s restriction is visible to the provider (Art 8)S3, P2emptyReason is never withheld while disclose = false; a node’s refusal and a pre-filter exclusion read as a member without the patient; a national contact point’s requests are always served with disclose = falsebuilt on the query path: app/ferrofed-server/tests/it/consent_withheld/mod.rs (a_withheld_exclusion_reads_exactly_as_a_member_that_does_not_know_the_patient), app/ferrofed-server/tests/it/consent_withheld/node.rs (a_node_refusal_reads_exactly_as_a_member_that_does_not_know_the_patient); the document has no withheld empty reason to write (crates/eehrxf/src/document.rs, EmptyReason); planned for the contact point: #734open, S3, P2
I-07A section query carries the patient identifier to a nodea patient identifier leaks (§5.4, N33)S3, P2each section is a stored query run through the rewrite and the outbound gate, so a node is asked by its ehr_id alonebuilt on the query path: app/ferrofed-server/tests/it/outbound.rs (either_carrier_and_a_projection_reach_a_node_as_its_ehr_id_alone), app/ferrofed-server/tests/it/hygiene.rs; the section queries (#776), each held with the patient a parameter and run by name, reach every member with no identifier in the query, path or headers: app/ferrofed-server/tests/it/stored/reserved.rs (each_section_query_runs_by_name_and_no_patient_identifier_reaches_a_node), app/ferrofed-eehrxf/tests/it/query.rs (the_patient_and_its_namespace_are_parameters_and_nothing_else_is_compared)S3, P1
I-08The mapping gives different output for the same input, or reads a dataset model other than the pinned onetwo requests for one patient disagree, or a profile element is mapped against the wrong definitionS3, P2the mapping is deterministic and the dataset model reads the same whatever the order of the package; the package is the pinned one and a malformed one is refusedcrates/eehrxf/tests/it/mapping.rs (the_same_composition_maps_to_the_same_bundle); crates/eehrxf/tests/it/property.rs (the_model_is_the_same_whatever_the_member_order); crates/eehrxf/tests/it/dataset.rs (the_package_is_the_pinned_one); crates/eehrxf/tests/it/refusals.rsS3, P1
I-09A generated summary is read as one a clinician wrote and attested, or as exhaustivea clinician trusts it as a complete, attested recordS3, P3the author is the gateway’s Device and the operator’s Organization, with no attester, and every section’s narrative says it is not exhaustiveapp/ferrofed-eehrxf/tests/it/summary.rs (a_document_from_two_members_meets_the_eps_profiles)open, S3, P3
I-10A received document is written to the wrong member or under the wrong patienta record is filed in another patient’s EHRS4, P2a received document goes to the one member declared for its category, and the answer names it with the new version; a member the registry does not hold refuses the start; the patient is resolved from every identifier of the document in a declared namespace at that member alone, and identifiers that do not all name one ehr_id there, or a patient the member holds no EHR for, are refused before anything is sent; a caller confined to one patient writes only into that patient’s EHRapp/ferrofed-server/tests/it/fhir/receive.rs (a_document_is_written_to_its_member_by_its_ehr_id_alone, identifiers_that_name_two_patients_are_refused, a_patient_the_member_holds_no_ehr_for_is_refused, a_caller_confined_to_one_patient_writes_only_into_its_ehr, a_member_the_registry_does_not_hold_refuses_the_start); a wrong link at the identity service stays the deployment’s (threat model, risk 7)S4, P1
I-11A received document is stored with content lost: the mapping carries only part of it, or a document that breaks its profiles is taken ina later reader misses an allergy or a medication the sender recordedS4, P3the document is decoded against FHIR R4 and held to the R4 document rules, then checked against its category’s profiles with every finding refused and every constraint the check cannot evaluate listed; the original document is kept inline in the composition’s FEEDER_AUDIT.original_content, and the losses a run declares travel beside the composition; invariants, bindings and the entries’ own profiles are planned (#808)crates/eehrxf/tests/it/receive/read.rs (a_property_r4_does_not_define_is_refused_with_its_path, a_document_whose_first_entry_is_no_composition_is_refused); crates/eehrxf/tests/it/receive/conform.rs (a_missing_required_section_is_found, a_closed_slicing_finds_every_section_no_slice_admits, a_pattern_form_the_model_does_not_read_is_listed_as_not_evaluated); crates/eehrxf/tests/it/receive/openehr.rs (a_document_maps_to_one_composition_that_keeps_the_original); writing it to a member is planned (#802)open, S4, P3

The section queries

Each patient summary section is fed by a stored query the gateway holds read-only, eu.ferrofed.eehrxf::patient-summary-{section} at version 1.0.0, which selects every whole composition that contains one of the section’s archetypes, with its template id, from every member (the gateway’s own queries). The archetypes are those the openEHR International Patient Summary template of the openEHR international CKM (cid 1013.26.376, asset version 1, DRAFT) names in the template section that carries the patient summary section. The selection waits on this file’s clinical review.

Section (Xt-EHR)eHNTemplate sectionArchetypes
allergiesAndIntolerancesA.2.1.1Allergies & IntolerancesEVALUATION.adverse_reaction_risk.v1, EVALUATION.exclusion_global.v1, EVALUATION.absence.v2
problemsA.2.3.1Problem List, Past History of IllnessesEVALUATION.problem_diagnosis.v1, EVALUATION.exclusion_global.v1, EVALUATION.absence.v2
medicationSummaryA.2.4Medication SummaryACTION.medication.v1, EVALUATION.exclusion_global.v1, EVALUATION.absence.v2
medicalDevicesAndImplantsA.2.3.2Medical DevicesEVALUATION.device_summary.v0
proceduresA.2.3.3History of ProceduresACTION.procedure.v1, EVALUATION.absence.v2, EVALUATION.exclusion_global.v1
immunisationsA.2.2.1ImmunizationsACTION.medication.v1, EVALUATION.absence.v2
socialHistoryA.2.5Social HistoryEVALUATION.tobacco_smoking_summary.v1, EVALUATION.alcohol_consumption_summary.v1
pregnancyHistoryA.2.6PregnancyEVALUATION.pregnancy_summary.v0, EVALUATION.estimated_date_delivery.v0, OBSERVATION.exclusion_pregnancy.v0
advanceDirectivesA.2.7.2Advanced DirectivesEVALUATION.advance_care_directive.v1, EVALUATION.limitation_of_treatment.v0
observationResultsA.2.8Diagnostic Results, Vital SignsOBSERVATION.laboratory_test_result.v1, OBSERVATION.imaging_exam_result.v0, OBSERVATION.body_weight.v2, OBSERVATION.height.v2, OBSERVATION.respiration.v2, OBSERVATION.pulse.v2, OBSERVATION.body_temperature.v2, OBSERVATION.head_circumference.v1, OBSERVATION.pulse_oximetry.v1, OBSERVATION.body_mass_index.v2, OBSERVATION.blood_pressure.v2
carePlansA.2.9Plan of CareACTION.care_plan.v0, INSTRUCTION.service_request.v1

Each archetype id is openEHR-EHR- followed by the name in the table. The Xt-EHR observation results are “measurements, laboratory results, anatomic pathology results, radiology results or other imaging or clinical results”, so they take the template’s vital signs as well as its diagnostic results. Four crosswalk sections have no query:

  • The medical alert (A.2.1.2), a gap. The template has no alert section, and no openEHR content is named to feed it.
  • The functional status (A.2.3.4), a gap. The template’s Functional Status section names only EVALUATION.problem_diagnosis.v1 and EVALUATION.clinical_synopsis.v1, which do not tell a functional status from any other problem or impression, so a query on them would put every problem in the section.
  • The travel history (A.2.7.1). The template has no travel section.
  • The patient story. The section carries a note alone and no entry.

The selection is a superset for three reasons the review weighs. The exclusion and absence statements are offered in several sections, so a composition with “no known allergies” is selected for every section that offers them, and the mapping places each statement by its content. The template records both a medication statement and an immunisation statement in ACTION.medication.v1, so the medication and immunisation queries select the same compositions. The problem list and the past history share EVALUATION.problem_diagnosis.v1.

Shared hazards

IdHazardous situationHarmBeforeControlImplemented byAfter
X-01One component changes the other’s output or behaviour (Art 30(1)(b))an access goes unrecorded, or a document changes, because of the other componentS3, P2two crates with no edge between them; only the composition root links both; the engine compiles neitherapp/ferrofed-engine/tests/it/architecture.rs (the_two_harmonised_components_are_independent_of_each_other, no_crate_but_the_composition_root_links_both_components, the_engine_compiles_neither_component_and_no_fhir); the server tests that each output is unchanged by the other are planned with #689S3, P1 at the crate level

The completeness default, re-examined

The interoperability component’s document is all-or-nothing by default, with a partial document on request and every silent member named, as §11 sets for a federated query. That default was to be re-examined here.

It holds. I-01 is the most severe hazard a federated summary adds, and the default makes the summary fail visibly when a member that may hold the patient’s data is silent. A partial document is no less safe than a partial query answer as long as every silent member is named in the document and no section claims “no information” for a member that did not answer, which are I-01’s controls. The cost is L-02’s kind: an answer withheld while one member is down. The claims review assessed that cost against Annex II, point 2.5, and found the partial answer one header away.

Overall residual risk

  • Logging component: L-01, L-02, L-03, L-05, L-06, L-08 and L-09 are controlled and tested; L-09 depends on the deployment naming its emergency purposes. L-04 is open at S2. L-07 is open at S3 and is carried by the deployment’s Audit Record Repository until #660 lands. The component records every access the gateway serves today.
  • Interoperability component: I-07 and I-08 are controlled. Every other hazard is open, most at S4, so the component is not offered for its Annex II purpose and the gateway does not serve it. The overall residual risk of the component is evaluated again when the issues above close.

The instructions for use name each open hazard a professional user needs to know (Art 28(b)).

Review and change

  • At each release. The release cut reviews this file when the release changes either component, its mapping pins or the query path it rides (docs/release.md, Before the tag), and records the review below. A change to the section catalogue or the mapping pin is not merged without a review of I-01 to I-05.
  • From the field. Every complaint and every possible serious incident is checked against this file, and a new hazard or a control that failed enters it (Complaints and incidents).
  • When an implementing act is adopted. The exchange format (Art 15(1)) and the common specifications (Art 36(1)) can change what a component must do; their adoption reopens the hazards they touch.
Reviewed onReleaseChangeHazards touched
2026-10-06before 0.0.10file openedall
2026-10-06before 0.0.10the patient summary section catalogue: the crosswalk of eehrxf 0.0.4 (#777), with the medical alert and the functional status openI-03; I-01, I-02, I-04 and I-05 unchanged, because no document is built yet
2026-10-06before 0.0.10the section queries (#776): one read-only stored query per section, selecting by the archetypes the openEHR International Patient Summary template names (pending the clinical review), with the medical alert, the functional status, the travel history and the patient story unselectedI-07 controlled; I-03 (the selection and its gaps); I-01, I-02, I-04 and I-05 unchanged, because no document is built yet