OZO FHIR implementation guide
0.7.7 - ci-build
OZO FHIR implementation guide - Local Development build (v0.7.7) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
All notable changes to the OZO FHIR Implementation Guide will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
category from 1..* to 0..*. The SNOMED CT practice setting list lacks coverage for primary care and the social domain, making it impractical to require a coded category for all team types. Category is now optional — teams can provide any code system (SNOMED CT, Dutch organization type list urn:oid:2.16.840.1.113883.2.4.15.1060, or plain text).Task.focus being updated on every new Communication, Task?status=requested is now sufficient as the primary subscription for both unread tracking and new-message notification. Both messaging pages updated to:
Task?status=requested as the only required subscriptionCommunication?id as optional (only needed to see own sent messages)CommunicationRequest?id as optional (only needed for thread lifecycle events)Task.focus updates solve itTask?id is only needed when the platform also wants to detect read receipts (REQUESTED → COMPLETED transitions)focus field (0..1, Reference(OZOCommunication)) to point to the latest Communication in the thread. When a new message arrives, the OZO FHIR Api updates Task.focus to reference the new Communication. This ensures Task subscriptions fire even when the status value doesn't change (the resource content genuinely changes), and gives clients a direct pointer to the most recent unread message.requested (correct for examples showing what a client would create). The HAPI activation issue is solved by the minimal package stripping examples.status from requested to off to prevent HAPI from activating example subscriptions with unreachable endpoints on server restart. Changed endpoint URLs from example.nl to example.com.source.observer in AuditEvents. Resolves HAPI HAPI-0575 validation error where a plain Device resource was rejected because it didn't conform to any of the installed Nictiz Device profiles (medical devices only). The proxy can now upsert a Device with meta.profile = OZODevice and it will be accepted.source.observer no longer constrained to Reference(Device). Now accepts any reference type with logical identifiers (system/value) — no Device resource needs to exist on the server.entity.what from 1..1 to 0..1. Empty search results are access attempts that must be logged for NEN7510 but don't reference a specific resource — the search query in entity.query serves as the audit trail. Aligns with FHIR R4 base.https://www.ozoverbindzorg.nl/namingsystem/{type} without ozo/ or ozo-connect/ prefixes: .../person, .../professional, .../organization, .../team, .../network-relation, .../email, .../devicesource.observer changed from literal Reference(Device/ozo-aaa-proxy-001) to logical identifier with system = .../device, value = aaa-proxy-001https://www.ozoverbindzorg.nl/namingsystem/device)fhir.nl.gf references from configuration, dependency table, troubleshooting, and complete exampleTask?id note on both messaging pages: needed for read-list tracking (REQUESTED → COMPLETED transitions)fhir.nl.gf (NL Generic Functions) dependency. OZOPractitioner and OZOOrganization no longer extend NL-GF profiles — they now extend base FHIR R4 Practitioner and Organization directly. This eliminates the AssignedId slice, the HAPI-0574 workaround, and the dependency on an unpublished package.0..* MS with open slicing. No named slices, no invariants. Any identifier system accepted.0..* MS with open slicing. Removed all 5 named slices and invariant.NlGfPractitioner to Practitioner. Simplified identifiers to 0..* MS with open slicing. Removed AssignedId slice and invariant.NlGfOrganization to Organization. Simplified identifiers to 0..* MS with open slicing. Removed AssignedId and URA slices.ozoverbindzorg.nl/namingsystem/professionalozoverbindzorg.nl/namingsystem/organizationoverview.md identifier tables for all resource typesinteraction-network.md identifier requirements sectionOZOPatient to allowed sender types. Production data shows Patient resources are used as senders (4 out of 192 Communications).OZOPatient to allowed requester and sender types. Production data shows Patient resources are used as requester/sender (2 out of 33 CommunicationRequests).Patient/$expunge is supported for AVG/GDPR right-to-erasure. Includes status mapping per resource type, security labels, and proxy enforcement guidance.entity.what references to version-specific format ({ResourceType}/{id}/_history/{version}). NEN7510 requires audit events to reference the exact version of the resource accessed, not the mutable current version.entity.what must use version-specific references for NEN7510 compliance. Non-versioned references become broken links when resources are deleted, undermining the legal audit trail.status field, and AuditEvent entity references not version-specific.recipient from 1..* to 0..*. Thread participants are defined on CommunicationRequest.recipient — individual messages do not have separate addressing. The field is kept from the parent profile for FHIR compliance but documented as unused in the OZO messaging model. Matches production data where no Communication resources have a recipient.recipient from all Communication examples (Reply-Manu-to-Kees, Reply-Kees-to-Netwerk, Clinic-Response-to-Pharmacy, Pharmacy-Followup-by-Pieter)recipient 0..* as unusedrecipient is not set on Communicationspart-of:CommunicationRequest.recipient instead of Communication.recipientchannel.payload as required in Dutch healthcare). Covers new message detection, unread tracking, and thread lifecycle.inResponseTo reference (was pointing to deleted Pharmacy-Initial-Message; this is now the first reply in the thread, responding to the CommunicationRequest payload)#completed to #requested (initial state when created by the OZO FHIR Api). Added Title and Description.Task?id to Task?status=requested to avoid subscription storms and scope via AAA proxyCommunication subscription is the primary mechanism for new-message detection, not TaskTask notifications detect new messages — Task is a read/unread indicator onlysubject 0..0 — organizational teams have no patientmanagingOrganization 1..1 — required link to the owning Organizationcategory 1..* — required SNOMED CT coded team typename 1..1 — team display name requiredparticipant.member restricted to OZOPractitioner only (no RelatedPerson in org teams)interaction-messaging-team.md) with stepwise walkthrough of team-to-team messaging flows, including thread creation, replies from both teams, follow-up by different team members, and read receiptsOZOOrganizationalCareTeam. participant.member now also allows OZOOrganizationalCareTeam for nested team references (fixes existing conformance bug where Netwerk-Jan-de-Hoop referenced Department-Thuiszorg as CareTeam participant but the profile did not allow it)recipient now also allows OZOOrganizationalCareTeam in addition to existing typesrecipient now also allows OZOOrganizationalCareTeam. OZOSenderCareTeam extension tightened from Reference(CareTeam) to Reference(OZOOrganizationalCareTeam) (formalizes existing practice)OZOCareTeam to OZOOrganizationalCareTeam profile. Removed fake Patient/example-unassigned subject references that were a workaround for the previous subject 1..1 constraintOZOOrganizationalCareTeam profile and canonical URLsenderCareTeam extension pattern (sender field is always an individual, extension provides CareTeam reply-to address)Cache-Control header requirements for FHIR requests (no-cache vs no-store), pagination with _count and Bundle next links, and the OZO proxy Warning: 199 header for no-store detectionCT-, Msg-, Tsk-, AE-) that caused ugly doubled page URLs (e.g., CareTeam-CT-H-de-Boer.html). The IG Publisher already prepends the resource type to page URLs, making prefixes redundant.
CT-H-de-Boer → Netwerk-H-de-Boer, CT-Jan-de-Hoop → Netwerk-Jan-de-Hoop, CT-Department-Thuiszorg → Department-Thuiszorg, CT-Clinic-B → Clinic-B, CT-Pharmacy-A → Pharmacy-AMsg-RelatedPerson-to-CareTeam → Reply-Kees-to-Netwerk, Msg-Team-Reply-1-Initial-Message → Pharmacy-Initial-Message, Msg-Team-Reply-2-Clinic-Response → Clinic-Response-to-Pharmacy, Msg-Team-Reply-3-Pharmacy-Followup → Pharmacy-Followup-by-PieterTsk-Practitioner-Manu-Example → Notify-Manu-van-Weel, Tsk-Practitioner-Mark-Example → Notify-Mark-Benson, Tsk-RelatedPerson-Example → Notify-Kees-GrootAE-System-Access → System-Read, AE-Practitioner-Manu-Access → Manu-Read-Messages, AE-Practitioner-Mark-Access → Mark-Read-Messages, AE-RelatedPerson-Access → Kees-Read-Messages, AE-REST-Create-Example → REST-Create, AE-REST-Search-Example → REST-Search, AE-REST-Update-Failure → REST-Update-DeniedMsg-Practitioner-to-Practitioner example (which had sender = recipient = same person and wrong payload text)HAPI-0574: Slicing cannot be evaluated: Could not match discriminator ($this) for slice Practitioner.identifier:AssignedId:
^patternIdentifier.system to the AssignedId slice on both profilesAssignedId slice (inherited from NL-GF parent profiles) uses a value:$this discriminator but lacked a top-level patternIdentifier, preventing HAPI from matching identifiers to the slicehttps://ozo.headease.nl/practitionershttps://ozo.headease.nl/organizationsoverview.md, interaction-messaging.md, interaction-network.md, and auditevent-nen7510.md to match new Instance namesfetchDependencies: true approach with explicit dependency listing — transitive dependencies pull in hl7.fhir.r4.core and hl7.fhir.uv.extensions.r4 which contain R5-only SearchParameters (DeviceUsage, DomainResource) that crash HAPI R4hl7.fhir.uv.extensions.r4 as STORE_ONLY entry to satisfy dependency resolution without installing problematic SearchParametersnictiz.fhir.nl.r4.zib2020 and nictiz.fhir.nl.r4.nl-core entries as STORE_AND_INSTALLfhir.nl.gf as a separate implementation guide entry (with direct packageUrl to CI build)install_transitive_ig_dependencies: false to prevent recursive dependency installationHAPI-1684: Unknown resource name "DeviceUsage" / "DomainResource" (R5-only SearchParameters)HAPI-1301: Unable to locate package fhir.nl.gf#0.3.0security tool on macOS^version overrides (values like "0.2.1", "1.0.0", "2.0.0") that were misleading. The IG Publisher sets StructureDefinition.version to the IG package version from sushi-config.yaml, making per-profile version overrides redundant. All profiles now consistently report the IG version.fhir.nl.gf v0.3.0 to the package dependencies table with manual installation noteImplementationGuide and StructureDefinition to the recommended supported_resource_types configurationimplementationGuide field{ResourceType}-{id}.html. Previously, Instance names like Patient-H-de-Boer produced page URLs like Patient-Patient-H-de-Boer.html (doubled prefix), causing 404 errors from documentation linksPatient- prefix (e.g., Patient-H-de-Boer → H-de-Boer)Practitioner- prefix (e.g., Practitioner-Manu-van-Weel → Manu-van-Weel)RelatedPerson- prefix (e.g., RelatedPerson-Kees-Groot → Kees-Groot)Organization- prefix (e.g., Organization-Ziekenhuis-Amsterdam → Ziekenhuis-Amsterdam)CareTeam- with CT- prefix (e.g., CareTeam-H-de-Boer → CT-H-de-Boer)CommunicationRequest- prefix (e.g., CommunicationRequest-Thread-Example → Thread-Example)Communication- with Msg- prefix (e.g., Communication-RelatedPerson-to-CareTeam → Msg-RelatedPerson-to-CareTeam)Task- with Tsk- prefix (e.g., Task-RelatedPerson-Example → Tsk-RelatedPerson-Example)AuditEvent- with AE- prefix (e.g., AuditEvent-System-Access → AE-System-Access)* id overrides from 13 instances that had numeric IDs (e.g., * id = "1209") — the Instance name now serves as the id"Practitioner/1208") to FSH Reference() syntax (e.g., Reference(Marijke-van-der-Berg)) in CareTeam and RelatedPerson examplesoverview.md, interaction-network.md, interaction-messaging.md, and auditevent-nen7510.md to match new Instance names and generated page URLsPractitioner to NlGfPractitioner (nl-gf-practitioner):
nl-core-HealthProfessional-Practitioner via nl-gf-practitionerAssignedId identifier requirement (1..1) with assigner pattern linking practitioners to their employing organizationvalue:$this slicing discriminator. OZO identifiers are still validated via ozo-practitioner-has-professional-id invariant and supported through open slicingAssignedId identifier with https://ozo.headease.nl/practitioners system, practitioner slug as value, and employing organization's URA as assignerfhir.nl.gf v0.3.0) - Added as a dependency to support care services directory compliance and IHE mCSD alignmentcare-services-directory.plantuml)Organization to NlGfOrganization (nl-gf-organization):
nl-gf-organization via nl-core-HealthcareProvider-Organization)AssignedId identifier requirement (1..1) with assigner patternura-identifier-or-partof invariant: organizations must have a URA identifier or be partOf another organizationAssignedId identifier, type (V4 Ziekenhuis), updated URA system to canonical URLAssignedId identifier, type (V4 Ziekenhuis), updated URA system to canonical URLAssignedId identifier, type (Z3 Huisartspraktijk), updated URA system to canonical URLAssignedId identifier, type (G2 Apotheek), updated URA system to canonical URLinstall-nl-gf Makefile target to download fhir.nl.gf package from CI build (package is not published on FHIR registry)scripts/get_dependencies.py to parse sushi-config.yaml dependencies for automated installationOZO/Person → https://www.ozoverbindzorg.nl/namingsystem/ozo/personOZO-CONNECT/Person → https://www.ozoverbindzorg.nl/namingsystem/ozo-connect/personOZO/Professional → https://www.ozoverbindzorg.nl/namingsystem/ozo/professionalOZO-CONNECT/Professional → https://www.ozoverbindzorg.nl/namingsystem/ozo-connect/professionalOZO/Team → https://www.ozoverbindzorg.nl/namingsystem/ozo/teamOZO-CONNECT/Team → https://www.ozoverbindzorg.nl/namingsystem/ozo-connect/teamOZO/NetworkRelation → https://www.ozoverbindzorg.nl/namingsystem/ozo/network-relationemail → https://www.ozoverbindzorg.nl/namingsystem/email (temporary - should migrate to telecom)ura → http://fhir.nl/fhir/NamingSystem/ura (Nictiz standard)did_web → urn:ietf:rfc:3986 (value is itself a URI)build_with_image.sh to use ghcr.io imageoverview.md and interaction-network.md with new identifier URI patternsCommunicationRequest.sender does not allow CareTeam referencesOZOSenderCareTeam extension to support team-level messaging where a CareTeam needs to be the reply-to addresscopy-changelog Makefile target copies CHANGELOG.md to history.md during buildsender field constraint allowing OZOPractitioner, OZORelatedPerson, or OZOCareTeamsender serves as the reply-to address for team-level messaging and provides team-level authorizationrequester remains restricted to individuals (OZOPractitioner or OZORelatedPerson) to preserve auditabilitybuild-minimal and build-ig-minimal Makefile targetsscripts/convert_ig_to_package.py - Converts ImplementationGuide to package.json formatscripts/create_index.py - Creates .index.json for FHIR package structurescripts/strip_narratives.py - Strips narratives and mappings while preserving snapshots-minimal suffix)fhir-package-full) and minimal (fhir-package-minimal) builds.gitignore to exclude /output-minimal/ and additional build artifactsOZOPatient, OZOPractitioner, and OZORelatedPerson profiles:
^OZO[^/]*/ResourceType$) instead of explicit system enumerationOZO/Person, OZO-CONNECT/Person, OZO-MOBILE/Person, OZO-WEB/Person)ozoProfessionalId to ozoConnectProfessionalId for identifiers using the OZO-CONNECT/Professional system^url, ^name, and ^description metadata elements to all OZO FHIR profiles for improved canonical URL support and HAPI FHIR server compatibility:
OZOAuditEvent - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOAuditEventOZOCareTeam - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOCareTeamOZOCommunication - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOCommunicationOZOCommunicationRequest - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOCommunicationRequestOZOOrganization - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOOrganizationOZOPatient - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOPatientOZOPractitioner - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOPractitionerOZORelatedPerson - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZORelatedPersonOZOTask - http://ozoverbindzorg.nl/fhir/StructureDefinition/OZOTaskinput/fsh/input/fsh/instances/ to input/fsh/examples/ for improved organization and clarityaliases.fsh from input/fsh/input/fsh/ to input/fsh/ (root level)input/fsh/input/fsh/profiles/ to input/fsh/profiles/OZOPatient - Patient profile for the OZO platform with OZO Person identifier and BSN supportOZOPractitioner - Practitioner profile with OZO Professional identifier and email slicingOZORelatedPerson - RelatedPerson profile for informal caregivers with OZO Person and NetworkRelation identifiersOZOOrganization - Organization profile with URA and OZO Organization identifiersOZOCareTeam - CareTeam profile representing care networks with practitioners and related personsOZOCommunication - Communication profile for messages with thread linking via partOfOZOCommunicationRequest - CommunicationRequest profile for message threadsOZOTask - Task profile for work assignments and referrals with thread linking via basedOnOZOAuditEvent - AuditEvent profile for NEN7510 compliance with W3C Trace Context extensionsaliases.fsh with common system and profile aliases