Merge d293672220 into e9f0f31d27
commit
a4a5b49d9c
@ -0,0 +1,185 @@
|
||||
# MSC4302: Exchanging FHIR resources via Matrix events
|
||||
|
||||
## A brief abstract of FHIR, resources and profiles
|
||||
|
||||
[FHIR] (pronounced "fire") is a globally established standard for the digital exchange of
|
||||
healthcare-related information. The base building block of FHIR are so-called *resources*. Resources
|
||||
have a type that defines their base schema. This schema can be further customised through one or
|
||||
more *profiles*.
|
||||
|
||||
As an example, [`Questionnaire`] is the resource type for generic medical forms. This type defines
|
||||
several fields such as an *optional* `title` property containing a human readable name for the form.
|
||||
[`ISiKFormularDefinition`], in turn, is a profile on `Questionnaire` created by Germany's national
|
||||
health agency, gematik, for use within hospitals. It customises the schema of `Questionnaire` in
|
||||
several ways, such as making `title` required rather than optional.
|
||||
|
||||
Profiles can extend either resource types or other profiles, meaning it is possible to build chains
|
||||
of profiles. Both resource types and profiles are described via [`StructureDefinition`]s which are
|
||||
uniquely identified by their [canonical URL].
|
||||
|
||||
``` json5
|
||||
{
|
||||
// This is the profile ISiKFormularDefinition v5.0.0, created by gematik GmbH
|
||||
"resourceType": "StructureDefinition",
|
||||
"id": "ISiKFormularDefinition",
|
||||
"url": "https://gematik.de/fhir/isik/StructureDefinition/ISiKFormularDefinition",
|
||||
"version": "5.0.0",
|
||||
"publisher": "gematik GmbH",
|
||||
// It extends the base type Questionnaire from FHIR v4.0.1
|
||||
"type": "Questionnaire",
|
||||
"fhirVersion": "4.0.1",
|
||||
// It is based directly on the base type without intermediary profiles
|
||||
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Questionnaire",
|
||||
// It changes the base type, among others, by making the title field mandatory
|
||||
"differential": {
|
||||
"element": [{
|
||||
"id": "Questionnaire.title",
|
||||
"min": 1,
|
||||
"mustSupport": true,
|
||||
...
|
||||
}, ...]},
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
While the above example is trivial, the customisations achievable via profiling can be extensive. As
|
||||
a result, it is crucial for implementations to understand what profiles are being used when
|
||||
exchanging data.
|
||||
|
||||
## The problems of using FHIR resources in Matrix
|
||||
|
||||
FHIR resources can be serialised into JSON or XML which can be transmitted via the [`m.file`]
|
||||
message type with a MIME type of `application/fhir+json` or `application/fhir+xml`. However, the
|
||||
generic MIME type doesn't let clients understand what resource is contained in the file without
|
||||
downloading it. This is suboptimal because clients may want to apply special display logic for
|
||||
certain resource types and profiles. Using the example of `Questionnaire`s, clients may want to
|
||||
render the resource as an interactive form for the user to fill out and send back a
|
||||
[`QuestionnaireResponse`] resource.
|
||||
|
||||
Similarly, clients that connect external systems to Matrix may want to automatically process certain
|
||||
resources. For instance, an anamnesis bot may want to export received `QuestionnaireResponse`s into
|
||||
a hospital's patient management system. Again, the generic MIME type forces such a client to
|
||||
download the file to determine if it is indeed a `QuestionnaireResponse`.
|
||||
|
||||
These problems would be mitigated to some extent if FHIR resources were inlined into Matrix events.
|
||||
However, serialized resources contain only limited information about the underlying
|
||||
`StructureDefinition`. Most importantly the base resource type is missing, making it difficult for
|
||||
implementations that support a base type but not a specific profile to fall back in a reasonable
|
||||
way. Furthermore, inlining isn't always possible due to the [64 KiB event size limit] and no
|
||||
suitable event type or content block exists, as of writing.
|
||||
|
||||
## Proposal
|
||||
|
||||
To enable the compatible and efficient exchange of FHIR resources in either inline or file form, a
|
||||
new event type `m.fhir` is introduced. This type mandates the following properties in `content`:
|
||||
|
||||
- `m.fhir.structure_definition` (object, required): Information about the resource's
|
||||
`StructureDefinition`.
|
||||
- `url` (string, required): The [canonical URL] of the most specific `StructureDefinition`
|
||||
describing the resource. This is equivalent to [`StructureDefinition.url`].
|
||||
- `version` (string, required): The version of the `StructureDefinition`. This is equivalent to
|
||||
[`StructureDefinition.version`].
|
||||
- `type` (string, required): The `StructureDefinition`'s base type. This is equivalent to
|
||||
[`StructureDefinition.type`].
|
||||
- `fhir_version` (string, required): The version of the FHIR specification on which the
|
||||
`StructureDefinition` is based. This is equivalent to [`StructureDefinition.fhirVersion`].
|
||||
- `m.fhir.resource` (object, required if `m.file` is missing): The serialised JSON if it fits within
|
||||
the [64 KiB event size limit].
|
||||
- `m.file` (object, required if `m.fhir.resource` is missing): An [MSC3551] content block describing
|
||||
an uploaded JSON or XML serialisation of the resource if it is too large to be inlined.
|
||||
|
||||
``` json5
|
||||
{
|
||||
"type": "m.fhir",
|
||||
"content": {
|
||||
// Metadata to help identify the resource
|
||||
"m.fhir.structure_definition": {
|
||||
"url": "https://gematik.de/fhir/isik/StructureDefinition/ISiKFormularDefinition",
|
||||
"version": "5.0.0",
|
||||
"type": "Questionnaire",
|
||||
"fhir_version": "4.0.1",
|
||||
},
|
||||
// Either: The resource in inline form
|
||||
"m.fhir.resource": {
|
||||
"resourceType": "Questionnaire",
|
||||
"title": "Dr. Dre's anamnesis questionnaire for new patients",
|
||||
// further properties as per the questionnaire's schema
|
||||
},
|
||||
// Or: A file representing the resource
|
||||
"m.file": {
|
||||
"url": "mxc://example.org/abcd1234",
|
||||
"mimetype": "application/fhir+json",
|
||||
// further properties as per MSC3551
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `url` and `version` properties, on the one hand, allow implementations with support for the
|
||||
particular profile to activate dedicated display or processing logic. The `type` and `fhir_version`
|
||||
properties, on the other hand, enable implementations *without* support for the specific profile to
|
||||
offer fallback behaviour if they have generic support for the resource's base type.
|
||||
|
||||
## Potential issues
|
||||
|
||||
FHIR includes generic resources such as [`Bundle`] which wrap other resources. The metadata in
|
||||
`m.fhir.structure_definition` will not help clients understand the wrapped content without
|
||||
downloading it in these cases. Dedicated event types or further metadata fields may be introduced in
|
||||
future to cater to these situations.
|
||||
|
||||
## Alternatives
|
||||
|
||||
Dedicated MIME types per resource, version and serialisation format could be introduced. Since FHIR
|
||||
supports a vast number of resources and profiles this doesn't appear practical, however.
|
||||
|
||||
[RFC 2045] allows MIME types to include modifying parameters. The contents of
|
||||
`m.fhir.structure_definition` could, therefore, be included alongside the media type[^1].
|
||||
|
||||
``` http
|
||||
Content-type: application/fhir+json; url="https://gematik.de/fhir/isik/StructureDefinition/ISiKFormularDefinition"; ...
|
||||
```
|
||||
|
||||
This would allow reusing the `m.file` message type but leaks metadata to the home server in
|
||||
[`POST /_matrix/media/v3/upload`].
|
||||
|
||||
## Security considerations
|
||||
|
||||
Malicious clients could attempt to trick other clients into automatically downloading files by
|
||||
faking the metadata in `m.fhir.structure_definition`. As a minimal defense, clients SHOULD
|
||||
sanity-check the size of the downloaded file by issuing a HEAD request and refuse to automatically
|
||||
download large files without explicit user consent.
|
||||
|
||||
## Unstable prefix
|
||||
|
||||
While this MSC is not considered stable, the following identifiers should be used:
|
||||
|
||||
- `m.fhir` → `de.gematik.msc4302.fhir`
|
||||
- `m.fhir.structure_definition` → `de.gematik.msc4302.fhir.structure_definition`
|
||||
- `m.fhir.resource` → `de.gematik.msc4302.fhir.resource`
|
||||
|
||||
Note that `m.file` has its own prefixing requirements as per [MSC3551].
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
[^1]: This could also be done by reusing the `profile` parameter from [RFC 6906]. Since the term
|
||||
"profile" already has a specific meaning within the FHIR standard, this could be confusing,
|
||||
however.
|
||||
|
||||
[FHIR]: https://hl7.org/fhir/
|
||||
[`Questionnaire`]: http://hl7.org/fhir/StructureDefinition/Questionnaire
|
||||
[`ISiKFormularDefinition`]: https://gematik.de/fhir/isik/StructureDefinition/ISiKFormularDefinition
|
||||
[`StructureDefinition`]: https://build.fhir.org/structuredefinition.html
|
||||
[canonical URL]: https://build.fhir.org/references.html#canonical
|
||||
[`m.file`]: https://spec.matrix.org/v1.14/client-server-api/#mfile
|
||||
[`QuestionnaireResponse`]: http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse
|
||||
[64 KiB event size limit]: https://spec.matrix.org/v1.16/client-server-api/#size-limits
|
||||
[`StructureDefinition.url`]: https://build.fhir.org/structuredefinition-definitions.html#StructureDefinition.url
|
||||
[`StructureDefinition.version`]: https://build.fhir.org/structuredefinition-definitions.html#StructureDefinition.version
|
||||
[`StructureDefinition.type`]: https://build.fhir.org/structuredefinition-definitions.html#StructureDefinition.type
|
||||
[`StructureDefinition.fhirVersion`]: https://build.fhir.org/structuredefinition-definitions.html#StructureDefinition.fhirVersion
|
||||
[MSC3551]: https://github.com/matrix-org/matrix-spec-proposals/pull/3551
|
||||
[`Bundle`]: http://hl7.org/fhir/StructureDefinition/Bundle
|
||||
[RFC 2045]: https://datatracker.ietf.org/doc/html/rfc2045#section-5
|
||||
[`POST /_matrix/media/v3/upload`]: https://spec.matrix.org/v1.14/client-server-api/#post_matrixmediav3upload
|
||||
[RFC 6906]: https://datatracker.ietf.org/doc/html/rfc6906
|
||||
Loading…
Reference in New Issue