Koppeltaal 2.0 Implementation Guide (Full Documentation)
0.15.1 - ci-build
NL
Koppeltaal 2.0 Implementation Guide (Full Documentation) - Local Development build (v0.15.1) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
| Page standards status: Draft |
Dit document analyseert KPTSTD-879 en formuleert drie voorstellen voor aanpassingen in TOP-KT-011:
| # | Voorstel | Status |
|---|---|---|
| 1 | X-Correlation-Id volgt causaliteit - Verwijst naar direct triggerende request, niet naar "root trigger" | Te accorderen |
| 2 | X-Trace-Id fallback verwijderen - Niet vullen met X-Request-Id, maar leeg laten of nieuwe waarde | Te accorderen |
| 3 | Nieuw sequence diagram - Vervangt huidige onduidelijke diagrammen | Te accorderen |
Aanleiding: Bevinding van Jan-Wijbrand Kolman (Minddistrict) dat de huidige diagrammen "onjuist of onduidelijk" zijn.
Dit issue komt voort uit een bevinding gerapporteerd door Jan-Wijbrand Kolman (Minddistrict) tijdens een TC-meeting.
"Bij deze een markdown file met daarin een sequence diagram in Mermaid-syntax. Dit diagram is dus een weerslag van mijn begrip, aangevuld door Joris, van de bedoeling van de trace headers in Koppeltaal.
Als mijn begrip juist is, mag wat mij betreft het diagram toegevoegd aan de spec. Ik denk dat de twee huidige sequence diagrammen op deze pagina onjuist of in elk geval onduidelijk zijn."
De VZVZ/Koppeltaal standaard is beschreven in:
De specificatie bevat op pagina 5 twee sequence diagrammen voor "Tracing en ketenlogging". Deze diagrammen zijn de "onduidelijke" diagrammen waar Jan-Wijbrand over klaagt.
De huidige spec bevat twee diagrammen die de header propagatie tonen. Problemen:
Volgens de huidige specificatie gebruikt Koppeltaal drie headers voor ketenlogging:
| Header | Doel |
|---|---|
X-Request-Id |
Unieke identifier per individueel request |
X-Trace-Id |
Identifier die constant blijft door de hele trace-keten |
X-Correlation-Id |
Verwijst naar de X-Request-Id van het voorgaande request in de keten |
Deze headers worden vastgelegd in AuditEvents en maken tracering mogelijk.
Het voorgestelde sequence diagram toont de header propagatie in een typisch scenario:
X-Request-Id: epd100X-Request-Id: epd100X-Trace-Id: trace123 (FHIR store start nieuwe trace context)X-Request-Id: fhir200 (nieuw request)X-Correlation-Id: epd100 (verwijst naar origineel)X-Trace-Id: trace123 (behouden)X-Correlation-Id: fhir200 (verwijst naar de notification)X-Trace-Id: trace123X-Request-Id (md300, md301, md302, md303)X-Correlation-Id: fhir200. Dit is de X-Request-Id van de notification, niet van het direct triggerende request.Probleem: Door alle X-Correlation-Ids naar dezelfde notification te laten verwijzen (fhir200), gaat de causale/volgordelijke relatie verloren. Op basis van de AuditEvents kan dan niet gereconstrueerd worden welk request welk ander request heeft getriggerd.
In stap 3 krijgt kt2implementation de notification met X-Correlation-Id: epd100, maar in stap 4+ gebruikt kt2implementation X-Correlation-Id: fhir200. Dit suggereert dat de Correlation-Id altijd verwijst naar het direct triggerende request.
De responses bevatten geen X-Correlation-Id (alleen X-Request-Id en X-Trace-Id). Dit lijkt correct - Correlation-Id is alleen relevant voor uitgaande requests.
Fout in X-Correlation-Id voor stappen 7 en 11:
Als de regel is dat X-Correlation-Id verwijst naar het direct triggerende request, dan:
| Stap | Actie | In diagram | Zou moeten zijn |
|---|---|---|---|
| 5 | Request Task details | fhir200 |
fhir200 (getriggerd door notification) |
| 7 | Forward Task data | fhir200 |
md300 (getriggerd door stap 5) |
| 9 | Request Patient details | fhir200 |
fhir200 (getriggerd door notification) |
| 11 | Forward Patient data | fhir200 |
md302 (getriggerd door stap 9) |
Conclusie: De forward-acties (7, 11) zouden de X-Request-Id van hun direct triggerende request (5, 9) als X-Correlation-Id moeten gebruiken.
De juiste X-Correlation-Id hangt af van de causaliteitsketen. Er zijn twee mogelijke interpretaties:
Scenario A: Parallelle triggering door notification
Notification (3)
|-- triggert direct -> Task ophalen (5)
|-- triggert direct -> Patient ophalen (9)
+-- triggert direct -> ActivityDefinition ophalen (13)
Dan is X-Correlation-Id: fhir200 voor stappen 5, 9 en 13 correct
Scenario B: Sequentiële/causale triggering (met parallelle takken)
Notification (3)
+-- triggert -> Task ophalen (5)
+-- Task bevat Patient referentie
| +-- triggert -> Patient ophalen (9)
+-- Task bevat ActivityDefinition referentie
+-- triggert -> ActivityDefinition ophalen (parallel met Patient)
Dan zou stap 9 X-Correlation-Id: md300 moeten hebben (de Task request, niet de notification).
Analyse: In de praktijk is scenario B waarschijnlijker: je weet pas welke Patient en ActivityDefinition je moet ophalen nadat je de Task hebt ontvangen (de referenties zitten in de Task). Dit betekent dat de causaliteit sequentieel is vanuit de notification, maar parallel vanuit de Task response - zowel Patient als ActivityDefinition worden getriggerd door dezelfde Task fetch en hebben daarom beide X-Correlation-Id: md300.
Aanbeveling: Het diagram moet expliciet maken wat de causaliteitsketen is, en de X-Correlation-Id moet deze causaliteit correct reflecteren.

