Back to Docs

Architecture

Last updated

The Health Dataspace v2 architecture in ArchiMate 3.2 views, with a sequence diagram wherever an order of messages matters: the five-layer graph model, the data flow, the deployment topology, the service dependencies, the permit and negotiation procedure, and the identity and trust framework. Click a diagram to open it full screen and zoom.

1. Five-Layer Knowledge Graph

The Neo4j knowledge graph organises health data across five architectural layers: DSP Marketplace (connector discovery), HealthDCAT-AP (dataset metadata), FHIR R4 (clinical data), OMOP CDM (research analytics), and Ontology (terminology alignment).

The five-layer knowledge graph as an ArchiMate information structure view: one band per layer, the node labels as data objects and the Neo4j relationship types as labelled associations
Fig 1. Five-layer knowledge graph, with the labels and relationships the seeds create. The FHIR nodes carry the same CODED_BY links as their OMOP counterparts; ICD-10 codes exist on Condition only.

2. Data Flow Pipeline

Synthetic patient data flows from Synthea generation through FHIR R4 resource loading into Neo4j, then transforms to OMOP CDM for research analytics. Each stage preserves full provenance through graph relationships.

The same data flow as a sequence diagram: Synthea generates the bundles, the loader writes the FHIR nodes, the Cypher transform maps them to OMOP and copies the codings, the dashboard queries the cohorts
Fig 2. End-to-end data flow from Synthea to analytics

3. Deployment Topology

The full JAD stack runs 27 Docker Compose services (profiles included) across six layers: infrastructure (Traefik, PostgreSQL, Vault, NATS, Keycloak), EDC-V / DCore (Control Plane, dual Data Planes), Identity (Identity Hub, Issuer Service), CFM (Tenant/Provision Managers, 4 background agents), Application (Neo4j, Proxy, UI), and a static GitHub Pages export. The same topology is deployed to Azure Container Apps at ehds.mabu.red (21 Container Apps and 9 Container Apps jobs on 2026-10-04, see ADR-012). Arrows show runtime dependencies.

The deployment topology as an ArchiMate technology view: the edge, the application, the EDC-V and identity services and the infrastructure as bands, with the run-time dependencies between them
Fig 3. Full deployment topology, 27 services with their dependencies

Operating hours on Azure

The Azure deployment runs Monday to Friday, 05:00 to 18:00 UTC, and is stopped outside those hours (ADR-053). Stopping is a real stop through the Container Apps API, not scale-to-zero, because nearly every service is called by another one and would never reach zero replicas. The UI is the exception: it sleeps at zero replicas, wakes for a visitor and serves an offline notice that links the static export.

StepEvening stop (18:00 UTC)Morning start (05:00 UTC, Mon to Fri)
1UI to offline mode, min 0PostgreSQL Flexible Server, wait until Ready
220 Container Apps stopped, consumers firstVault, Keycloak, Neo4j, NATS, proxy, enricher
3PostgreSQL Flexible Server stoppedEDC control plane, data planes, identity, CFM
4UI back online, then the Keycloak login check

Berlin public holidays skip the start. The catalog crawler runs in office hours only. A night or weekend session holds the stack with the repository variable LIVE_DEMO_HOLD_UNTIL; see the off-hours runbook.

4. Service Dependencies

Complete inventory of all services in the docker-compose.yml and docker-compose.jad.yml stacks, their exposed ports, upstream dependencies, and purpose.

