visit the hl7 website
Ontario Immunization Repository Implementation Guide -v1.0.0-draft3
fhir-logo
  • Index
  • Home
    • Home
    • Introduction
    • Relationship to Other Specifications
    • Scope
    • Glossary
  • Business Context
    • Business Context
    • Business Model
    • Business Data
    • Use Cases
    • Business Rules
  • Technical Context
    • Technical Context
    • Implementer Responsibility
    • Conformance Rules
    • Connectivity Summary
    • Obligations
    • Obligations in EHR Profiles
  • FHIR Artifacts
    • FHIR Artifacts
    • Interactions
    • Profiles
    • Extensions
    • Data Types
    • Terminology
    • System URIs
    • Examples
    • Capability Statement
    • Custom Search Parameters
    • Response Handling
    • Downloads
  • Change Log
    • Change Log
    • Known Issues & Future Developments
    • Revision History
    1. Index
    2. Technical Context
    3. Obligations

For a full list of available versions, see the Directory of published versions

3.4. Obligations

3.4.1. Overview

3.4.1.1. What is MustSupport?

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.

3.4.1.2. What are Obligations?

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.

3.4.1.3. Relationship to MustSupport

MustSupport and Obligations are complementary, not competing:

  • MustSupport signals that an element matters and that implementers must provide support for it.
  • Obligations define precisely - per actor, per role - what that support entails.
  • If an element has obligations defined, it SHOULD also carry mustSupport = true.
  • In cases where legacy interpretation of MustSupport makes raising the flag problematic, the profile or IG SHOULD document the rationale for the discrepancy.
  • When deriving profiles, 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.

3.4.2. Obligation Codes and Actors

3.4.2.1. Code Structure

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).

3.4.2.2. Actor Scoping

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 .identifier
  • DataConsumer SHALL NOT error on receipt of .identifier and SHOULD display it to the end user
  • DataRepository SHALL store .identifier Without actor scoping, an obligation applies to all systems implementing the element.

3.4.3. Main Use Cases for Defining Obligations

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.


3.4.4. FHIR Version Support

3.4.4.1. Origin: FHIR R5

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.

3.4.4.2. R4 Support via the FHIR Extensions Pack

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:

  • The Obligation extension is represented slightly differently in R4, and the R4-adapted form is still marked as draft while real-world experience is being collected.
  • Since 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.

3.4.4.3. Version Comparison

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

3.4.4.4. Real-World R4 Usage

3.4.4.4.1. HL7 Europe

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.

3.4.4.4.2. Canada

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.


3.4.5. HAPI FHIR and Smile CDR Support

3.4.5.1. Runtime Enforcement is Fundamentally Limited

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.

3.4.5.2. What HAPI / Smile CDR Supports

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.

3.4.5.3. Summary: HAPI / Smile CDR Obligation Support Matrix

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

3.4.5.4. Broader Context

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.


3.4.6. Motivation for Adoption of Obligations

Currently, OH FHIR IGs expresses conformance expectations through two parallel, loosely coupled mechanisms:

  1. The mustSupport flag on profile elements, governed by a shared narrative block (the "MustSupport Flag" section) that defines submitting and consuming obligations in prose.
  2. Per-element human-readable notes (e.g. "SHALL include at least one identifier / SHOULD include patient's MRN") that express behavioural expectations at the element level but are not machine-readable and are not consistently structured across profiles.

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.


3.4.7. Scoping and Design Decisions

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.

3.4.7.1. Actor Model

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.

3.4.7.2. Conformance Model: MS + Obligations vs. Obligations Only

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).

3.4.7.3. Obligation Code Set

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.

3.4.7.4. Separation of Structural Profiles and Obligation Profiles

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).


3.4.8. Impact Assessment

3.4.8.1. Profile Inventory

A full profile inventory must be completed as the first concrete deliverable. At minimum the inventory should capture:

  • Profile name, URL, and IG it belongs to
  • Whether it is a "data in" profile (submitter-facing), "data out" profile (consumer-facing), or both
  • Number of elements currently carrying mustSupport = true
  • Whether the profile inherits MS from a parent profile (e.g. acCDR / miCDR alignment)
  • Presence and quality of existing per-element notes (well-structured vs. ad hoc)
  • Downstream profiles or IGs that derive from or reference this profile

