Page History
| Navitabs | ||
|---|---|---|
| ||
Indholdsfortegnelse
| Table of Contents |
|---|
Introduktion
Formål
Formålet med dette dokument er at beskrive systemarkitekturen for DROSGM-BFF.
Læsevejledning
Nærværende dokument er tiltænkt udviklere og IT-arkitekter med interesse i DROS GM-BFF og dens opbygning.
Definitioner og referencer
| NSP | National Service Platform | ||
| DROS | Dokumentregistrings- og opdateringsservice | ||
| GM | Graviditetsmappen | DGWS | Den Gode WebService
Overblik over
...
Dokumentregistrings- og opdateringsservice (DROS) håndterer oprettelsen af nye dokumenter. Servicen tager såldees imod registreringer til repository. Efterfølgende sørger det centrale XDS repository for at meta-data afleveres til registry, så dokumenterne kan fremsøges vha. Dokumentdelingsservice (DDS)
| HTML |
|---|
<iframe src="https://archi.nspop.dk/NSP/570928ca/views/id-6a5cebb5-c103-4f88-bfc3-0e96ed8049b4.html" name="test" height="450" width="800">You need a Frames Capable browser to view this content.</iframe> |
* Hver kasse i ovenstående diagram har en kort forklaring, som kommer frem i et nyt browservindue, når der klikkes på kassen.
Løsningens afhængigheder
DROS betjener sig af tredjeparts biblioteker fra IPF Open eHealth Integration Platform til implementations- og hjælpeklasser, der har med XDS IHE at gøre.
DROS anvender NSP libraries:
- audit-api
- security-api
Løsningens opbygning
Nedenstående diagram viser opbygningen af DROS.
GM-BFF
Graviditetsmappens Backend For Frontend (GM-BFF) er en service, som skal servicere MinGraviditet app. Den følger BFF mønsteret (https://samnewman.io/patterns/architectural/bff/), hvilket resulterer i en række operationer, der stiller data til rådighed i klumper tilpasset klientens (appens) behov, uanset at disse kan komme fra flere datakilder eller i strukturer der ikke egner sig til appens brug. BFF'en har til opgave at sammenstille og omforme data efter appens behovI designet er der lagt vægt på at definere en fornuftig struktur, hvor hver af DROS services er opbygget på en ensartet måde.
abedaecfGliffy Diagram macroId
3a317a93aae7-
4ec11fd2-
b59243dd-
7ebf99f9c6c7a8e5-
DROS pakkeoverblik454c52b0acbf displayName
DROS pakkeoverblikgm-bff component overview name gm-bff component overview pagePin
Ovenstående diagram viser, hvorledes en DROS ITI-X service er opbygget.
Selve service interface og implementation er placeret i pakkerne dk.nsp.dros.service(.impl). Klasserne i disse pakker er ansvarlige for at modtage requests fra anvenderne på de for DROS definerede snitflader. Ved at anvende klasser i pakken dk.nsp.dros.security valideres det, at den indkommende sikkerhedsbillet er valid og overholder de for DROS definerede krav (se evt. DROS - Driftsvejledning for muligheder for opsætning).
Klasserne i pakkerne dk.nsp.dros.service.validation(.impl) indeholder funktionalitet der har til formål at:
- Validere det indkommende request (se afsnit nedenfor vedr. validering)
- Konvertere de indkommende requests til domæneklasser (som defineret i biblioteket openehealth) til brug for videre validering (se afsnit nedenfor vedr. validering).
Hvis valideringerne i DROS ikke er overholdt, så returnerer DROS passende fejlbesked til den kaldende anvender.
Hvis valideringerne er overholdt, så anvender DROS klasser i pakkerne dk.nsp.dros.backend(.impl) til at kalde den bagvedliggende XDS infrastruktur.
Validering i DROS
DROS validerer de indkommende requests.
Whitelisting
DROS har sin egen whitelistingtabel, hvor cvr eller UUID for det kaldende certifikat skal være whitelistet. Se DROS - Driftsvejledning for detaljer.
Håndterede type koder (type codes)
DROS kan konfigureres med en liste af type codes, sådan at en instans håndtere en eller flere type koder. Dette resulterer i følgende opførsel, hvis der kaldes med en ikke håndteret type:
- ITI-41 Provide and Register document: hvis typecode indgår i dokumentets metadata (documententry) og den ikke håndteres afvises kaldet med en fejl.
- ITI-42 Register document set: hvis typecode indgår i dokumentets metadata (documententry) og den ikke håndteres afvises kaldet med en fejl.
- ITI-61 Register on demand document: hvis typecode indgår i dokumentets metadata (documententry) og den ikke håndteres afvises kaldet med en fejl.
- ITI-57 Update metadata: hvis typecode indgår i dokumentets metadata (documententry) og den ikke håndteres afvises kaldet med en fejl.
- ITI-57 Deprecate: forventes at blive afvist af bagvedliggende registry, da target dokument forventes ikke at være tilgængeligt.
IHE validering
I det anvendte openhealth bibliotek findes en standard XDS validering. Dette anvendes til en simpel validering, som tjekker, at det indkommende request er lovligt i henhold til standarden IHE XDS.
Valideringspakkerne er struktureret, så disse senere kan udvides med NSP specifikke valideringer.
Validering af CPR nummer
Kalderen vil således altid få 0 eller flere Document Entry tilbage fra DROS, hvis der spørges på et lovligt CPR nummer og man ikke vha. søgekriterier har udeholdt formatcode og typecode.
Til valideringen skal der opsættes en CPR validering, der anvender CPRExists service til verficering af CPR-numre. CPR valideringen kan køre i følgende tre modes:
- OFF: Der foretages ikke yderligere verifikation af CPRnummeret udover den simple validering beskrevet ovenfor. CPRExists kaldes ikke
- WARNING: CPRExists service kaldes. Hvis denne service svarer, at CPR nummeret ikke findes, så audit logges denne information. Der gives en warning tilbage til anvenderen (sammen med svaret i øvrigt).
- REJECT: CPRExists service kaldes. Svaret fra denne er en hård validering dvs kaldet til DROS, hvis CPRExist service ikke kender CPR nummeret.
Hvis cpr-validering er slået til, udføres valideringen på ITI-41, ITI-42 og ITI-61, men ikke på ITI-57. Dvs. ved oprettelse og ændring foretages validering, men det er muligt at slette dokumentkilder uden fejl/warning.
Validering af requests
Der er udviklet et bibliotek til validering af XDS dokumenter, XdsValidation.
DROS kan konfigureres til at anvende dette bibliotek til at validere requests, inden de videresendes til det bagvedliggende registry. Der er en række konfigurationer, som kan sættes op til valideringsbiblioteket, sådan at DROS har mulighed for at påvirke valideringen. I dets nuværende form drejer det sig hovedsagligt om en række lister af gyldige koder. F.eks. hvilke typecodes, formatcodes, eventscodes etc metadata og dokument må indeholde.
Se driftsvejledning for detaljer om muligheder og konfiguration. Validering gennem validerings bibliotek kan køre i fire modes:
...
2
BFF'en henter data fra 2 kilder: gm-facade på NSP for journaldata og CMS for artikler og tekster. Journal data caches i en lokal database, for at undgå gentagne opslag efter de samme data. BFF udstiller søgning i CMS via Meilisearch.
Løsningens afhængigheder
BFF'en udstilles som en Spring Boot server med et REST API.
CMS er en Strapi (https://strapi.io/) instans, hostet i samme kubernetes miljø som BFF'en. Strapi stiller et API til rådighed til udlæsning af ressourcer i Strapi, fx kategorier, artikler eller tjeklister. API'et er et REST agtigt api med en lidt speciel syntaks for søgninger og specificering af returnerede værdier. Disse særheder gemmes bag BFF'en, så appen kan få et API der er lettere at arbejde med.
gm-facade komponenten ligger på NSP, og udstiller en FHIR model for graviditetsmappen. Da der ikke er indført et forløbsbegreb eller lignende strukturerende begreber, er der kun én operation på gm-facade, nemlig "hent hele journalen for den angivne borger". Denne udstilles i en FHIR model som BFF læser og omformer til en intern model, der benyttes til de enkelte operationer på BFF.
Løsningens arkitektur
Internt er BFF'en struktureret i delkomponenter som følger:
- Controllere: API'et specificeret i OpenAPI, og ud fra dette genereres model-klasser og API interfaces. Disse API interfaces implementeres af Controllere, hvis formål er at udstille operationerne på BFF web servicen.
- Config: Applikationen er en Spring Boot applikation, så en del aspekter er sat op gennem konfiguration og interceptorer, deriblandt sikkerhed og logning.
- Integrationer: Der skal kaldes til eksterne services i form af CMS og gm-facade.
- Mappere: For at oversætte de interne modeller til API'ets modeller foretages mapning fra interne model-klasser eller kaldte services modeller til BFF API'ets genererede model-klasser.
- Journal Translator: gm-facadens FHIR model oversættes til en intern model, der er nemmere at arbejde med.
- Journal Logic: Udledning af terminsdatoer og forløb fra journal-modellen.
- Journal Cache: En tidsbestemt caching af læste journal data pr. borger.
Den simpleste udgave af et kald på BFF kalder videre til CMS eller gm-facade, omformer svaret til det rette format og returnerer dette. Lidt mere detaljeret ser det sådan ud:
| Gliffy Diagram | ||||||
|---|---|---|---|---|---|---|
|
Der er som det ses af ovenstående mere end blot gennemstilling af kald:
- gm-facaden returnerer en FHIR model. Modellen består af en masse FHIR Observations med data i forskellige extensions. For at gøre navigationen i modellen lettere, læses FHIR modellen over i en model der afspejler den logiske model mere direkte, dvs. man kan tilgå data på mere sigende vis, fx
prf.allergiskDiposition().barnDisponeret(). Dette sker iSearchBundleTranslatorog returnerer enUnstructuredJournal. UnstructuredJournalindeholder stadig alle borgerens dokumenter i ustruktureret form. Da der ikke er et eksplicit forløbsbegreb, er vi nødt til at forsøge at samle dokumenter i grupper der er samme forløb. Dette foregår iCarePathExtractor, der udleder forløbsperioder ud fra registrerede terminsdatoer og fordeler dokumenter i de forskellige forløb.- Endelig skal data formateres om fra
UnstructuredJournaltil operationens API. For de helt simple operationer foregår det bare direkte i controlleren, men for mere avancerede strukturer foregår det i en mapper, alaBackgroundInfoJournalDataSetMapper.
Ovenstående sekvensdiagram ignorerer to yderligere kompleksiteter, nemlig cachen af journaldata og sammenstilling af journaldata med CMS indhold. Sammenstilling af data foregår ved at data hentes fra CMS (fx i dette tilfælde ordforklaringer) og fra gm-facaden, og i mapperen plukkes data så fra hhv. CMS'ens eller gm-facadens returnerede data.
Cache
Svar fra gm-facaden caches i lokal database for gm-bff.
Nøglen til opslag i cachen er borgerens CPR (taget fra bearer token) kombineret med BFF'ens release nummer. Dette sikre at en ny version af gm-bff vil invalidere cachen og data hentes igen fra gm-facade.
Cachen er tidsbegrænset, dvs. en cachet værdi genbruges kun hvis den er hentet for nyligt. Hvor lang tid cachen skal gælde er konfigurerbart, men er i udgangspunktet konfigureret til en halv time. Dog er det lavet sådan at hver gang man bruger data nulstilles uret. Så hvis man læser journalen op og lægger den i cachen, og så læser den igen 20 minutter senere, vil den så igen gælde 30 minutter derfra, altså 50 minutter i alt, hvis den ikke tilgås igen inden.
Cachen ryddes op løbende af et baggrundsjob, der kører hvert 5 minut (konfigurerbart). Jobbet finde alle indgang der er udløbet og slette dem fra databasen.
Sikkerhed
REST servicens API er delt i åbne og lukkede endpoints. De endpoints der ikke involverer persondata, er åbne og kræver ingen adgangskontrol.
For de lukkede endpoints er adgangskontrollen baseret på bearer token sikkerhed i form af json web tokens med standarden JTP-H. Tokens valideres for gyldighed, for issuer og for om de har det forventede scope. Det givne token sendes i øvrigt videre med til kald på gm-facaden.
BFF'en kobles på sundhedsdatanettet til al adgang til NSP'en.
Driftsmiljø og netværk
BFF og CMS driftes separat fra NSP, i et TCS (Trifork Cloud Stack) Kubernetes miljø. Al indgående og udgående trafik går gennem Kubernetes Ingress, hvor udstillede end points, routing, TLS terminering og IP-whitelisting håndteres.
BFF'en og de omkringliggende komponenter i driftsmiljøet, og hvordan de kommunikerer, er vist i nedenstående diagram.
Her illustreres hvordan appen tilgår OIDC providere og hhv lukkede og åbne endpoints på BFF'en, mens CMS Admin konsollen tilgår CMS komponenten, samt Keycloak til to-faktor login.
BFF komponenten udstiller lukkede endpoints, der kræver en gyldig JTP-H bearer token (til alt der indeholder persondata), og åbne endpoints, der ikke har nogen sikkerhedskrav (til artikler mm. fra CMS'en). Begge grupper af end points udstilles kun på HTTPS.
Internt i TCS driftsmiljøet, snakker komponenterne sammen via interne definerede netværk, der er konfigureret i TCS miljøet og ikke tilgængelige udefra. Disse kommunikerer via HTTP for at mindske overhead. CMS'en opdaterer Meillisearch indexet ved opdateringer til artikler, og BFF tilgår CMS servicen og Meilisearch indexet.
BFF'en snakker med OIDC provideren ved validering af tokens, og endelig snakker BFF'en med GMAF (GM facade) på NSP. Al kommunikation til NSP foregår via tilkobling til sundhedsdatanettet.
Dokument Historik
| 3/4 2025 | Martin Henriksen/SDS | Etablering af dokumentation |
| 22/7 2025 | Anders Ringsmose/Trifork | Beskrivelse af arkitektur |
| 15/9 2025 | Thomas Glæsner/Trifork | Mindre rettelser |
...