ServiceLayerPort(s)Depends OnPurpose
TraefikInfrastructure:80 / :8090--API gateway, reverse proxy, *.localhost routing
PostgreSQL 17Infrastructure:5432--Shared database (11 DBs: cfm, controlplane, dataplane, dataplane_omop, identityhub, issuerservice, keycloak, redlinedb, rogueissuer, simplga, taskdb)
HashiCorp VaultInfrastructure:8200--Secrets store with file storage, so a restart keeps every key (since 2026-09-26; on Azure it stores in the Flexible Server, ADR-046)
NATS JetStreamInfrastructure:4222 / :8222--Async event mesh for DSP protocol events
KeycloakInfrastructure:8080 / :9000PostgreSQLOIDC SSO provider, realm edcv, 8 demo users across 5 roles
vault-bootstrapInfrastructure--Vault, KeycloakInit sidecar: seeds Vault secrets and Keycloak config
vault-unsealInfrastructure--VaultSidecar: initialises Vault once, then unseals it after every restart
sigletInfrastructure--VaultToken signing and certificate exchange for the EDC 0.18 data planes (#97)
Control PlaneEDC-V / DCore:11003PostgreSQL, Vault, NATS, KeycloakEDC-V runtime: DSP negotiation, management API, policy engine
Data Plane FHIREDC-V / DCore:11002PostgreSQL, Vault, Control PlaneDCore data plane for FHIR R4 resource transfer
Data Plane OMOPEDC-V / DCore:11012PostgreSQL, Vault, Control PlaneDCore data plane for OMOP CDM data transfer
Identity HubIdentity:11005PostgreSQL, Vault, KeycloakDCP: DID resolution, Verifiable Credential storage
Issuer ServiceIdentity:10013PostgreSQL, Vault, KeycloakVC issuance: EHDS membership, data permits, org credentials
Tenant ManagerCFM:11006PostgreSQL, KeycloakCFM: multi-tenant participant management
Provision ManagerCFM:11007PostgreSQL, Keycloak, Control PlaneCFM: automated resource provisioning
cfm-cp-shimCFM--Control Planenginx shim: the CFM agents call Management API v5alpha, EDC 0.18 serves v5beta (#181)
cfm-keycloak-agentCFM--KeycloakBackground: syncs Keycloak realm configuration
cfm-edcv-agentCFM--Control PlaneBackground: manages EDC-V connector lifecycle
cfm-registration-agentCFM--Identity HubBackground: handles participant DID registration
cfm-onboarding-agentCFM--Tenant ManagerBackground: automates tenant onboarding workflows
Neo4j 5Application:7474 / :7687--Knowledge graph: 5-layer model, APOC + n10s plugins
Neo4j SPE2Application:7475 / :7688--Secondary graph instance (federated profile)
Neo4j ProxyApplication:9090Neo4j, Control PlaneExpress bridge: FHIR/OMOP REST endpoints over Neo4j
Next.js UIApplication:3000 / :3003Neo4j ProxyPersona overviews, catalog, governance and exchange: 64 pages, 84 API routes
jad-seedSeed--All servicesOne-shot: phases 1-7 data seeding (Synthea, FHIR, OMOP, DSP)
GitHub PagesStatic--Next.js UI (static export)Public demo site with mock data fixtures

5. DSP Contract Negotiation

The Dataspace Protocol (DSP) governs how data holders and data users negotiate access to health datasets. The EHDS regulation adds HDAB approval as a pre-requisite for data permit issuance before contract negotiation can proceed.

DSP contract negotiation as a sequence diagram: the user queries the catalogue, applies to the access body and receives the permit as a credential, then negotiates the contract with the holder, who verifies the permit and evaluates the policy before agreeing and transferring the data
Fig 4. DSP contract negotiation with the EHDS data permit
Data permit and contract negotiation as an ArchiMate business process cooperation view: the access body assesses and issues the permit, the user queries, applies, negotiates and requests the transfer, the holder verifies, evaluates, agrees and transfers, over the application services
Fig 5. The same procedure as an ArchiMate business process view: three phases, the roles and the services

6. Identity & Trust Framework

The Decentralized Claims Protocol (DCP) manages identity, credentials, and trust. Identity Hub stores DIDs and Verifiable Credentials, the Issuer Service mints EHDS-specific credentials, and Keycloak provides SSO/OIDC authentication.

Identity and trust as an ArchiMate application cooperation view: the trust anchors, the DCP identity layer with Identity Hub, Issuer Service and the Secure Token Service, the five credentials the issuer defines, and the interfaces the tokens protect
Fig 6. DCP identity and trust architecture

7. SIMPL-Open & Compliance

This reference implementation aligns with the EU SIMPL-Open programme for federated data spaces. The architecture satisfies EHDS regulation, DSP 2025-1, DCP v1.0, and supply chain transparency requirements.

SIMPL-Open Alignment

  • DSP 2025-1: Sovereign data exchange via Control Plane
  • DCP v1.0: DID:web identity + Verifiable Credentials
  • Trust Framework: W3C Verifiable Credentials issued over DCP against the issuer's definitions
  • Federated Catalog: HealthDCAT-AP metadata (Release 8 vocabulary) profiles (ADR-003)
  • SBOM: CycloneDX 1.5 supply chain transparency

Regulatory Compliance

  • EHDS Art. 3-12: Patient rights (access, rectification, portability)
  • EHDS Art. 50-51: Secondary use, HDAB approval, data permits
  • GDPR Art. 15-22: Data subject rights enforcement
  • EU CRA Art. 13: SBOM mandate, vulnerability disclosure
  • BSI C5: Cloud security baseline (DEV, OPS controls)

8. Architecture Decision Records

All 73 ADRs are maintained as standalone Markdown files in docs/ADRs/ .

ADR-001
PostgreSQL vs Neo4j Data Storage Split

Accepted

ADR-002
EDC Data Plane Architecture

Accepted

ADR-003
W3C HealthDCAT-AP Alignment

Superseded

ADR-004
Next.js 14 as Unified Frontend

Accepted

ADR-005
JAD + CFM Source Builds

Accepted

ADR-006
GHCR Image Publishing

Accepted

ADR-007
DID:web Resolution and DSP Contract Negotiation

Accepted

ADR-008
Comprehensive Testing Strategy

Accepted

ADR-009
IssuerService DCP Credential Issuance Fix

Accepted

ADR-010
WCAG 2.2 AA Accessibility Compliance

Accepted

ADR-011
Security Penetration Testing Strategy

Accepted

ADR-012
Azure Container Apps Deployment

Accepted

ADR-013
SIMPL-Open EU Programme Alignment

Superseded

ADR-014
Weekly Demo Environment Reset

Accepted

ADR-015
Single-VM Dev Deployment for Personal VS Subscription

Superseded

ADR-016
ACA Off-Hours Scale-Down

Superseded

ADR-017
Persistent Storage for Stateful Services on ACA

Accepted

ADR-018
24×7 Operation on INF-STG-EU_EHDS + Postgres-on-ACA Workaround

Accepted

ADR-019
Neo4j GDS + APOC + Azure AI Foundry for GraphRAG Accuracy

Accepted

ADR-020
Cross-Participant Dataset Discovery via Federated Catalog + NLQ

Accepted

ADR-021
Docling for AWMF Leitlinien PDF Ingestion (Layer 6)

Accepted

ADR-022
EDC Connector — Function vs Cost

Superseded

ADR-023
Reinstate Off-Hours ACA Scale-Down

Superseded

ADR-024
Full EDC Provisioning per Participant on Azure

Accepted

ADR-025
Keycloak Custom Domain (`auth.ehds.mabu.red`)

Accepted

ADR-026
Token-Efficient Planning & ADR Structure

Accepted

ADR-027
EDC Stack in Off-Hours Scale-Down (FinOps Cost Correction)

Superseded

ADR-028
Patient QR login via the EUDI Wallet (OpenID4VP)

Accepted

ADR-029
Dependency version pinning and refresh cadence

Accepted

ADR-030
Neo4j 5.26 → 2025.x calver line — migration readiness

Accepted

ADR-031
Every automated check must assert its outcome and exit non-zero on failure

Accepted

ADR-032
The API collection is organised by EHDS persona, and every request asserts its outcome

Accepted

ADR-033
Two-stage lab-report extraction: self-hosted parse, schema extraction, EU-resident models

Accepted

ADR-034
Reach the Claude API through workload identity federation, from a backend, never from the phone

Accepted

ADR-035
Azure EU by default, Anthropic by explicit consent, and the user's own provider without limit

Accepted

ADR-036
Operator secrets live in Azure Key Vault and are referenced, never copied

Accepted

ADR-037
A secure processing environment built on confidential computing, not on trust in the operator

Accepted

ADR-038
The scan is kept, as a sealed PDF, and diagnostics leave the phone only as a deliberate export

Accepted

ADR-039
Published reference ranges are quoted alongside the printed one, never in place of it

Accepted

ADR-040
Derived compliance state is computed in the API from the graph, never persisted

Accepted

ADR-041
Managed PostgreSQL on Azure, containerised PostgreSQL for local development

Accepted

ADR-042
Off-hours scale-down, the state that runs today

Accepted

ADR-043
UI routes read the graph directly; the proxy serves the data planes and what needs its credentials

Accepted

ADR-044
Every API route needs a session

Accepted

ADR-045
Cloud-native, vendor-agnostic observability, and a tamper-evident audit trail for regulators

Accepted

ADR-046
The Azure Vault keeps its state on the Flexible Server

Accepted

ADR-047
Vault stays up off-hours until it keeps its own state

Accepted

ADR-048
The TestFlight request is mailed by the hub, without a session

Superseded

ADR-049
Klarbefund connects to a patient's record by a device grant the website starts

Accepted

ADR-050
The Klarbefund beta is joined by a public TestFlight link

Accepted

ADR-052
The confidential secure processing environment, revisited against Azure and the vendors of October 2026

Superseded

ADR-053
Everything stops off hours, and the UI says so

Accepted

ADR-054
Klarbefund creates a sandbox account on the hub, gated by App Attest

Accepted

ADR-055
Azure runs the same JAD build as compose and CI

Accepted

ADR-056
Neo4j on Azure grows to 2 vCPU and 4 GiB, with its memory bounded

Accepted

ADR-057
Klarbefund sends weekly device means to the person's own EHDS record, behind a switch of its own

Accepted

ADR-058
Azure triggers the off-hours stop and start, as a managed identity

Accepted

ADR-059
The record holds reports, vaccinations and the medication plan, not laboratory values alone

ADR-060
The app locks with Face ID or the passcode; certificate pinning and jailbreak detection are declined with reasons

ADR-061
The UI on Azure scales out on whole cores, on its own HTTP concurrency rule

Accepted

ADR-062
The Art. 71 opt-out is a dated record and a label every secondary-use query excludes

Accepted

ADR-063
HealthDCAT-AP follows the release Implementing Regulation 2026/2098 points to, today Release 8, in its own namespace

Accepted

ADR-064
The hub meets Simpl-Open as a connector outside its agent, over DSP and DCP, with the Governance Authority as a trusted issuer

Accepted

ADR-065
The EUDI Wallet sign-in identifies the person: HAIP, both PID formats, one record per PID

Accepted

ADR-066
The hub runs its own EUDI verifier, behind a gate that passes the wallet API only

Proposed

ADR-067
A PID links to an account by a keyed fingerprint; the hub stores neither name nor birth date

Accepted

ADR-068
A sovereign confidential SPE: Confidential Containers and a Trustee the access body runs, Neo4j loaded per permit

Accepted

ADR-069
Two SPE workspaces as ACI confidential containers

Accepted

ADR-070
ADR-070-the-interface-follows-the-language-picker-without-locale-urls.md

ADR-071
ADR-071-the-documentation-follows-the-language-picker.md

ADR-072
SPE workspaces are stopped by default and start on demand

Accepted

ADR-073
The SPE workspaces' SEV-SNP TCB is checked against a minimum, not a list

Proposed

ADR-074
E2E, compliance and performance suites run nightly when main changed, not on every push

Accepted

Diagram legend (ArchiMate 3.2)

Yellow: business layer, the roles and the processes they perform
Blue: application layer, services, components and data objects
Green: technology layer, nodes, system software and devices
Open arrow: serving. Hollow dotted head: realization. Filled head: triggering. Dashed: flow. Dotted without head: access. Dot: assignment. Each diagram repeats its legend; the sources are in docs/architecture/diagrams.