| Stap | Actie | Origineel | Gecorrigeerd | Reden |
|---|---|---|---|---|
| 7 | Forward Task data | X-Correlation-Id: fhir200 |
X-Correlation-Id: md300 |
Getriggerd door Task fetch (5) |
| 9 | Request Patient | X-Correlation-Id: fhir200 |
X-Correlation-Id: md300 |
Patient ref zit in Task response (6) |
| 11 | Forward Patient data | X-Correlation-Id: fhir200 |
X-Correlation-Id: md302 |
Getriggerd door Patient fetch (9) |
| 13 | Request ActivityDefinition | X-Correlation-Id: fhir200 |
X-Correlation-Id: md300 |
ActivityDefinition ref zit in Task (parallel met Patient) |
| 15 | Forward ActivityDefinition | X-Correlation-Id: fhir200 |
X-Correlation-Id: md304 |
Getriggerd door ActivityDefinition fetch (13) |
epd100 (EPD request)
+-- fhir200 (Notification)
+-- md300 (Task fetch)
|-- md301 (Forward Task)
|-- md302 (Patient fetch, want Patient ref in Task)
| +-- md303 (Forward Patient)
+-- md304 (ActivityDefinition fetch, want ActivityDefinition ref in Task)
+-- md305 (Forward ActivityDefinition)
Let op: md302 (Patient fetch) en md304 (ActivityDefinition fetch) hebben beide X-Correlation-Id: md300 omdat ze parallel worden getriggerd door dezelfde Task response. Dit toont aan dat een causale hiërarchie ook parallelle processen kan bevatten.
Op basis van de analyse van het voorgestelde diagram (KPTSTD-879) en de huidige spec worden de volgende aanpassingen voorgesteld.
Uitgangspunt: X-Correlation-Id verwijst naar het direct triggerende request (causale keten), niet naar de "root trigger" of het originele EPD request.
Waarom causaliteit? De X-Correlation-Id wordt gebruikt om de sequentie te volgen. Door te verwijzen naar het direct triggerende request (in plaats van een vaste "root") kan op basis van de AuditEvents de volgorde in de tijd correct gereconstrueerd worden. Elk AuditEvent bevat:
Door deze keten te volgen kan de volledige causale flow worden afgeleid.
Regel:
Impact op diagram:
| Stap | Actie | Scenario A (parallel) | Scenario B (causaal) |
|---|---|---|---|
| 7 | Forward Task data | fhir200 |
md300 |
| 9 | Request Patient | fhir200 |
md300 |
| 11 | Forward Patient | fhir200 |
md302 |
| 13 | Request ActivityDefinition | fhir200 |
md300 (parallel met Patient) |
| 15 | Forward ActivityDefinition | fhir200 |
md304 |
De waarde van dit veld is globaal uniek en heeft een string waarde. Om globaal
uniek te zijn wordt aangeraden een uuid v4 te gebruiken.
Deze waarde is typisch het X-Request-Id van het originele request indien er
sprake is van een asynchroon request of notificatie. Verder niet gevuld.
Indien ontbreekt: leeg laten
Implementatie uitvoerder: leeg laten indien er geen bovenliggend request is,
vullen met X-Request-Id van het bovenliggend request.
Implementatie ontvanger: loggen in het AuditEvent indien van toepassing,
teruggeven in het HTTP response indien de X-Request-Id gevuld is met aan
andere waarde dan in het request is meegegeven.
Mapping op AuditEvent: extension.correlation-id
De waarde van dit veld is globaal uniek en heeft een string waarde. Om globaal
uniek te zijn wordt aangeraden een uuid v4 te gebruiken.
De X-Correlation-Id verwijst naar de X-Request-Id van het **direct triggerende
request**. Dit is het request dat causaal verantwoordelijk is voor het huidige
request. Voorbeelden:
- Een request dat voortkomt uit een **notification** gebruikt de X-Request-Id
van die notification als X-Correlation-Id
- Een request dat voortkomt uit de **verwerking van een resource** (bijv. een
Patient ophalen omdat de Task een Patient referentie bevat) gebruikt de
X-Request-Id van het resource-fetch request als X-Correlation-Id
- Een request dat voortkomt uit de **response van een ander request** gebruikt
de X-Request-Id van dat request als X-Correlation-Id
- **Parallelle requests** die door dezelfde resource response worden getriggerd
(bijv. zowel Patient als ActivityDefinition ophalen na een Task response)
gebruiken beide de X-Request-Id van dat resource-fetch request als
X-Correlation-Id
Indien ontbreekt: leeg laten
Implementatie uitvoerder: leeg laten indien er geen bovenliggend request is,
vullen met X-Request-Id van het **direct triggerende** request.
Implementatie ontvanger: loggen in het AuditEvent indien van toepassing,
teruggeven in het HTTP response indien de X-Request-Id gevuld is met een
andere waarde dan in het request is meegegeven.
Mapping op AuditEvent: extension.correlation-id
| Aspect | Huidige tekst | Voorgestelde tekst |
|---|---|---|
| Definitie | "originele request" (onduidelijk) | "direct triggerende request" (causaal) |
| Voorbeelden | Geen | Drie concrete voorbeelden |
| Uitvoerder | "bovenliggend request" | "direct triggerende request" |
Probleem: Het gebruiken van X-Request-Id als fallback voor X-Trace-Id is onlogisch:
Voorstel:
De waarde van dit veld is globaal uniek en heeft een string waarde. Om globaal
uniek te zijn wordt aangeraden een uuid v4 te gebruiken.
De X-Trace-Id kan in verschillende requests met dezelfde waarde voorkomen om
aan te geven dat deze requests aan elkaar gerelateerd zijn.
Indien de waarde ontbreekt: in het request mag de ontvangende partij deze
vullen met de waarde van de X-Request-Id van het bovenliggende request. Het
veld mag ook leeg gelaten worden.
Implementatie uitvoerder: vullen met de X-Trace-Id waarde van het
bovenliggende request, of eventueel met de waarde van de X-Request-Id als het
bovenliggende request geen waarde voor de X-Trace-Id heeft ingevuld.
Implementatie ontvanger: opslaan indien er andere requests uit voorkomen,
vullen met X-Request-Id indien de X-Trace-Id ontbreekt of leeglaten. Loggen
in het AuditEvent indien van toepassing.
Mapping op AuditEvent: extension.trace-id
De waarde van dit veld is globaal uniek en heeft een string waarde. Om globaal
uniek te zijn wordt aangeraden een uuid v4 te gebruiken.
De X-Trace-Id kan in verschillende requests met dezelfde waarde voorkomen om
aan te geven dat deze requests aan elkaar gerelateerd zijn.
Indien de waarde ontbreekt: de ontvangende partij MAG een nieuwe X-Trace-Id
genereren om een nieuwe trace context te starten. Het veld MAG ook leeg
gelaten worden.
Implementatie uitvoerder: vullen met de X-Trace-Id waarde van het
bovenliggende request indien aanwezig, anders leeg laten.
Implementatie ontvanger: opslaan indien er andere requests uit voorkomen.
Indien de X-Trace-Id ontbreekt MAG een nieuwe waarde gegenereerd worden of
leeg gelaten worden. Loggen in het AuditEvent indien van toepassing.
Mapping op AuditEvent: extension.trace-id
| Aspect | Huidige tekst | Voorgestelde tekst |
|---|---|---|
| Fallback indien ontbreekt | "vullen met X-Request-Id" | "nieuwe waarde genereren OF leeg laten" |
| Uitvoerder fallback | "met waarde van X-Request-Id" | "leeg laten" |
| Ontvanger fallback | "vullen met X-Request-Id" | "nieuwe waarde OF leeg laten" |
Voorstel: Het sequence diagram (Scenario B - Causale keten) toevoegen aan de TOP-KT-011 Confluence pagina ter vervanging van de huidige onduidelijke diagrammen.
Huidige situatie:
Na aanpassing:
| Header | Aspect | Huidige Spec | Voorstel |
|---|---|---|---|
| X-Correlation-Id | Verwijzing | "originele request" (vaag) | "direct triggerende request" (causaal) |
| X-Correlation-Id | Voorbeelden | Geen | 3 concrete voorbeelden |
| X-Trace-Id | Fallback | Vullen met X-Request-Id | Nieuwe waarde OF leeg |
| Diagrammen | Formaat | Kleurcodes, onduidelijk | Mermaid, expliciet |
| # | Stap | Status |
|---|---|---|
| 1 | Vergelijken met KPTSTD-879.doc | Afgerond |
| 2 | Review voorgesteld diagram | Afgerond |
| 3 | Voorstellen bespreken/accorderen | In afwachting |
| 4 | Aanpassingen doorvoeren op Confluence | Na akkoord |
Scope: Alleen Confluence wijzigingen (TOP-KT-011), geen FHIR IG profielaanpassingen.
epd100 (EPD request - Create Task)
|
+-- fhir200 (FHIR Store Notification)
|
+-- md300 (Task fetch - correlation: fhir200)
|
|-- md301 (Forward Task - correlation: md300)
|
|-- md302 (Patient fetch - correlation: md300, want Patient ref in Task)
| |
| +-- md303 (Forward Patient - correlation: md302)
|
+-- md304 (ActivityDefinition fetch - correlation: md300, want ActivityDefinition ref in Task)
|
+-- md305 (Forward ActivityDefinition - correlation: md304)
Parallelle processen: md302 en md304 hebben dezelfde correlation: md300 omdat beide worden getriggerd door de Task response. Ze kunnen parallel uitgevoerd worden, maar delen dezelfde causale oorsprong (de Task fetch).
Wanneer een systeem zelf een trace start (bijv. batch processing, scheduled job):
batch001 (Batch processing start)
| X-Request-Id: batch001
| X-Correlation-Id: <leeg>
| X-Trace-Id: <nieuwe trace>
|
|-- proc001 (Process item 1)
| X-Request-Id: proc001
| X-Correlation-Id: batch001
| X-Trace-Id: <zelfde trace>
|
+-- proc002 (Process item 2)
X-Request-Id: proc002
X-Correlation-Id: batch001
X-Trace-Id: <zelfde trace>
Laatste update: 2026-01-26