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

Data protection

This page is for the people who write a deployment’s data protection impact assessment (DPIA) and its records of processing. It lists the personal data a FerroFED gateway processes, where each item is held, how long it is kept and what protects it. It then states the roles of a deployment, what the gateway offers an entity under the NIS2 Directive, and what the documents claim about the medical device regulation.

The legal texts are cited from the Official Journal:

This page is not legal advice. It describes what the software does, so that a deployment’s counsel and data protection officer can decide what that means for the deployment. The last section lists what they must confirm.

What the gateway holds

FerroFED holds no clinical data of its own. It passes each member CDR’s answer to the client, merges the answers, and forwards a write to the CDR that owns the record. Clinical content is in the gateway’s memory for the length of one request and is never written to disk or to a log.

What it does keep is routing state, audit records and operational telemetry. Several of these hold personal data: an ehr_id is a pseudonymous key to one patient’s record at one node, the caller’s identity names a health professional, the IHE audit records name the patient, and the access records name both. Every row of the inventory below names what it carries.

Processing inventory

Store or channelPersonal data it carriesWhereHow longProtectionSettings
The client’s requestthe patient identifier in the AQL or a parameter; the caller’s access token; for a write, the clinical contentprocess memoryone request, at most server.request_timeout_ms (30 s)the identifier is held as a PatientRef whose Debug and Display are redacted, never serialised, logged, traced or measured; the token is verified before anything else is read (Client authentication)server.request_timeout_ms, server.body_limit_bytes
Requests to the identity servicesthe patient identifier, sent to the PIX Manager (ITI-83), the PDQm Supplier (ITI-78 or ITI-119), each XCPD responding gateway (ITI-55) and the NVI (a pseudonymised BSN); to Mitz, the patient identifier with the professional’s UZI number and role and the organisation’s URA and typein transit to each service you configureone exchangehttps required outside the development profile (What must travel encrypted); optional mutual TLS[pixm], [pdqm], [xcpd], [nl_gf.nvi], [nl_gf.mitz]
Requests to the member nodesthe node’s own ehr_id; the caller’s sub, the issuer that vouched for it, the caller’s organisation, purpose of use and scopes, and the professional’s name, identifier, the agency that issued it and roles where the caller’s token states them, in the signed openEHR-federation-client token; for a write, the clinical content byte for bytein transit to each member askedone requestno patient identifier in any part the gateway composes (§5.4.1, N33), checked by the outbound gate (Where the patient identifier stops); the caller’s own token is never forwarded[credentials."<id>"], [signing]
The answersclinical rows and documents from each memberprocess memory, then the clientone requesteach node decides what it releases (§13.2, N26, N27); a node error quoted in meta.federation has each consumed value maskednone
Resolution bindingsthe caller (issuer, subject, client) with the {node, ehr_id} pairs its resolutions foundprocess memory, per replicafederation.binding_ttl_ms after the last resolution that returned the pair (15 minutes by default); lost on restartkeyed by ehr_id, never by a patient identifier; seen by no other caller; bounded by binding_capacity (100 000)Resolution bindings
The ehr_id indexwhich member holds which ehr_idprocess memory, per replicaleast recently used past ehr_index_capacity (100 000); lost on restartno caller and no patient identifierThe ehr_id index
Integrity incidentsan ehr_id, only when it is a bare UUID, and the endpoints that claim itprocess memory (the last 25 of each kind) and one log lineuntil restart; the log line as long as your log pipeline keeps itno patient identifier; read on the operator surface with the operator scope (Integrity incidents)none
Per-caller rate bucketsthe caller’s issuer and client_idprocess memory, per replicauntil the bucket refills; at most 10 000 callersnone read outside the process[server.caller_rate]
IHE audit spoolsthe patient identifier inside each ITI-83, ITI-78, ITI-119 and ITI-55 record; the identities a PMIR message names; the caller’s iss, sub, client_id and purposes of use on a record made for a callera directory on disk, one per replicauntil the Audit Record Repository accepts the record; a quarantined record until you remove itdirectory 0700, files 0600, refused at start when open to other users; bounded by spool_max_bytes (64 MiB) and spool_max_events (100 000); encryption at rest is the volume’s (The audit trail)[audit.repository], [xcpd.audit_repository]
The ATNA Audit Record Repositorythe same recordsyour repositoryyour repository’s retentionITI-20 over TLS: the FHIR Feed over https, syslog over TLSthe repository’s own
The access recordsfor each federated query, stored-query execution, routed read and routed write that reached a node: the caller’s iss, sub, client_id, organisation, professional identification and purposes of use; the professional’s name and identifier (the IHE IUA subject_name and national_provider_identifier), the assurance level of the authentication when the issuer’s mapping established one, and whether a person or a client acted (The person behind an access); the patient identifier and namespace the request named, and each ehr_id reached with its endpoint; the request as the client sent it, which may name the patient; the request id and the address the request came from; each endpoint asked with its node, system_id, outcome and row count; the categories of the datathe [audit] spool, then the Audit Record Repositoryas the IHE audit records abovestored before the answer leaves, and an access whose record cannot be stored is answered 503 access-unrecorded with none of the data; the spool and transport protections above; no part reaches a node, the log, a span or a metric label (The access log)[audit], [audit.repository], [access_log]
The log audit destinationthe profile, the action, the outcome, the server of a request the gateway sent, counts of entities, and on_behalf as caller or gatewaythe logyour log pipeline’s retentionno patient identifier, no request content, no sub, client_id or issuer of the caller, and no client of a request the gateway received; refused outside development for a gateway with a registry, because it cannot hold the access records[audit] destination = "log", [xcpd] audit = "log"
The request log and every other log linethe method, route template, status, latency and request id; a security event’s reason; in the edge mode, keyed HMAC references to the subject and client that change at every start; on an admin listener write action, the operator’s issuer and subjectstdout, then your log pipelineyour log pipeline’s retentionno request body, AQL text, header value, request path or patient identifier (What the log records)[telemetry] filter, format
Metricsnone: every label value comes from a closed set or the registrythe admin listener, the OTLP pushyour metrics store’s retentionMetrics[metrics]
Trace spansnone: route templates, registry ids, operations, statuses and counts; the trace id is the gateway’s own, never the client’syour OpenTelemetry collectoryour collector’s retentionTracing[telemetry] otlp_endpoint, trace_sample_ratio
Stored-query definitionsnone: parameterised AQL, and a definition that names a patient by a literal is refusedredb, PostgreSQL or read-only filesdurable; a stored version is immutable (§12.7, N44)the bound values of an invocation are never written (Stored queries)[stored_queries]
The PMIR identity feedthe Patient Master Identities each ITI-93 message names, with their identifiers and demographicsprocess memory for one message, then the audit spoolone message; the audit record as abovehttps outside development; a feed token from a file; only the kind and count of each change is logged (The identity feed)[pmir]
The operator console’s sessionsthe operator’s ID Token claims and access tokenthe console’s process memoryidle_timeout_s (1 800) without a request, absolute_timeout_s (43 200) at most, and no longer than the access token; lost on restartheld on the server, known to the browser by an opaque HttpOnly cookie; every page no-store; a query answer is rendered and not kept (The operator console)[session], [oidc]

