FHIR Application Feature Framework Implementation Guide, published by HL7 International / FHIR Infrastructure. This guide is not an authorized publication; it is the continuous build for version 1.0.0-ballot built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/capstmt/ and changes regularly. See the Directory of published versions
Page standards status: Informative |
Welcome to the FHIR Application Feature Framework.
A Feature is a software behavior that applications may choose to implement, or be required to implement, where the existence (or not) of the behavior it describes changes the behavior of other actors in the ecosystem. Features may be software behaviors that are directly related to FHIR based interoperability, such as "forces version-aware updates on resources", or they may be more general - such as "passes a testing protocol" (potentially defined using a TestScript - or they may relate to the user interface/experience, such as "the interface complies to a [named national specification]".
There is no scope limitation to the kinds of things that Features might be be described, but the intent of features is that they relate to software behaviors that affect the other participants in the ecosystem of FHIR exchange.
Features are defined using FeatureDefinitions. This is a logical structure that looks a lot like a FHIR resource (and may become one in a future version of the FHIR specification). The important parts of the FeatureDefintion are:
The Application Feature Framework only defines one actual feature: FeatureSupport, which declares the most recent version of the feature framework that the application supports. This feature is used by applications to declare that they support the application feature framework at the root of their capability statement.
Note that applications can implement some of all of this specification without declaring that they support the application feature framework, but if they do declare that it is supported, they SHALL support the following functionality:
Features are declared in an extension. Each Feature is a pair: a code that identifies of which features is being described, and a value for that feature.
"extension" : [{
"url" : "http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature",
"extension" : [{
"url" : "definition",
"valueCanonical" : "http://hl7.org/fhir/uv/application-feature/FeatureDefinition/FeatureSupport"
},{
"url" : "value",
"valueCode" : "[[[$ver]]]"
}]
}]
or in xml:
<extension url="http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature">
<extension url="definition">
<valueCanonical value="http://hl7.org/fhir/uv/application-feature/FeatureDefinition/FeatureSupport"/>
</extension>
<extension url="value">
<valueCode value="[[[$ver]]]"/>
</extension>
</extension>
The feature extension can appear in any resource, on any element, but in practice, it's only allowed
to appear on the element contexts allowed in the Feature Definition. For example, the feature definition
for Feature says that it appears
on the root element of the CapabilityStatement resource (http://hl7.org/fhir/StructureDefinition/CapabilityStatement#CapabilityStatement
):
{
"resourceType" : "CapabilityStatement",
"id" : "something",
"extension" : [{
"url" : "http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature",
"extension" : [{
"url" : "definition",
"valueCanonical" : "http://hl7.org/fhir/uv/application-feature/FeatureDefinition/FeatureSupport"
},{
"url" : "value",
"valueCode" : "[[[$ver]]]"
}]
}]
or in xml:
<CapabilityStatement xmlns="http://hl7.org/fhir">
<id value="something"/>
<extension url="http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature">
<extension url="definition">
<valueCanonical value="http://hl7.org/fhir/uv/application-feature/FeatureDefinition/FeatureSupport"/>
</extension>
<extension url="value">
<valueCode value="[[[$ver]]]"/>
</extension>
</extension>
</CapabilityStatement>
Features defined inside the capability statement automatically have an implied scope, but are otherwise the same statement.
Here is an example of a feature defined for all resources available via REST:
<CapabilityStatement xmlns="http://hl7.org/fhir">
<rest>
<extension url="http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature">
<extension url="code">
<valueCanonical value="http://hl7.org/fhir/uv/application-feature/CodeSystem/feature-versioning"/>
</extension>
<extension url="value">
<valueCode value="versioned-update"/>
</extension>
</extension>
</rest>
</CapabilityStatement>
Here is the same feature only defined on CodeSystem:
<CapabilityStatement xmlns="http://hl7.org/fhir">
<rest>
<resource>
<type value="CodeSystem"/>
<extension url="http://hl7.org/fhir/uv/application-feature/StructureDefinition/feature">
<extension url="code">
<valueCanonical value="http://hl7.org/fhir/uv/application-feature/CodeSystem/feature-versioning"/>
</extension>
<extension url="value">
<valueCode value="versioned-update"/>
</extension>
</extension>
</resource>
</rest>
</CapabilityStatement>
Note, however, that the feature scopes are not restricted to the contexts implied by the structure of the FeatureCapabilityStatement profile. Feature contexts are defined for features that are deeper into the system than those defined by the FeatureCapabilityStatement profile.
In general, default CapabilityStatements returned from the /metadata
endpoint do not include
Feature assertions (other then possibly the FeatureFramework Feature itself), though specific features or
other implementation guides may require that features are populated in the CapabilityStatement by default.
For other CapabilityStatements - e.g. those produced to store in registries as static copies, it is at the
discretion of the application to decide how much to populate the CapabilityStatement with the applicable
features.
When an application fetches
up to here….
General Patterns
Responses
By default, when a client asks a server for it's capability statement using /metadata, which features to report on is at the discretion of the server. Typically, servers will not report any features by default. Features can be queried by search parameter or via an operation.
Features are identified by an expression that includes the scope in which the feature is being asserted. Here's some examples:
The full details of the expression format are described below.
Clients interacting with a FHIR server that supports this implementation guide SHOULD NOT download entire CapabilityStatement resources, since they may be many megabytes in size, instead use the $feature-query operation to determine if the server supports needed features.
General Patterns
Responses
By default, when a client asks a server for it's capability statement using /metadata, which features to report on is at the discretion of the server. Typically, servers will not report any features by default. Features can be queried by search parameter or via an operation.
Clients can request that a server by using the feature parameter, which represents a query for information about a particular feature:
GET [base]/feature-query?feature[@context](value)
For example, here is how you would ask if the Patient resource has read access:
GET [base]/feature-query?param=read@Patient(true)
Requesting multiple features:
GET [base]/feature-query?param=read@Patient(true)¶m=update@Patient(true)
TBD: add example in/out params and explain invoking them in a POST
In addition to querying for a capability statement, clients can do negotation. There are 2 different approaches that are supported: an operation, and an HTTP header.
Alternatively, a client can include a feature assertion on an HTTP header:
GET [base]/Patient/23/_history/45
Required-Features: param=read@Patient(true)
The server checks the header, and return a 501 Not implemented if it does not support reading historical entries for AdverseEvent.
Clients can only expect a server to check these headers if the server declares that it does using the feature rest:server.feature-header = true.