For a full list of available versions, see the Directory of published versions
The FHIR mustSupport flag (set on an ElementDefinition within a profile) signals that implementations producing or consuming resources SHALL provide support for that element in some meaningful way. However, the flag deliberately does not define what "support" means - a profile using mustSupport is required to make that expectation explicit through accompanying narrative or other conformance mechanisms.
This intentional ambiguity has been a persistent pain point. HL7 recognises that IG authors and their communities have not always been fully aligned on the interpretation of mustSupport, leading to implementer confusion about the scope and nature of the obligation it implies.
Obligations are the formal, machine-readable answer to the MustSupport ambiguity problem. Rather than leaving behavioural expectations to narrative prose, the Obligation extension provides a structured, actor-specific, and tooling-verifiable mechanism for expressing exactly what applications must do with a given element.
Obligations relate to application behaviour, not to the content of the element itself in the resource instance. They define what a system must do with data - not what the data must look like.
MustSupport and Obligations are complementary, not competing:
mustSupport = true.mustSupport can be changed from false to true but not from true to false. Similarly, obligations can be added for specific actors in derived profiles but existing actor obligations cannot be removed or weakened.
In summary: MustSupport says this element matters; Obligations say exactly what you must do with it, and who you are when you do it.Obligation codes combine a qualifier and a functional code using the syntax [qualifier]:[code] - for example, SHALL:populate or SHOULD:display.
Qualifiers express conformance strength: SHALL, SHOULD, or MAY.
Functional codes are grouped into three high-level categories:
| Category | Applies to |
|---|---|
| ResourceProducerObligations | Applications that create and send FHIR resources |
| ExchangerObligations | Applications that receive and forward resources (intermediaries) |
| ResourceConsumerObligations | Applications that receive and act on resources |
Note that a given application will typically play multiple roles simultaneously - for example, a clinical data repository may be both a consumer (receiving data from submitters) and a producer (serving data to EMRs).
Obligations may be scoped to specific named actors using the actor sub-element of the Obligation extension. This allows an IG to express different expectations for different system roles - for example:
DataSubmitter SHALL populate .identifierDataConsumer SHALL NOT error on receipt of .identifier and SHOULD display it to the end userDataRepository SHALL store .identifier
Without actor scoping, an obligation applies to all systems implementing the element.1. Separate sender and receiver expectations A single MustSupport flag cannot distinguish what a sender must provide from what a receiver must do with it. Obligations make these expectations explicit and separately testable per actor.
2. Display and rendering requirements
Obligations can mandate that a consuming system SHOULD or SHALL display an element to end users (e.g. SHALL:display) - a behavioural expectation that MustSupport alone cannot express.
3. Data persistence and storage
An obligation can require that a receiving or intermediary system SHALL persist an element (e.g. SHALL:store), which is important for audit trails, longitudinal records, and safety-critical data.
4. Forwarding and pass-through rules For intermediary actors, obligations can require that an element be passed on unchanged when forwarding a resource - critical in health information exchange scenarios where data fidelity must be guaranteed across hops.
5. Separating structural validation from behavioural conformance Structural profiles define what a resource may contain. Obligations define what systems must do with the content they send or receive. Keeping these concerns separate makes conformance expectations clearer and independently testable.
6. Multi-actor IGs and workflow profiles IGs that describe end-to-end workflows involving multiple system types (e.g. submitter → repository → EMR) benefit most from obligations, since each hop has distinct responsibilities. Obligations should be associated with defined actors wherever possible, and use-case profiles embedded in a workflow should derive from abstract profiles that capture shared obligations applicable across the workflow.
Obligations were not part of FHIR R4. The mustSupport and obligation features of ElementDefinition as a combined conformance mechanism were formally introduced in FHIR R5 (published May 2023). The ActorDefinition resource - the formal way to define named actors that obligations can be scoped to - is also an R5 addition and does not exist as a native resource in R4.
Despite being an R5 concept, obligations can be used in R4-based IGs through the FHIR Extensions Pack (hl7.fhir.uv.extensions). The extensions defined in this pack apply equally to FHIR versions R5, R4B, R4, and R3. An R4 IG can declare a dependency on hl7.fhir.uv.extensions.r4 and use the Obligation extension on ElementDefinition elements.
There are, however, important limitations when using obligations in R4:
ActorDefinition does not exist natively in R4, the typed canonical reference to an ActorDefinition resource is not available. Actor references must be expressed as plain URIs rather than as typed resource references.| Feature | FHIR R4 | FHIR R5 |
|---|---|---|
mustSupport flag |
✅ Native | ✅ Native |
| Obligation extension | ⚠️ Via Extensions Pack (draft, limited) | ✅ Native, normative |
ActorDefinition resource |
❌ Not available natively | ✅ Native |
| Actor-scoped obligations | ⚠️ URI reference only | ✅ Typed canonical reference |
| Tooling / validator support | ⚠️ Partial, emerging | ✅ Better supported |
Obligations are already in use in R4-based IGs despite their draft status. The HL7 Europe Laboratory Report IG (R4-based) adds obligations as informative material to collect feedback, using separate "obligation profiles" (distinct StructureDefinitions) from the structural constraint profiles. This separation pattern is recommended: since R4 tooling support is limited, maintaining separate structural profiles (constraints) and obligation profiles (behavioural expectations) reduces coupling and isolates change.
The CA Core+ Implementation Guide (v1.2.0-DFT, published by Canada Health Infoway) adopts the FHIR Obligation extension as a formal mechanism for expressing actor-specific conformance expectations across its R4-based profiles. CA Core+ defines two primary actors - Producer and Consumer - whose roles align with how obligations are specified across the guide. These are represented as example ActorDefinition instances included with the release, with the page narrative serving as the authoritative source of truth given that some publishing environments do not yet fully render R5 ActorDefinition content alongside R4 artifacts. Because CA Core+ is based on FHIR R4, the guide backports the Obligation extension (defined natively in R5) to enable consistent declaration of requirements and expectations across its artifacts. Obligations use codes from the standard Obligation Codes ValueSet and are applied with the explicit caveat that no data should be populated or processed in any way that conflicts with regional laws, regulations, or policies.
In practice, CA Core+ applies three obligation codes across its profiles. Producers are assigned either SHALL:populate-if-known - meaning the system must send an element when the data is known or available in the source system - or MAY:populate-if-known, which signals that sending is permitted but not required even when the data is available. Consumers are uniformly assigned SHALL:no-error, requiring that receiving systems be able to process the element gracefully without generating an error, regardless of whether the element is present or absent. The SHALL:populate-if-known obligation is applied to CACDI-mapped elements considered critical for interoperability, while MAY:populate-if-known is used where implementer flexibility is appropriate. CA Core+ is explicit that obligations and actor expectations are an evolving mechanism that will be refined as adoption grows and as additional exchange patterns - such as REST, messaging, and subscriptions - are supported. The current obligation set is therefore intentionally conservative: a minimal, well-defined starting point rather than a complete expression of all possible behavioural expectations.
The core reason HAPI and Smile CDR do not enforce obligation semantics at runtime is architectural, not a gap in implementation. Obligations describe application behaviour, not the content of resource instances. The information needed to determine whether a usage context applies - what actor is sending the request, in what workflow, in what direction - is typically outside the resource payload and outside the scope of what a server-side validator can inspect at the HTTP layer.
Validating SHALL:display or SHALL:store requires observing the behaviour of the consuming application, not the shape of the data it receives. No instance validator can do this.
Parsing and serialising Obligation extensions
HAPI's R4, R4B, and R5 model layers can parse and serialise StructureDefinition resources containing the Obligation extension without error. Extensions not explicitly known to the validator are validated structurally but do not cause validation failures.
Storing and serving IG packages with obligations
Smile CDR stores and serves conformance resources - including StructureDefinitions with Obligation extensions - loaded from NPM packages and Implementation Guides. An IG package containing obligation-annotated profiles loads cleanly and the full StructureDefinition content, including the Obligation extension, is served correctly through the REST API.
Instance validation - the boundary
The HAPI FHIR instance validator checks resources for conformance using StructureDefinition and ValueSet resources, validating structure, cardinality, data types, terminology bindings, and invariants. Elements carrying mustSupport = true are subject to any associated cardinality or type constraints. The obligation codes themselves (SHALL:populate, SHALL:display, etc.) are not evaluated during instance validation - they describe system behaviour, not data shape, and cannot be assessed from a resource payload alone.
Policy advisor extension point
HAPI's FhirInstanceValidator exposes an IValidationPolicyAdvisor interface allowing custom validation logic to be plugged in. Theoretically, a custom policy advisor could inspect obligation codes on elements and apply application-specific enforcement. This is not provided out of the box, and implementing it requires application-level context that goes beyond what the HAPI core libraries supply.
| Capability | Support |
|---|---|
| Parse / store profiles with Obligation extension | ✅ Supported |
| Serve IG packages containing obligations via REST | ✅ Supported |
Structural validation of elements with mustSupport |
✅ Supported (cardinality and type rules) |
| Enforce obligation codes during instance validation | ❌ Not supported |
| Actor-aware obligation checking (server vs. client) | ❌ Not supported |
Runtime enforcement of SHALL:display / SHALL:store |
❌ Not supported (by design) |
Custom enforcement via IValidationPolicyAdvisor |
⚠️ Possible with custom implementation |
This limitation is not unique to HAPI. The FHIR reference CLI validator (validator_cli.jar), which is developed in association with HL7, SmileCDR, and the HAPI FHIR project, also does not currently enforce obligation codes. The FHIR specification explicitly acknowledges that validation tooling can only validate the computable aspects of conformance - there are always additional rules expressed in narrative that conformance tools cannot check. Obligations, particularly actor-scoped behavioural ones, fall squarely into that category.
HAPI and Smile CDR are compliant participants in the obligation ecosystem: they correctly handle the Obligation extension as data, load obligation-annotated IG packages, and provide extension points for custom logic. Obligation enforcement - ensuring that a given system actually stores, displays, or forwards data as declared - must be implemented at the application layer, not delegated to the FHIR server.
Currently, OH FHIR IGs expresses conformance expectations through two parallel, loosely coupled mechanisms:
mustSupport flag on profile elements, governed by a shared narrative block (the "MustSupport Flag" section) that defines submitting and consuming obligations in prose.This dual approach has served the IGs well but creates gaps: the narrative is not actor-specific (submitter vs. consumer obligations are conflated), the per-element notes are not testable by conformance tooling, and the approach diverges from the direction HL7 International is taking with the formal Obligation extension. As the IGs mature toward wider adoption, aligning with the Obligation extension would be the right long-term investment.
Before any profile changes can be made, the team must agree on a set of design decisions that will govern the migration uniformly. These decisions define the "house style" for obligations across all IGs.
The Obligation extension is most powerful when scoped to named actors. The current IGs implicitly identify two actors - a submitter (e.g. hospital or ICHSC sending data in) and a consumer (e.g. EMR queerying data out) - but these are described in prose only. A prerequisite to adding obligations is formalising the actor model.
Proposed canonical actors (to be confirmed with the team):
| Actor name | Description |
|---|---|
DataSubmitter |
Hospital, ICHSC, or source system submitting FHIR resources to Ontario Health |
DataConsumer |
EMR or consuming application receiving FHIR resources from the OH CDF FHIR repository |
DataRepository |
The OH CDF FHIR repository that stores and serves data |
Each actor should be defined in a shared ActorDefinition resource (or, for R4 compatibility, as a documented canonical URI) and referenced consistently across all IG obligation statements.
Option A - MS + Obligations (recommended for near-term)
Retain the mustSupport flag for backwards compatibility with existing tooling and validators. Add the Obligation extension alongside MS to provide machine-readable actor-specific detail. The shared MS narrative block is updated to note that obligations provide the authoritative per-actor detail.
Option B - Obligations Only
Remove the mustSupport flag and rely entirely on the Obligation extension. Cleaner long-term but breaks any tooling or downstream IGs that currently key on mustSupport. Not recommended until HAPI/Smile CDR validator support for obligations matures.
Recommendation: Proceed with Option A. Retire Option B as a future consideration, subject to tooling maturity review at a defined milestone (see Phase 3).
Establish a constrained set of obligation codes to use across the IGs to avoid inconsistency. Proposed minimum set:
| Code | Applies to | Meaning |
|---|---|---|
SHALL:populate |
DataSubmitter | The submitter SHALL include this element when data is available |
SHOULD:populate |
DataSubmitter | The submitter SHOULD include this element if available |
SHALL:no-error |
DataConsumer | The consumer SHALL not error or fail on receipt |
SHALL:handle |
DataConsumer | The consumer SHALL process and act on this element meaningfully |
SHOULD:display |
DataConsumer | The consumer SHOULD display this element to end users |
SHALL:store |
DataRepository | The repository SHALL persist this element |
Additional codes may be added per profile where needed, but the above must be present in any element that currently has mustSupport = true.
Given that R4 tooling for obligations is still maturing, consider the HL7 Europe pattern of maintaining separate obligation profiles (child StructureDefinitions that add only obligations, no structural constraints) layered on top of the structural profiles. This keeps the structural profiles stable and isolates obligation changes from constraint changes.
This is optional but strongly recommended for profiles that are shared across multiple IGs or are inherited by downstream profiles (e.g. OH EHR profiles).
A full profile inventory must be completed as the first concrete deliverable. At minimum the inventory should capture:
mustSupport = trueMap the inheritance relationships between profiles across IGs. The EHR profiles sit at the top of the dependency tree; domain–specific IGs derive from them. Obligations set in a parent profile constrain what child profiles can do (obligations can be added but not relaxed in a derivation). This means the EHR base profiles must be migrated first before any derived profile can be migrated without risk of inconsistency.
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Obligation extension not validated by Smile CDR | High | Low (obligations are informative, not enforced at runtime) | Document that obligations describe application behaviour, not instance content; set implementer expectations accordingly |
| R4 actor reference limitations | High | Low–Medium | Use canonical URI references for actors rather than typed ActorDefinition references; document the limitation |
| Inconsistency introduced during incremental migration | Medium | Medium | Enforce the design decisions via a review checklist before any profile is published |
| Downstream IG breakage from profile changes | Low | High | Limit structural changes to zero during Phase 1; obligations are additive only |
| Implementer confusion during transition (MS + Obligations coexisting) | Medium | Medium | Update the shared MS narrative block to clearly explain the relationship and direct implementers to obligations for per-actor detail |
| Tooling immaturity (FHIR publisher rendering, IG builder) | Medium | Low | Review rendering of obligation extension in IG publisher before committing to the approach; confirm display in simplifier.net |
Before beginning the migration, verify the following:
hl7.fhir.uv.extensions.r4 is available in the IG dependency chainA big-bang migration - updating all profiles across all IGs simultaneously - carries significant risk. Changes to parent profiles cascade to children, and simultaneous changes across IGs reduce the team's ability to catch inconsistencies before they propagate.
The recommended approach is incremental, top-down migration following the profile dependency graph:
Phase 0 - Foundations (no profile changes)
Phase 1 - Pilot (EHR base profiles, one domain IG)
Phase 2 - Broad Rollout (remaining profiles)
Phase 3 - Consolidation and Future Consideration
DataSubmitter be split into sub-actors (e.g. HospitalSubmitter vs. ICHSCSubmitter) given that different submitter types may have different obligation levels for some elements?