diff --git a/README.md b/README.md index 72039a64..c392c4cc 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ The CI/CD pipeline uses the HL7 CI/CD infrastructure and Github webhooks which i ## Local development +### Running SUSHI +Use `./sushi.sh` instead of `npx sushi` to suppress known-safe naming warnings (ehealth-* names that don't follow PascalCase) while keeping all other output intact. + ### Running locally Do `rm -rf output && rm -rf temp/ && ./_genonce.sh` diff --git a/input/fsh/ehealth-carecommunication.fsh b/input/fsh/ehealth-carecommunication.fsh new file mode 100644 index 00000000..8960be2a --- /dev/null +++ b/input/fsh/ehealth-carecommunication.fsh @@ -0,0 +1,321 @@ +// comment for later: +// The note "should also exist in the MedcomCareCommunicationMessage bundle" is a packaging rule—consider documenting +// this in your IG narrative, as you can't force presence in a different Bundle with profile alone. + + +Profile: ehealth-carecommunication +Id: ehealth-carecommunication +Parent: Communication + +* obeys + stopped-status-statusReason + and only-asap-or-routine + and topic-required-when-category-other + and priority-category-invariant + and atLeastOnePayloadString + and payloadAttachment-contentType-required + and no-standard-sender + and sender-required-based-on-messagetype + and reply-requires-inResponseTo + +* identifier 1..2 MS +* identifier ^slicing.discriminator.type = #value +* identifier ^slicing.discriminator.path = "system" +* identifier ^slicing.rules = #open +* identifier contains communicationId 1..1 MS and messageHeaderId 0..1 MS + +* identifier[communicationId] obeys uuidv4 +* identifier[communicationId].system 1..1 MS +* identifier[communicationId].system = "http://ehealth.sundhed.dk/id/ehealth-carecommunication-identifier" +* identifier[communicationId].use 0..1 +* identifier[communicationId].use from http://hl7.org/fhir/ValueSet/identifier-use (required) +* identifier[communicationId].value 1..1 MS +* identifier[communicationId].value ^short = "UUID v4 in URN form (urn:uuid:)" +* identifier[communicationId].value ^definition = "The communication identifier as a UUID v4 in URN form. The URN form (urn:uuid:) is used so the same UUID is byte-identical to Bundle.entry.fullUrl and references in the MedCom careCommunication Bundle this profile is aligned with." +* identifier[communicationId] ^short = "The communication identifier" + +* identifier[messageHeaderId].system 1..1 MS +* identifier[messageHeaderId].system = "http://ehealth.sundhed.dk/fhir/system/medcom-message-header-id" +* identifier[messageHeaderId].value 1..1 MS +* identifier[messageHeaderId] ^short = "The ID of the originating MessageHeader resource" + +* status 1..1 MS + +* category 1..1 MS +* category from http://ehealth.sundhed.dk/vs/ehealth-carecommunication-category (required) +* category.coding 1..1 MS +* category.coding.system 1..1 MS +* category.coding.system = "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-category" +* category.coding.code 1..1 MS + +* subject 1..1 MS +* subject only Reference(Patient) + +* encounter MS +* encounter ^short = "Shall contain a reference to an Encounter resource with a episodeOfCare-identifier, if the identifier is included in a previous message." + +* topic 0..1 MS +* topic ^short = "Must be added when category is \"other\". Topic must be added in the text-element." +* topic.text 1..1 MS +* topic.text ^short = "Plain text representation of the concept." +* topic.text ^definition = "The topic must be present." + +* priority MS +* priority ^short = "Only used when the category is 'regarding referral', see priority-category-invariant." +* priority only code +* priority from http://ehealth.sundhed.dk/vs/ehealth-carecommunication-priority (required) + +* extension contains ehealth-carecommunication-sender named sender 0..1 MS + +* extension contains ehealth-carecommunication-destination named destination 1..1 MS + +* extension contains ehealth-carecommunication-origin named origin 1..1 MS + +* extension contains ehealth-carecommunication-message-Type named messageType 1..1 MS + +* recipient 0..1 +* recipient only Reference(CareTeam or PractitionerRole) +* recipient MS +* recipient ^short = "The recieving actor of the message" + +* inResponseTo 0..1 MS +* inResponseTo ^short = "references the Ehealth-CareCommunication Communication.id, which this message is a response to." + +* sender 0..0 + +* basedOn 0..0 + +* partOf 0..0 + +* extension contains ehealth-administrative-status named administrativeStatus 1..1 + +* payload 1..* +* payload ^slicing.discriminator.type = #type +* payload ^slicing.discriminator.path = "$this.content" +* payload ^slicing.rules = #open +* payload contains string 1..* and attachment 0..* + +* payload[string].contentString 1..1 MS +* payload[string].extension contains + ehealth-carecommunication-datetime named date 1..1 MS and + ehealth-carecommunication-payload-identifier named identifier 1..1 MS + +* payload[attachment].content[x] only Attachment +* payload[attachment].contentAttachment 1..1 MS +* payload[attachment].extension contains + ehealth-carecommunication-datetime named date 1..1 MS and + ehealth-carecommunication-payload-identifier named identifier 1..1 MS +* payload[attachment].contentAttachment.contentType MS +* payload[attachment].contentAttachment.contentType ^short = "The content type shall be present when the content is an attachment included in the data element." +* payload[attachment].contentAttachment.contentType from http://ehealth.sundhed.dk/vs/ehealth-carecommunication-mimetypes (required) +* payload[attachment].contentAttachment.data MS +* payload[attachment].contentAttachment.data ^short = "Shall be present and contain the base64 encoded content of the attachment." +* payload[attachment].contentAttachment.url MS +* payload[attachment].contentAttachment.url ^short = "Shall be present if the attachment is a link to a web page." +* payload[attachment].contentAttachment.title 1.. MS +* payload[attachment].contentAttachment.title ^short = "Note: it is not allowed for the system to automatically include '.filetype' in the title." +* payload[attachment].contentAttachment.creation MS +* payload[attachment].contentAttachment.creation ^short = "The time the attachment was created" + +// Extensions + +Extension: ehealth-carecommunication-sender +Id: ehealth-carecommunication-sender +Title: "Sender Extension, contains the sending PractitionerRole, Practitioner and CareTeam." +Description: "References the sending PractitionerRole (Actor), the Practitioner, and optionally a CareTeam." +* extension contains + actor 1..1 MS and + practitioner 1..1 MS and + contactPoint 0..1 MS and + careTeam 0..1 MS +* extension[actor] ^short = "Sending PractitionerRole" +* extension[actor].value[x] only Reference(PractitionerRole) +* extension[practitioner] ^short = "The underlying Practitioner for this sender" +* extension[practitioner].value[x] only Reference(Practitioner) +* extension[careTeam] ^short = "Optionally, the involved CareTeam" +* extension[careTeam].value[x] only Reference(CareTeam) +* extension[contactPoint] ^short = "Optional contactpoint for the sender" +* extension[contactPoint].value[x] only ContactPoint + +Extension: ehealth-carecommunication-destination +Id: ehealth-carecommunication-destination +Title: "Destination Extension" +Description: "Reference to the destination Organization for this communication." +* . ^short = "Organization receiving the message" +* value[x] only Reference(Organization) + +Extension: ehealth-carecommunication-datetime +Title: "DateTime Extension" +Description: "Date and time of the payload segment." +* . ^short = "Payload dateTime" +* value[x] only dateTime + +Extension: ehealth-carecommunication-payload-identifier +Title: "Identifier Extension" +Description: "Extension to hold an Identifier for a payload. Identifier.value shall be a UUID v4 in URN form (urn:uuid:)." +* value[x] only Identifier +* valueIdentifier 1..1 + +Extension: ehealth-carecommunication-origin +Title: "sender organization" +Description: "Reference to the sending organization for this payload segment." +* . ^short = "Reference to the sending organization of the message" +* value[x] only Reference(Organization) + +Extension: ehealth-carecommunication-message-Type +Title: "Message type" +Description: "The type of the message. If inResponseTo is present, the type can not be new-message." +* value[x] only Coding +* valueCoding from MessageType (required) +* . ^short = "Message type" + +// Valuesets + +ValueSet: MessageType +Title: "Message Type ValueSet" +Description: "Allowed message types: new-message, reply-message, forward-message." +* ^url = "http://ehealth.sundhed.dk/vs/ehealth-carecommunication-message-type" +* ^compose.include.system = "http://ehealth.sundhed.dk/cs/message-type" +* ^compose.include.concept[+].code = #new-message +* ^compose.include.concept[=].display = "New Message" +* ^compose.include.concept[+].code = #reply-message +* ^compose.include.concept[=].display = "Reply Message" +* ^compose.include.concept[+].code = #forward-message +* ^compose.include.concept[=].display = "Forward Message" + +ValueSet: EhealthCareCommunicationCategoryVS +Id: ehealth-carecommunication-category +Title: "eHealth CareCommunication Categories" +* ^url = "http://ehealth.sundhed.dk/vs/ehealth-carecommunication-category" +* ^status = #active +* ^description = "Categories used for CareCommunciation messages." +* ^compose.include.system = "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-category" + +ValueSet: EhealthCareCommunicationMimeTypesVS +Id: ehealth-carecommunication-mimetypes +Title: "eHealth CareCommunication Attachment MIME Types" +Description: "Allowed MIME types for attachments in eHealth CareCommunication messages. Mirrors MedCom's medcom-core-attachmentMimeTypes ValueSet." +* ^url = "http://ehealth.sundhed.dk/vs/ehealth-carecommunication-mimetypes" +* ^status = #active +* ^compose.include.system = "urn:ietf:bcp:13" +* ^compose.include.concept[+].code = #application/pdf +* ^compose.include.concept[=].display = "application/pdf" +* ^compose.include.concept[+].code = #image/gif +* ^compose.include.concept[=].display = "image/gif" +* ^compose.include.concept[+].code = #image/jpeg +* ^compose.include.concept[=].display = "image/jpeg" +* ^compose.include.concept[+].code = #image/png +* ^compose.include.concept[=].display = "image/png" +* ^compose.include.concept[+].code = #image/tiff +* ^compose.include.concept[=].display = "image/tiff" +* ^compose.include.concept[+].code = #image/bmp +* ^compose.include.concept[=].display = "image/bmp" + +ValueSet: EhealthCareCommunicationPriorityVS +Id: ehealth-carecommunication-priority +Title: "eHealth CareCommunication Priorities" +* ^url = "http://ehealth.sundhed.dk/vs/ehealth-carecommunication-priority" +* ^status = #active +* ^description = "Priorities used for CareCommunication messages." +* ^compose.include.system = "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-priority" + + +// CodeSystems + +CodeSystem: MessageTypeCS +Title: "Message Type CodeSystem" +Description: "Allowed codes for message type." +* ^url = "http://ehealth.sundhed.dk/cs/message-type" +* #new-message "New Message" +* #reply-message "Reply" +* #forward-message "Forward" + +CodeSystem: EhealthCareCommunicationCategoryCS +Id: ehealth-carecommunication-category +Title: "eHealth CareCommunication Category codes" +Description: "The set of CareCommunication category code." +* ^url = "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-category" +* #alcohol-and-drug-treatment "Alcohol and drug treatment" +* #assistive-devices "Assistive technology" +* #carecoordination "Care Coordination" +* #decease "Decease" +* #discharge "Discharge" +* #examination-results "Examination Results" +* #healthcare "Healthcare" +* #home-care-assessment "Home care assessment" +* #medicine "Medicine" +* #nursing "Nursing" +* #outpatient "Outpatient" +* #psychiatry-social-disability "Psychiatry, Social, Disability" +* #regarding-referral "Regarding Referral" +* #telemedicine "Telemedicine" +* #training "Training" +* #acute-ambulant "Acute ambulant" +* #extended-care-responsibility "Extended care responsibility" +* #other "Other" + +CodeSystem: EhealthCareCommunicationPriorityCS +Id: ehealth-carecommunication-priority +Title: "eHealth CareCommunication Priority codes" +Description: "The set of CareCommunication priority code." +* ^url = "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-priority" +* #routine "Routine" +* #asap "ASAP" + + + + +// Invariants + +Invariant: stopped-status-statusReason +Description: "If status is 'stopped', statusReason must be either 'system-error' or 'recipient-unavailable'." +Expression: "status != 'stopped' or statusReason.coding.where(code = 'system-error' or code = 'recipient-unavailable').exists()" +Severity: #error + +Invariant: only-asap-or-routine +Description: "priority must be either 'asap' or 'routine'" +Expression: "priority.empty() or priority = 'asap' or priority = 'routine'" +Severity: #error + +Invariant: topic-required-when-category-other +Description: "topic must be present when category is 'other'." +Expression: "iif(category.coding.code != 'other', true, category.coding.code = 'other' and topic.exists())" +Severity: #error + +Invariant: priority-category-invariant +Description: "Priority must not be present when category is not 'regarding-referral'." +Expression: "category.coding.code = 'regarding-referral' or priority.empty()" +Severity: #error + +Invariant: uuidv4 +Description: "identifier.value SHALL be a valid UUID v4 in URN form (urn:uuid:)" +Expression: "value.matches('^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$')" +Severity: #error + +Invariant: atLeastOnePayloadString +Description: "At least one payload segment shall have a message text (payload.contentString)" +Expression: "payload.contentString.exists()" +Severity: #error + +Invariant: payloadAttachment-contentType-required +Description: "contentType SHALL be present if data or url is present in Attachment" +Expression: "payload.contentAttachment.data.exists() or payload.contentAttachment.url.exists() implies payload.contentAttachment.contentType.exists()" +Severity: #error + +Invariant: no-standard-sender +Description: "The standard Communication.sender element SHALL NOT be used. Use the ehealth-carecommunication-sender extension instead." +Expression: "sender.empty()" +Severity: #error + +Invariant: reply-requires-inResponseTo +Description: "If messageType is 'reply-message', inResponseTo SHALL be populated." +Expression: "extension('http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-carecommunication-message-Type').value.where(code = 'reply-message').exists() implies inResponseTo.exists()" +Severity: #error + +Invariant: sender-required-based-on-messagetype +Description: """ +If messagetype is 'new' or 'reply', the sender extension must be present. +If 'forward', sender may be absent. +""" +Expression: "extension('http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-carecommunication-message-Type').value.where(code = 'new-message' or code = 'reply-message').exists() implies extension('http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-carecommunication-sender').exists()" +Severity: #error \ No newline at end of file diff --git a/input/fsh/ehealth-media.fsh b/input/fsh/ehealth-media.fsh index 4b6442bd..3fb9bd6a 100644 --- a/input/fsh/ehealth-media.fsh +++ b/input/fsh/ehealth-media.fsh @@ -19,7 +19,7 @@ Parent: Media * subject ^type.aggregation = #referenced * subject.reference 1..1 * created[x] 1..1 -* operator only Reference(ehealth-practitioner) +* operator only Reference(ehealth-practitioner or ehealth-patient or ehealth-relatedperson) * operator ^type.aggregation = #referenced * device only Reference(ehealth-device or ehealth-devicemetric) * device ^type.aggregation = #referenced diff --git a/input/fsh/ehealth-patient.fsh b/input/fsh/ehealth-patient.fsh index fc2d3b26..6a0c97db 100644 --- a/input/fsh/ehealth-patient.fsh +++ b/input/fsh/ehealth-patient.fsh @@ -31,6 +31,8 @@ Parent: DkCorePatient * telecom[eBoks].rank 0..0 * identifier[cpr] 1..1 +* identifier[x-ecpr] 0..0 +* identifier[d-ecpr] 0..0 * gender 1..1 * contact.extension contains ehealth-patient-contactnote named patientContactnote 0..* diff --git a/input/fsh/ehealth-relatedperson.fsh b/input/fsh/ehealth-relatedperson.fsh index 5be02dc9..3a0caa31 100644 --- a/input/fsh/ehealth-relatedperson.fsh +++ b/input/fsh/ehealth-relatedperson.fsh @@ -12,7 +12,7 @@ Parent: RelatedPerson * patient only Reference(ehealth-patient) * patient ^type.aggregation = #referenced -* relationship.coding from http://ehealth.sundhed.dk/vs/relatedperson-relationshiptype +* relationship.coding from http://ehealth.sundhed.dk/vs/relatedperson-relationshiptype (extensible) * name 1..* Instance: relatedperson01 diff --git a/input/intro-notes/StructureDefinition-ehealth-carecommunication-intro.md b/input/intro-notes/StructureDefinition-ehealth-carecommunication-intro.md new file mode 100644 index 00000000..7db8e2c4 --- /dev/null +++ b/input/intro-notes/StructureDefinition-ehealth-carecommunication-intro.md @@ -0,0 +1,58 @@ +# Introduction + +An Ehealth-CareCommunication is an FUT abstraction of a MedCom CareCommunication. +This is needed to support communication through the VANS network with parties outside the FUT infrastructure, as well as inside FUT. +The Ehealth-CareCommunication's primary feature is to enable communication in relation to several images of different file types. + +# Remarks about status and administrative-status + +- __status__: + - A message is considered "not yet sent" when it has one of the following status and can freely transition from one to another: 'preparation', 'on-hold', 'not-done', 'entered-in-error' + - A message is considered "being sent" when created or patched into status 'in-progress' and cannot be patched further or deleted by the sender + - The server will automatically transition a message from 'in-progress' to 'completed' when it has been sent successfully (happens when the Vans-Relay has received a positive acknowledgement on the send message) + - The server will automatically transition a message from 'in-progress' to 'stopped' if it could not be sent (happens when the Vans-Relay has received a negative acknowledgement on the send message, or at 3 failed attempts at sending) + - The client can never create or patch a message into status 'completed' or 'stopped' + - The sender cannot patch, only delete messages with status 'stopped' + - The sender cannot patch or delete messages with status 'completed' + - The recipient can patch /received and administrative-status on messages with status 'completed' + +- __administrative-status__ (extension): Makes it possible for the message __recipient__ to indicate the state of a message. A message may hold an administrative status that defines the last action the recipient took on the message in question. At first, the message has administrative-status "activate". The recipient may mark the message as read by setting administrative-status "read". If the recipient considers the message a sort of "task", the message may also be updated with + administrative-status "complete" when the task is done, or "reactivate" if the task was not complete anyway. + +# Scope and Usage + +In the eHealth Infrastructure the ehealth-CareCommunication resource is used in conjunction with the +following resources: + +- Patient + - As a subject of a message + +- PractitionerRole + - As specific sender/recipient of a message + +- Practitioner + - the Practitioner of the PractitionerRole + +- CareTeam + - as specific sender/recipient of a message + +- Organization + - as sender/recipient of a message + +__note on sender__: The sender of a message is structured as a complex extension, +holding a reference to the sending PractitionerRole, the linked Practitioner and optional +CareTeam. If a CareTeam is present, that CareTeam is considered the specific sender, +not the PractitionerRole. PractitionerRole is still required, since every message has to +have a PractitionerRole representing that message. + +# General rules + +- The sender/receiver Organizations have to have both a SOR and GLN (EAN) identifier to be eligible for VANS communication. +- If the message type is Forward, you as a sender have to pick which payloads should be included in the message. +- If the message type is Reply, the message will be populated automatically with all prior payloads of the given conversation. +- The Communication identifier is the same for all Ehealth-CareCommunications of the same conversation. A new Communication Id is needed for a Forward message type, even though bundles from a prior conversation are included. +- The MessageHeader identifier is set for received messages, as client-side assignment of id's is not possible. For messages sent from the FUT infrastructure, it is not needed. +The reasoning for the use of this identifier is that the correlating MedCom model for Ehealth-CareCommunications identifies specific messages based on the MessageHeader identifier. +- inResponseTo has to be included for Reply messages. It points to the previous MessageHeader identifier in the conversation if present, otherwise Ehealth-CareCommunication.id. +- If category is other, the topic.text element has to be populated. +- recipient can be excluded, which means the message is considered sent to the destination organization. \ No newline at end of file diff --git a/input/pagecontent/changelog.md b/input/pagecontent/changelog.md index f59eb97d..344fcbc8 100644 --- a/input/pagecontent/changelog.md +++ b/input/pagecontent/changelog.md @@ -1,5 +1,39 @@ This is the log of changes made to the eHealth Implementation Guide. +## Release 2026.3. todo: change to semver format before release +### General changes +- Updated ehealth-media to allow patient and relatedPerson references in it's operator field. +### Custom operations +#### System operations +#### Instance operations +### Code systems +- Re-added `http://ehealth.sundhed.dk/cs/poa-privilege` (Power of Attorney Privilege) CodeSystem. Content is `not-present` — codes are vendor-specific and externally governed. +### ValueSets +- Re-added `http://ehealth.sundhed.dk/cs/poa-privilege` as an include in `http://ehealth.sundhed.dk/vs/relatedperson-relationshiptype`. +### ConceptMaps +### Resource/profile changes +- Updated ehealth-media to allow patient and relatedPerson references in it's operator field. +- Excluded inherited `x-ecpr` and `d-ecpr` identifier slices from `ehealth-patient`. These slices were added on `DkCorePatient` in dk-core 3.x and flowed into `ehealth-patient` silently; FUT does not support electronic CPR identifiers, so both are now constrained to `0..0`. Real CPR identifiers (`identifier[cpr]`, system `urn:oid:1.2.208.176.1.2`) are unaffected. + +### Event messages +- Tightened the `EHealthApplicationEvent` JSON schema (CCR0303 AC-7): the schema is now declared as JSON Schema draft-07; `eventType` and `resourceReference` are top-level required; `resourceReference` requires `minItems: 1` with each entry requiring both `label` and `reference`; and per-`eventType` `if`/`then`/`contains` rules assert the obligatory `resourceReference.label`. **Note for vendors:** producers must now emit both `label` and `reference` on every `resourceReference` entry and include the `eventType`-specific obligatory label. + +## 9.0.2-SNAPSHOT (2026-05-04) +### Code systems +- Added http://ehealth.sundhed.dk/cs/ehealth-carecommunication-category for CareCommunication category codes. +- Added http://ehealth.sundhed.dk/cs/ehealth-carecommunication-priority for CareCommunication priority codes. +- Added http://ehealth.sundhed.dk/cs/message-type for CareCommunication message types (new-message, reply-message, forward-message). +### ValueSets +- Added http://ehealth.sundhed.dk/vs/ehealth-carecommunication-category. +- Added http://ehealth.sundhed.dk/vs/ehealth-carecommunication-priority. +- Added http://ehealth.sundhed.dk/vs/ehealth-carecommunication-mimetypes for allowed CareCommunication attachment MIME types. +- Added MessageType ValueSet for CareCommunication message types. +### ConceptMaps +- Added ConceptMap CareCommunication-Priority mapping CareCommunication priorities to MedCom equivalents. +- Added ConceptMap CareCommunucation-Category mapping CareCommunication categories to MedCom equivalents. +### Resource/profile changes +- Added new `ehealth-carecommunication` Communication profile with extensions for sender (PractitionerRole, Practitioner, optional CareTeam and ContactPoint), destination Organization, origin Organization, payload datetime, payload identifier, and message type. + ## 9.0.1 (2026-05-05) ### ValueSets - Removed http://ehealth.sundhed.dk/cs/poa-privilege CodeSystem and http://ehealth.sundhed.dk/vs/relatedperson-relationshiptype ValueSet include of the CodeSystem, since they were causing some issues during release, and are not strictly needed until 2026.3. @@ -605,7 +639,8 @@ This is the log of changes made to the eHealth Implementation Guide. ## 2.7.0 (2023-03-29) ### General changes -- Changed the description in section "Automatic NemSMS Notifications" for Ehealth-message. This is related to "CCR0167 Ingen automatisk NemSMS for ehealth-message med kategori message" from Release 13. +- Changed the description in section "Automatic NemSMS Notifications" for Ehealth-message. This is related to "CCR0167 Ingen automatisk NemSMS for ehealth-message med kategori message" from +13. - Changed the descriptions of ehealth-message category to reflect CCR0154 changes. ### Custom operations #### System operations diff --git a/input/pagecontent/event-messages.md b/input/pagecontent/event-messages.md index dcd056fa..2b7d26e2 100644 --- a/input/pagecontent/event-messages.md +++ b/input/pagecontent/event-messages.md @@ -133,8 +133,10 @@ topic: `ehealth-application-event` ``` { + "$schema" : "http://json-schema.org/draft-07/schema#", "type" : "object", "id" : "urn:jsonschema:dk:sundhed:ehealth:event:models:EHealthApplicationEvent", + "required" : [ "eventType", "resourceReference" ], "properties" : { "messageType" : { "type" : "string", @@ -162,9 +164,11 @@ topic: `ehealth-application-event` }, "resourceReference" : { "type" : "array", - "description" : "References to related resources", + "minItems" : 1, + "description" : "References to related resources. At least one entry is required; the obligatory label per eventType is listed in the Event Types table below.", "items" : { "type" : "object", + "required" : [ "label", "reference" ], "properties" : { "label" : { "type" : "string", @@ -177,7 +181,19 @@ topic: `ehealth-application-event` } } } - } + }, + "allOf" : [ + { "if" : { "required" : [ "eventType" ], "properties" : { "eventType" : { "const" : "AppointmentReminder" } } }, + "then" : { "properties" : { "resourceReference" : { "contains" : { "properties" : { "label" : { "const" : "Appointment" } } } } } } }, + { "if" : { "required" : [ "eventType" ], "properties" : { "eventType" : { "const" : "VideoAppointmentReminder" } } }, + "then" : { "properties" : { "resourceReference" : { "contains" : { "properties" : { "label" : { "const" : "Appointment" } } } } } } }, + { "if" : { "required" : [ "eventType" ], "properties" : { "eventType" : { "const" : "ReminderSubmitMeasurement" } } }, + "then" : { "properties" : { "resourceReference" : { "contains" : { "properties" : { "label" : { "const" : "ServiceRequest" } } } } } } }, + { "if" : { "required" : [ "eventType" ], "properties" : { "eventType" : { "const" : "MissingMeasurement" } } }, + "then" : { "properties" : { "resourceReference" : { "contains" : { "properties" : { "label" : { "const" : "ServiceRequest" } } } } } } }, + { "if" : { "required" : [ "eventType" ], "properties" : { "eventType" : { "const" : "NewEHealthMessage" } } }, + "then" : { "properties" : { "resourceReference" : { "contains" : { "properties" : { "label" : { "const" : "EhealthMessage" } } } } } } } + ] } ``` ##### Properties @@ -187,11 +203,13 @@ topic: `ehealth-application-event` - `messageVersion`: The version of the message type, eg. "1.0" - `payload`: Notification text content from the CommunicationRequest - `userReference`: The reference (absolute URL) of the Patient resource representing the citizen -- `resourceReference`: Array of references to related resources, each with a `label` (resource type) and `reference` (absolute URL) +- `resourceReference`: Non-empty array of references to related resources. Each entry has a `label` (resource type) and `reference` (absolute URL). The obligatory entries per `eventType` are listed in the Event Types table. ##### Event Types -| eventType | Description | resourceReference label | Source | +Each `eventType` guarantees at least one `resourceReference` entry with the indicated `label`. This is enforced by the JSON schema's `allOf` / `if`-`then` / `contains` block above. + +| eventType | Description | Obligatory resourceReference label | Source | |---|---|---|---| | AppointmentReminder | Appointment reminder | Appointment | fut-appointment-notification-job | | VideoAppointmentReminder | Video appointment reminder | Appointment | fut-appointment-notification-job | diff --git a/input/resources/CapabilityStatement-patient.json b/input/resources/CapabilityStatement-patient.json index fbeefb64..98386ec9 100644 --- a/input/resources/CapabilityStatement-patient.json +++ b/input/resources/CapabilityStatement-patient.json @@ -751,7 +751,8 @@ "supportedProfile": [ "http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-communication", "http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-material-communication", - "http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-message" + "http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-message", + "http://ehealth.sundhed.dk/fhir/StructureDefinition/ehealth-carecommunication" ], "interaction": [ { diff --git a/input/resources/CodeSystem-ehealth-poa-privilege.json b/input/resources/CodeSystem-ehealth-poa-privilege.json new file mode 100644 index 00000000..2937ee4a --- /dev/null +++ b/input/resources/CodeSystem-ehealth-poa-privilege.json @@ -0,0 +1,25 @@ +{ + "resourceType": "CodeSystem", + "id": "ehealth-poa-privilege", + "url": "http://ehealth.sundhed.dk/cs/poa-privilege", + "version": "0.0.1", + "name": "PoAPrivilege", + "title": "Power of Attorney Privilege", + "status": "active", + "experimental": false, + "date": "2026-03-24T00:00:00+00:00", + "publisher": "ehealth.sundhed.dk", + "contact": [ + { + "telecom": [ + { + "system": "url", + "value": "http://ehealth.sundhed.dk/terminology" + } + ] + } + ], + "description": "Vendor-specific power of attorney privilege codes used by Keycloak when creating RelatedPerson resources for PoA-authenticated citizens. The full set of codes is externally governed and not enumerated here.", + "caseSensitive": true, + "content": "not-present" +} diff --git a/input/resources/ConceptMap-CareCommunication-Priority.json b/input/resources/ConceptMap-CareCommunication-Priority.json new file mode 100644 index 00000000..31d46f98 --- /dev/null +++ b/input/resources/ConceptMap-CareCommunication-Priority.json @@ -0,0 +1,36 @@ +{ + "resourceType": "ConceptMap", + "id": "ehealth-to-medcom-carecommunication-priority", + "url": "http://ehealth.sundhed.dk/cm/ehealth-to-medcom-carecommunication-priority", + "version": "1.0.0", + "status": "active", + "title": "eHealth to MedCom CareCommunication Priority Map", + "group": [ + { + "source": "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-priority", + "target": "http://medcomfhir.dk/ig/terminology/ValueSet/medcom-careCommunication-requestPriority", + "element": [ + { + "code": "routine", + "target": [ + { + "code": "routine", + "display": "Routine", + "relationship": "equivalent" + } + ] + }, + { + "code": "asap", + "target": [ + { + "code": "asap", + "display": "ASAP", + "relationship": "equivalent" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/resources/ConceptMap-CareCommunucation-Category.json b/input/resources/ConceptMap-CareCommunucation-Category.json new file mode 100644 index 00000000..a71865a7 --- /dev/null +++ b/input/resources/ConceptMap-CareCommunucation-Category.json @@ -0,0 +1,196 @@ +{ + "resourceType": "ConceptMap", + "id": "ehealth-to-medcom-carecommunication-category", + "url": "http://ehealth.sundhed.dk/cm/ehealth-to-medcom-carecommunication-category", + "version": "1.0.0", + "status": "active", + "title": "eHealth to MedCom CareCommunication Category Map", + "group": [ + { + "source": "http://ehealth.sundhed.dk/cs/ehealth-carecommunication-category", + "target": "http://medcomfhir.dk/ig/terminology/ValueSet/medcom-careCommunication-categories", + "element": [ + { + "code": "alcohol-and-drug-treatment", + "target": [ + { + "code": "alcohol-and-drug-treatment", + "display": "Alcohol and drug treatment", + "relationship": "equivalent" + } + ] + }, + { + "code": "assistive-devices", + "target": [ + { + "code": "assistive-devices", + "display": "Assistive technology", + "relationship": "equivalent" + } + ] + }, + { + "code": "carecoordination", + "target": [ + { + "code": "carecoordination", + "display": "Care Coordination", + "relationship": "equivalent" + } + ] + }, + { + "code": "decease", + "target": [ + { + "code": "decease", + "display": "Decease", + "relationship": "equivalent" + } + ] + }, + { + "code": "discharge", + "target": [ + { + "code": "discharge", + "display": "Discharge", + "relationship": "equivalent" + } + ] + }, + { + "code": "examination-results", + "target": [ + { + "code": "examination-results", + "display": "Examination Results", + "relationship": "equivalent" + } + ] + }, + { + "code": "healthcare", + "target": [ + { + "code": "healthcare", + "display": "Healthcare", + "relationship": "equivalent" + } + ] + }, + { + "code": "home-care-assessment", + "target": [ + { + "code": "home-care-assessment", + "display": "Home care assessment", + "relationship": "equivalent" + } + ] + }, + { + "code": "medicine", + "target": [ + { + "code": "medicine", + "display": "Medicine", + "relationship": "equivalent" + } + ] + }, + { + "code": "nursing", + "target": [ + { + "code": "nursing", + "display": "Nursing", + "relationship": "equivalent" + } + ] + }, + { + "code": "outpatient", + "target": [ + { + "code": "outpatient", + "display": "Outpatient", + "relationship": "equivalent" + } + ] + }, + { + "code": "psychiatry-social-disability", + "target": [ + { + "code": "psychiatry-social-disability", + "display": "Psychiatry, Social, Disability", + "relationship": "equivalent" + } + ] + }, + { + "code": "regarding-referral", + "target": [ + { + "code": "regarding-referral", + "display": "Regarding Referral", + "relationship": "equivalent" + } + ] + }, + { + "code": "telemedicine", + "target": [ + { + "code": "telemedicine", + "display": "Telemedicine", + "relationship": "equivalent" + } + ] + }, + { + "code": "training", + "target": [ + { + "code": "training", + "display": "Training", + "relationship": "equivalent" + } + ] + }, + { + "code": "acute-ambulant", + "target": [ + { + "code": "acute-ambulant", + "display": "Acute ambulant", + "relationship": "equivalent" + } + ] + }, + { + "code": "extended-care-responsibility", + "target": [ + { + "code": "extended-care-responsibility", + "display": "Extended care responsibility", + "relationship": "equivalent" + } + ] + }, + { + "code": "other", + "target": [ + { + "code": "other", + "display": "Other", + "relationship": "equivalent" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/resources/ValueSet-ehealth-relatedperson-relationshiptype.json b/input/resources/ValueSet-ehealth-relatedperson-relationshiptype.json index b1224550..93cb9a2a 100644 --- a/input/resources/ValueSet-ehealth-relatedperson-relationshiptype.json +++ b/input/resources/ValueSet-ehealth-relatedperson-relationshiptype.json @@ -24,7 +24,8 @@ { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "O", "display": "Operator Proficiency" }, { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "CHILD", "display": "child" }, { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "SPS", "display": "spouse" }, - { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "POWATT", "display": "power of attorney" } + { "system": "http://terminology.hl7.org/CodeSystem/v3-RoleCode", "code": "POWATT", "display": "power of attorney" }, + { "system": "http://ehealth.sundhed.dk/cs/poa-privilege", "abstract": true, "display": "Vendor-specific PoA privilege codes (externally governed, not enumerated)" } ] }, "compose": { @@ -72,6 +73,9 @@ "code": "POWATT" } ] + }, + { + "system": "http://ehealth.sundhed.dk/cs/poa-privilege" } ] } diff --git a/sushi-config.yaml b/sushi-config.yaml index cb799284..c29f40f8 100644 --- a/sushi-config.yaml +++ b/sushi-config.yaml @@ -7,7 +7,7 @@ canonical: http://ehealth.sundhed.dk/fhir name: eHealth Infrastructure title: eHealth Infrastructure status: active # draft | active | retired | unknown -version: 9.0.1 +version: 9.0.4-SNAPSHOT fhirVersion: 4.0.1 copyrightYear: 2021+ diff --git a/sushi.sh b/sushi.sh new file mode 100644 index 00000000..85a3f160 --- /dev/null +++ b/sushi.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# Runs SUSHI and filters out known-safe naming warnings for ehealth-* slice names. +# Use 'npx sushi' directly if you want unfiltered output. +FORCE_COLOR=1 npx sushi "$@" 2>&1 | sed '/Valid names start with an upper-case ASCII letter/{N;N;d}' \ No newline at end of file