3.4.8.2. Dependency Graph

Map 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.

3.4.8.3. Risk Assessment

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

3.4.8.4. Tooling Readiness Check

Before beginning the migration, verify the following:

  • FHIR IG Publisher version in use renders obligation extensions in the generated IG HTML
  • Simplifier.net displays obligation extensions on profile pages
  • Smile CDR / HAPI loads IG packages containing obligation extensions without error
  • The Obligation extension from hl7.fhir.uv.extensions.r4 is available in the IG dependency chain
  • Existing per-element notes can be systematically converted to obligation codes (gap analysis)

3.4.9. Recommended Approach

3.4.9.1. Incremental over Big Bang

A 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:

  1. Establish shared foundations (actor definitions, obligation code guidance, shared narrative update) - no profile changes yet
  2. Migrate EHR base profiles first
  3. Migrate domain–specific IGs
  4. Migrate data-in and data-out profiles last, inheriting obligations from their parents where possible

3.4.9.2. Phased Plan

Phase 0 - Foundations (no profile changes)

  • Finalise and ratify actor definitions
  • Ratify conformance model choice
  • Ratify obligation code set
  • Complete profile inventory and dependency graph
  • Conduct tooling readiness check
  • Draft and publish an internal "Obligations Authoring Guide" for use by all IG editors
  • Update shared MustSupport narrative block to reference obligations as the authoritative per-actor detail Estimated duration: 3–4 weeks
    Owner: IG Technical Lead + Team

Phase 1 - Pilot (EHR base profiles, one domain IG)

  • Apply obligations to the EHR base profiles (Patient, Encounter, and 1–2 others to be selected)
  • Apply obligations to one domain–specific IG chosen for its completeness of existing per-element notes (lower conversion effort)
  • Review rendering in IG publisher and simplifier.net
  • Share with a small group of implementers for feedback before broader rollout
  • Document lessons learned and update the Obligations Authoring Guide Estimated duration: 4–6 weeks
    Owner: Assigned profile editors (2 recommended) with IG Technical Lead review

Phase 2 - Broad Rollout (remaining profiles)

  • Migrate remaining EHR profiles using the patterns established in Phase 1
  • Migrate remaining domain–specific IGs in dependency order
  • Migrate data-in and data-out profiles
  • Peer review: each profile reviewed by at least one editor who did not author the obligations
  • Update cross-profile consistency check (actor names, obligation codes, MS flag alignment) Estimated duration: 8–12 weeks (dependent on number of profiles and editor availability)
    Owner: All IG editors; IG Technical Lead coordinates sequencing

Phase 3 - Consolidation and Future Consideration

  • Collect implementer feedback
  • Evaluate HAPI/Smile CDR obligation support maturity
  • Evaluate whether obligation profiles should be formally separated
  • Update roadmap based on lessons learned Estimated duration: TBD Owner: IG Technical Lead

3.4.10. Open Questions for the Team Discussion

  1. Actor granularity: Should DataSubmitter be split into sub-actors (e.g. HospitalSubmitter vs. ICHSCSubmitter) given that different submitter types may have different obligation levels for some elements?
  2. Obligation profiles: Is the team prepared to maintain separate obligation StructureDefinitions, or does the added complexity outweigh the benefit given the current IG scale?
  3. Existing per-element notes: Once obligations are added, should the human-readable per-element notes under the Notes section be removed (to avoid duplication and potential drift), retained as supplementary narrative, or replaced by obligation display rendered by the IG publisher?
  4. Tooling gap: If the FHIR publisher does not render obligations acceptably in the generated HTML, is the team prepared to author supplementary narrative tables as a stopgap, or should the migration be deferred?

Version: 1.0.0-draft3 FHIR Version: R4.0.1

Powered by SIMPLIFIER.NET

HL7® and FHIR® are the registered trademarks of Health Level Seven International