Two kinds of state hold no personal data: the registry document (organisations, endpoints, system_id mappings) and the creating_system_id routes the gateway learns. The signing key and the onward credentials are secrets: the gateway shows each as *** wherever it renders the configuration, and the hardening guide has them read from files.

The gateway sends nothing to its manufacturer. Every outbound connection goes to a URL your configuration names.

The record of each access

The gateway records every access to patient data it intermediates: each federated query and stored-query execution that a member was sent, and each routed read and write a node acted on, the operator console’s queries included. Each record names the verified caller, the patient and every ehr_id reached, each endpoint asked and the categories of the data. The gateway stores it in the [audit] spool before the answer leaves, and answers an access whose record cannot be stored with 503 access-unrecorded and none of the data (The access log). The record follows Annex II, point 3.2, of the EHDS Regulation, and the library that builds it is crates/ehds-logging.

What the record does not cover:

  • A definition request, such as a template or a stored-query definition, reaches no patient data and is not recorded.
  • Under the development profile, an unset [audit] destination records nothing, and log writes counts that name no one. Outside development, a gateway with a registry refuses every destination but repository.
  • A build without the IHE binding records no access, and refuses a registry outside development.
  • FerroFED offers no interface of its own to review the records (Annex II, point 3.3), and keeps them for no period by origin and category (point 3.4). Both are planned (#521); until then your Audit Record Repository decides who reads the records and how long it keeps them.

Each member node still audits who asked: every request carries the verified caller in the openEHR-federation-client token and the gateway’s request id (§13.1, N24; Verifying it at the node).

Retention

The gateway decides the retention of what it holds in memory. Everything it hands to another system is kept as long as that system keeps it.

DataDefaultSettingWhat decides the rest
A resolution binding15 minutes after the last resolution that returned itfederation.binding_ttl_ms, binding_capacitya restart forgets it
An ehr_id index entryuntil 100 000 newer entries push it outfederation.ehr_index_capacitya restart forgets it
An operator console session30 minutes idle, 12 hours at mostsession.idle_timeout_s, absolute_timeout_sthe access token’s own lifetime
An IHE audit record or an access record in the spooluntil the repository accepts itspool_max_bytes, spool_max_eventsa quarantined record waits for you to remove it
An audit record at the repositorynone from the gatewaynonethe repository’s retention policy
Log lines, metrics, spansnone from the gatewaynoneyour log, metrics and trace stores
Stored-query definitionskeptnonethey hold no personal data

GDPR Art 5(1)(e) asks that personal data be “kept in a form which permits identification of data subjects for no longer than is necessary”. Set the retention of the audit repository and of the log pipeline in your records of processing. The EHDS Regulation asks that information on each access to a person’s data through the health professional access service “be available for at least three years from each date of access” (Art 9(2)). That duty belongs to the access service. The gateway’s access records are kept as long as your Audit Record Repository keeps them, so its retention policy decides whether they meet that period; retention by origin and category is planned (#521).

Roles

The EHDS Regulation takes the definitions of “controller” and “processor” from GDPR Art 4(7) and (8) (EHDS Art 2(1)(a)). A controller “determines the purposes and means of the processing of personal data”; a processor “processes personal data on behalf of the controller”. Two or more controllers that “jointly determine the purposes and means of processing” are joint controllers (GDPR Art 26(1)).

FerroFED is software. Its manufacturer receives no personal data from a deployment, so it is neither the controller nor a processor of a deployment’s processing. Its obligations as the manufacturer of an EHR system are those of the EHDS Regulation (Regulatory status, decided on #519). The operator of a deployment is the party the GDPR roles attach to.

A hospital that runs its own gateway

A hospital that runs FerroFED over its own CDRs, or over the CDRs of a group it belongs to, decides why patient data is federated and by what means. It is the controller of the gateway’s processing. Its hosting provider, if the gateway runs at one, is a processor under a GDPR Art 28 contract. Each member CDR’s operator remains the controller of its own CDR and of what it releases.

A regional operator that runs a gateway for several hospitals

A regional operator that runs one gateway for several healthcare providers can stand in either of two roles, and the facts of the arrangement decide which:

  • A processor for each hospital. The hospitals decide the purposes, and the operator runs the gateway on their documented instructions. Each hospital then needs an Art 28(3) contract with the operator, and the operator keeps a record of processing per controller under Art 30(2).
  • A joint controller with the hospitals. Where the operator and the hospitals together set the rules of the federation (who may ask, for which purposes, which members take part), they jointly determine the purposes and means, and Art 26 asks for an arrangement that sets out their responsibilities.

FerroFED’s own design points to facts counsel will weigh: the operator chooses the issuers it trusts, the members it admits, the identity services it asks and the audit repository it writes to; each member node still makes its own release and consent decision (§13.2, N26, N27).

The other parties

PartyWhat it does with personal data in a federation
Each member CDR’s operatorholds the clinical record and decides what it releases to the gateway
The PIX Manager, PDQm Supplier, XCPD gateways, NVI and Mitzreceive the patient identifier, and Mitz the professional’s identity, to answer the gateway
The caller’s issuerissues the token that names the professional
The Audit Record Repositorystores the IHE audit records and the access records, which name the patient and the professional
The log, metrics and trace storesreceive the operational telemetry above

Each is a recipient in the sense of GDPR Art 30(1)(d) and has a role of its own to settle.

DPIA inputs

GDPR Art 35(3)(b) requires an impact assessment for “processing on a large scale of special categories of data referred to in Article 9(1)”, and data concerning health is one. A gateway that federates a region’s patient records will usually meet that test. These are the facts about the gateway an assessment needs; the deployment adds its own:

  • Nature. Intermediation: the gateway resolves the patient through an identity service, sends each member a query scoped to that member’s ehr_id, merges the answers and routes follow-up reads and writes. It stores no clinical data.
  • Scope. Every category of clinical data the member CDRs hold, because the gateway selects nothing by category (Regulatory status). The patients are those the members hold; the professionals are the callers of the trusted issuers.
  • Purposes. Patient care by healthcare providers. Each token declares a purpose of use, and a token without one is refused by default (Purpose of use).
  • Measures. The threat model names the risks the gateway mitigates, the setting or test behind each mitigation, and the risks the deployment carries. The hardening guide turns them into a checklist.
  • The risks to bring into the assessment. The patient identifier leaving for the identity services; the caller’s identity reaching every member asked; the audit spool on disk, which holds the access records until the repository accepts them; the access records at the repository, which name the patient and the professional for every access; and a wrong link at the identity service routing a request to another patient’s EHR.

A template for the record of processing

GDPR Art 30(1) lists what a controller’s record holds. This table fills in what FerroFED determines and leaves the rest to you. A processor’s record under Art 30(2) holds rows (a), (e) and (g), and “the categories of processing carried out on behalf of each controller” in place of (b) to (d).

Art 30(1)What to write
(a) the controller, joint controller, representative and data protection officeryours
(b) the purposes of the processingpatient care by healthcare providers: answering a professional’s query from the federation’s CDRs and routing the follow-up reads and writes; add the purposes your issuers’ tokens declare
(c) the categories of data subjects and of personal datapatients of the member CDRs: patient identifiers, ehr_ids, and health data in transit; health professionals: the token’s subject, issuer, client, organisation, scopes and purposes of use; operators: their console sign-in
(d) the categories of recipientsthe member CDRs; the identity services; the Audit Record Repository; your log, metrics and trace stores (The other parties)
(e) transfers to a third countrynone by the gateway; each URL in your configuration decides where data goes
(f) the time limits for erasureRetention, with your repository’s and log pipeline’s periods
(g) the technical and organisational measuresthe threat model and the hardening guide, with your own controls

NIS2

NIS2 Annex I, sector 5 “Health”, lists “Healthcare providers as defined in Article 3, point (g), of Directive 2011/24/EU”. The Directive applies to such a provider that is at least a medium-sized enterprise (Art 2(1)), with the exceptions of Art 2(2). One that exceeds the ceilings for medium-sized enterprises is an essential entity (Art 3(1)(a)), and one that does not is an important entity (Art 3(2)). A regional operator that runs systems for hospitals may fall under sector 9, “ICT service management (business-to-business)”, whose “managed service provider” provides “services related to the installation, management, operation or maintenance of ICT products … either on customers’ premises or remotely” (Art 6(39)). Whether either applies is for the entity to establish.

NIS2 puts the duties on the entity, never on its software. What FerroFED offers an entity for them:

NIS2What the gateway offers
Art 21(2)(b) incident handlingthe security events under ferrofed::security, each counted in ferrofed_security_events_total by event and reason; integrity incidents under ferrofed::integrity; the shipped alert rules, among them FerroFEDCallerRefusals, FerroFEDOutboundGateStopped, FerroFEDAuthenticationUnavailable and FerroFEDIntegrityIncident (Metrics); one request id shared by the client, the log and every node
Art 21(2)(c) business continuityhealth and readiness probes, a bounded drain, several replicas behind one address (Health probes, Running several replicas); the stored-query store is the one durable store to back up
Art 21(2)(d) supply chain securitysigned release provenance, a CycloneDX and an SPDX SBOM per binary, image attestations (The container image)
Art 21(2)(e) vulnerability handling and disclosureprivate reporting through GitHub security advisories, with an acknowledgement within seven days (SECURITY.md)
Art 21(2)(h) cryptographythe transport rules that refuse a credential or a patient identifier over plain http outside development, and the trust anchors over https (What must travel encrypted); ES256 and ES384 signing keys with rotation
Art 21(2)(i) access controlevery caller authenticated by token, SMART on openEHR scopes per route, an operator scope for the operator surface and the admin listener’s write actions (Client authentication), and a scrape token or mutual TLS for the metrics off loopback (Metrics)
Art 21(2)(j) multi-factor authenticationnone in the gateway: the caller’s issuer and the console’s OpenID Provider authenticate the person

Art 23(4) sets the reporting clock: an early warning “within 24 hours of becoming aware of the significant incident”, an incident notification within 72 hours, and a final report “not later than one month” after that notification. The gateway reports nothing to a CSIRT or a competent authority. It supplies the evidence the entity reports from: the alerts, the security and integrity log lines, and the dependency states of GET {base}/operator/dependencies. A personal data breach has its own clock under GDPR Art 33: the controller notifies “where feasible, not later than 72 hours”, and a processor notifies the controller “without undue delay”.

The EHDS Regulation has the manufacturer of an EHR system report a serious incident “not later than three days” after becoming aware of it, “without prejudice to incident notification requirements under Directive (EU) 2022/2555” (Art 44(7)). That is the manufacturer’s duty, planned in #672.

The medical device question

The documents classify FerroFED under the EHDS Regulation alone. They do not claim that FerroFED is a medical device under Regulation (EU) 2017/745, no FerroFED release carries a CE marking under it, and none of the documents states an intended purpose in its terms.

MDR Art 2(1) defines a medical device as software, among other articles, “intended by the manufacturer to be used … for human beings for one or more of the following specific medical purposes”, such as “diagnosis, prevention, monitoring, prediction, prognosis, treatment or alleviation of disease”. Recital 19 adds that software “specifically intended by the manufacturer to be used for one or more of the medical purposes” qualifies, “while software for general purposes, even when used in a healthcare setting … is not a medical device”.

FerroFED’s intended purpose is to find a patient’s records across a federation of CDRs and return them with their origin, and to route follow-up reads and writes to the CDR that holds the record. The reasoning a deployment’s counsel should check is this:

  • What FerroFED does to the data. It resolves a patient, rewrites the query per node, and merges the answers: DISTINCT, ORDER BY, paging and aggregates across nodes, and deduplication by version identity when the client asks for it (§10). It computes no score, flags no finding and recommends nothing. A row’s values are the node’s own, beside the endpoint they came from, except a selected subject, which the gateway puts back (N5), and an aggregate, which it combines from the members’ answers.
  • What could still matter. The merge decides which rows a clinician sees and in which order, and an aggregate is computed over the members’ answers. A missing member is named in meta.federation, and by default a member that was asked and did not answer fails the whole query (§11.4). Counsel should weigh whether that selection is a medical purpose, against Art 2(1) and the qualification guidance the Medical Device Coordination Group publishes.
  • Where the EHDS Regulation points. Recital 42 says “certain software components of EHR systems could be considered medical devices” and should then be certified under the MDR as well. Art 27 binds manufacturers of medical devices that “claim interoperability” with the harmonised components; FerroFED makes no such claim. Art 1(5) leaves the MDR untouched for “the security of medical devices … that interact with EHR systems”.
  • What a deployment adds. A client application, a stored query an operator publishes, or a change to FerroFED’s code is outside the manufacturer’s intended purpose. Each can bring a medical purpose of its own, and is classified on its own.

If counsel finds that a deployment’s software is a medical device, the MDR classification rules decide its class; Annex VIII, Rule 11, covers “software intended to provide information which is used to take decisions with diagnosis or therapeutic purposes”.

What counsel must confirm

This page states facts about the software. It decides no deployment’s obligations. A deployment’s counsel and data protection officer should at least confirm:

  1. Who is the controller of the gateway’s processing, and whether a regional operator is a processor under GDPR Art 28 or a joint controller under Art 26.
  2. The lawful basis under GDPR Art 6 and the condition under Art 9(2) for each purpose of use your issuers’ tokens declare.
  3. Whether the deployment needs a DPIA under Art 35, and its outcome.
  4. The retention of the audit repository and the log pipeline, and the access rights to each.
  5. Whether the deployment’s operator is an essential or important entity under NIS2, and which national transposition applies.
  6. That neither FerroFED nor anything the deployment adds to it is a medical device under Regulation (EU) 2017/745, or, where something is, its classification and conformity route.
  7. The EHDS points listed on Regulatory status.