DocumentReference Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-documentreference |
|---|---|
| Status | draft · 1.26.0 |
| Base | DocumentReference (constraint) |
| CQL primary code path | type — what this means |
| Source | FSH · JSON |
Nexus EMR profile for an ATTACHED DOCUMENT -- a clinical document that exists as a file:
scanned paper, incoming faxes, external consult letters received as PDF, signed consent forms,
patient-uploaded files. FHIR holds the metadata and clinical context; the bytes live in
document storage and are reached through content.attachment.url.
FSH
The authored source of truth: resources/StructureDefinition-nexus-emr-core-documentreference.fsh (edit on GitHub). One FSH file may define several related artifacts.
// NexusEmrCoreDocumentReference.fsh
// ATTACHED DOCUMENTS -- files that arrive as bytes: scans, PDFs, faxes, Word documents.
//
// SCOPE NARROWED (August 2026). This profile used to be "clinical document management" in
// general, and textual encounter notes were consequently mapped onto it. Authored notes now
// live on `NexusEmrCoreComposition`, where the narrative is XHTML in FHIR and
// `Composition.status` carries the draft/signed/amended lifecycle. DocumentReference keeps
// what it is genuinely good at -- referencing a document that exists as a FILE.
//
// THE BOUNDARY RULE (restated identically on the Composition profile):
// Composition = a note this EMR's user AUTHORED. Narrative IS the FHIR resource.
// DocumentReference = a document that ARRIVED as an opaque file, or is only meaningful as
// one. Content is bytes with a MIME type; FHIR holds metadata + a
// pointer.
// The test is not "is it clinical" -- both are. It is "did we write it, and is the content
// text we control?" A scanned consult letter is a DocumentReference even though a human wrote
// it, because what we hold is a TIFF. A dictated-then-transcribed progress note is a
// Composition even though a machine produced the text, because we hold the text.
//
// Typical DocumentReference content after the narrowing: incoming faxes, scanned paper,
// external consult letters received as PDF, lab reports delivered as documents rather than
// as DiagnosticReport, signed consent forms, imaging reports from outside systems,
// patient-uploaded files.
//
// WHAT THIS PROFILE NOW DOCUMENTS THAT IT DID NOT BEFORE: the gateway's content machinery.
// The profile previously described content as inline-base64-first, which stopped being true
// once the gateway grew document storage -- implementers were reading a contract the runtime
// no longer honours. The `content.attachment` element definitions below now describe what the
// FhirGateway actually does. Code-verified 2026-08-06 against
// `backend/services/FhirGateway/.../Middleware/AbstractAttachmentReferenceMiddleware.cs`,
// `.../DocumentReference/Middleware/DocumentReferenceStorageMiddleware.cs`, and
// `backend/services/FileStorageService/`.
Alias: $NexusEmrCoreDocumentReference = ../StructureDefinition/nexus-emr-core-documentreference
// Invariant to ensure Nexus EMR-compliant identifiers
// Invariant to ensure at least one of data or url is present on each attachment
Invariant: attachment-has-data-or-url
Description: "Each attachment must have either inline data (base64) or a url (blob storage URI), or both"
Severity: #error
Expression: "content.all(attachment.data.exists() or attachment.url.exists())"
// A FORM TEMPLATE HAS NO PATIENT, and until now this profile said it must (FHIR-94).
//
// PSD-1230 defines a form template as a SUBJECT-LESS DocumentReference: the tenant-wide blank of a
// form type, held once per tenant and about nobody. This profile marked `subject 1..1`, so the
// shape the guide told implementers to create was one this profile rejected. Nothing caught it
// because no example exercised either form naming system -- a declared identifier system with no
// instance is an unvalidated claim, and both now ship with one.
//
// WHY RELAX-PLUS-INVARIANT rather than a second profile. The alternative considered was a separate
// template profile, which answers the case once per resource type: the moment a second kind of
// subject-less document appears the choice is made again. This states the rule once, on the element
// a reader is already looking at, and it stays EVALUABLE -- a generic validator runs it, which a
// prose caveat would not be.
//
// The guarantee for every other document is UNCHANGED. A DocumentReference that is not a form
// template still requires a subject, and the invariant says so in portable FHIRPath rather than
// leaving `0..1` to be read as "optional". A consumer that assumed a subject was always present
// must now handle the template case, which is the point: the templates were already being written.
Invariant: nexus-documentreference-subject-unless-template
Description: "A DocumentReference SHALL carry a subject unless it is a form template. A template (an identifier under NamingSystem/nexus-form-template) is the tenant-wide blank of a form type and is about no patient; every other document is about one."
Severity: #error
Expression: "subject.exists() or identifier.where(system = '../NamingSystem/nexus-form-template').exists()"
// A FIELD MAPPING BELONGS TO A TEMPLATE. It names the fillable fields of the template's FILE that a
// chart value pre-fills; a filed form carries the filled values in its own file and has nothing
// for a mapping to say. Stated as an invariant rather than a second profile for the same reason
// `subject` is: one evaluable rule on the element a reader is looking at.
Invariant: nexus-documentreference-field-mapping-only-on-template
Description: "A field mapping SHALL appear only on a form template (an identifier under NamingSystem/nexus-form-template): it names the fillable fields of the template's file that a chart value pre-fills, and a filed form carries the values themselves"
Severity: #error
Expression: "extension.where(url = '../StructureDefinition/nexus-form-template-field-mapping').exists() implies identifier.where(system = '../NamingSystem/nexus-form-template').exists()"
// Profile Definition
Profile: NexusEmrCoreDocumentReference
Parent: DocumentReference
Id: nexus-emr-core-documentreference
Title: "DocumentReference Profile"
Description: """
Nexus EMR profile for an ATTACHED DOCUMENT -- a clinical document that exists as a file:
scanned paper, incoming faxes, external consult letters received as PDF, signed consent forms,
patient-uploaded files. FHIR holds the metadata and clinical context; the bytes live in
document storage and are reached through `content.attachment.url`.
Use `NexusEmrCoreComposition` instead for notes AUTHORED in this EMR -- encounter notes,
consult notes, telephone notes -- where the narrative is text the EMR controls and belongs in
FHIR as XHTML. The two profiles partition the clinical-document space; neither is a fallback
for the other.
Documents are submitted with inline base64 in `content.attachment.data`; the gateway stores
them and rewrites the attachment to carry a `url` instead. See the `content` element
definitions for the full round-trip contract, including what a reader should expect back.
Aligned with CA-Core+ standards and CII requirements for Canadian healthcare.
"""
* ^url = $NexusEmrCoreDocumentReference
* ^status = #draft
* obeys attachment-has-data-or-url and nexus-documentreference-subject-unless-template and nexus-documentreference-field-mapping-only-on-template
// THE effective date for this profile (see the EffectiveDate / NoEffectiveDate
// RuleSets): one date concept per resource, declared here rather than guessed.
* insert EffectiveDate([[date]])
// Salient fields — the reader/render surface (see SalientField + the Salient RuleSet).
* insert Salient(type, type, coded)
* insert Salient(category, category, coded)
* insert Salient(status, status, code)
* insert Salient(date, date, dateTime)
* insert Salient(description, description, string)
* insert Salient(author, [[author.first().display]], string)
// REMOVED 2026-08-06 with the scope narrowing — was:
// * insert SalientAs(data, [[content.first().attachment.data]], base64Binary, prose)
// It decoded `content.first().attachment.data` and surfaced it to chart/model readers as
// `prose`. That was defensible while this profile carried textual encounter notes. It is wrong
// now, on two independent grounds:
// 1. SCOPE. The content here is a PDF, a TIFF, a Word file. Base64-decoding it yields binary,
// not prose — a renderer given the "long-form text" hint would spill file bytes into the
// chart. The narrative surface moved to `NexusEmrCoreComposition.section.text`.
// 2. RUNTIME. `data` is normally ABSENT on read. The gateway converts inline data to stored
// files on write and sets `attachment.data = null`
// (`AbstractAttachmentReferenceMiddleware.cs:64`), so this accessor resolved to empty for
// every gateway-ingested document regardless.
// A document's salient reader surface is its metadata — type, title, date, author — plus the
// `url` to fetch bytes from. `title` is added below for exactly that reason.
* insert Salient(title, [[content.first().attachment.title]], string)
* insert Salient(url, [[content.first().attachment.url]], string)
// SMART on FHIR exposure -- this resource is reachable by an app, and these are the
// permissions each operation costs (see SmartExposed + the SmartExposed RuleSet).
* insert SmartExposed(documentreference)
// Review state: who signed this document off and when; ABSENT = unreviewed. The Task inbox is the
// review workflow; this is the queryable state it stamps, and it sits on the document so a reader
// holding the document renders a checkmark without joining to a Task.
// IT REPEATS HERE because a document is assigned to reviewers INDIVIDUALLY -- one review task per
// reviewer, each of whom signs off for themselves -- so the document carries one stamp per reviewer
// and a reader can tell which of them has acted.
* extension contains NexusEmrReviewed named reviewed 0..* MS
* extension[reviewed] ^short = "Review acknowledgement, one per reviewer (absent = unreviewed)"
// Why a document left `current`. R4 DocumentReference has no `statusReason`, so the reason a
// document was superseded or entered in error -- the half of a status change the code cannot
// carry -- rides this extension, on the version that recorded it. Absent on an active document.
* extension contains DocumentStatusReasonExtension named statusReason 0..1 MS
* extension[statusReason] ^short = "Free-text reason the document is superseded or entered in error (absent when current)"
* extension[statusReason] ^definition = """
Why the document is no longer `current`: what replaced a superseded document, or what made an
entered-in-error one wrong. Written when the status changes and removed when the document is
made current again, so a stale reason never sits on an active document. Because the resource is
updated in place, each stored version keeps the reason that applied to it -- the store's version
history is the audit of who changed the status, when, from what to what, and why. Optional: a
status change with no reason is a complete record.
"""
// --- Root Element ---
* . ^short = "An attached document (scan, PDF, fax, Word) with its metadata and clinical context"
* . ^definition = """
DocumentReference is the metadata wrapper for a document that exists as a FILE -- scanned paper,
an incoming fax, an external consult letter received as PDF, a signed consent form. It provides
indexing, discovery, and clinical context; the bytes themselves live in document storage and are
reached through `content.attachment.url`.
For notes AUTHORED in this EMR, use `NexusEmrCoreComposition` instead -- narrative belongs in
FHIR as XHTML, not as an encoded attachment. See the boundary rule at the top of this file.
The resource captures:
- Document identification and categorization
- Clinical context and temporal relevance
- Authorship and authentication details
- A pointer to the document content (and, on the way in, the content itself)
- Relationships to other documents
"""
* meta.source 0..1 MS
* meta.source ^short = "Identifies EMR instance & pipeline version the resource came from"
* meta.source ^definition = "A URI that identifies the EMR pipeline and version from which this resource originated. This tells you which EMR instance (recommend using the instance identifier), and the version of the pipeline code/transformations."
* text 0..1 MS
* text ^short = "Human-readable summary of the document reference"
* text ^definition = "A human-readable narrative that contains a summary of the document reference. This narrative should provide key information about the document for human interpretation, including document type, date, and key clinical context."
// Identifier: A business identifier is recommended but not required (any system). MS per CA-Core.
// NOT Must Support, and the reason is that nothing mints one. `identifier` here is
// RECOMMENDED but not required, under no mandated system -- and since the instance-scoped
// scheme was retired (FHIR-71) no producer writes a business identifier onto this type at
// all. Must Support asserts that an implementer can be expected to populate an element;
// claiming it for one the specification neither mandates nor produces states a guarantee
// that is not being made. The element stays available and documented -- a writer with a
// source-system identifier should still carry it.
* identifier 0..*
* identifier.system 1..1
* identifier.value 1..1
* identifier ^short = "Business identifier(s) for document reference"
* identifier ^definition = """
Unique business identifiers assigned to this document reference.
"""
* insert SourceIdentifier(identifier)
// Status: Required for document tracking
* status 1..1 MS
* status ^short = "Where the document reference is in its lifecycle"
* status ^definition = """
The status of this document reference. Allowed values:
- current: The document is active and current
- superseded: The document has been replaced by a newer version
- entered-in-error: The document was created in error and should not be used (deleted)
When a document is updated, the previous version can be marked as 'superseded' and a new DocumentReference
created with status 'current'. This approach:
- Maintains immutable document history
- Provides clear version tracking
- Enables audit trails
- Supports document lifecycle management
"""
// Type field - maintained for compatibility but not recommended
* type 0..1
* type ^short = "Precise type of document (use category instead)"
* type ^definition = """
Specifies the precise type of clinical document referenced (e.g., specific LOINC code for document type).
While this field is supported for backward compatibility with systems expecting it, Nexus EMR strongly
recommends using 'category' instead because:
- Category supports multiple classifications per document
- Category allows both clinical and administrative taxonomies
- Type is limited to a single classification
If used, prefer LOINC codes for interoperability.
Where this code was mapped from a source system's own vocabulary, carry the raw coding alongside the mapped one, flagged `userSelected = true`. See [Carrying the raw code](../guide/patterns/raw-codes.md).
"""
* type ^binding.strength = #extensible
* type ^binding.description = "LOINC document type codes"
// Slicing on the coding array for document type
* type.coding ^slicing.discriminator.type = #pattern
* type.coding ^slicing.discriminator.path = "system"
* type.coding ^slicing.rules = #open
* type.coding ^slicing.description = "Slice by code system"
* type.coding contains
loinc 0..1 MS
// LOINC slice (preferred)
* type.coding[loinc] ^short = "LOINC document type code"
* type.coding[loinc] ^definition = "LOINC code for document type when available"
* type.coding[loinc].system = "http://loinc.org" (exactly)
* type.coding[loinc].code 1..1
* type.coding[loinc].display 0..1
* type.text 0..1
* type.text ^short = "Plain text representation of document type"
// Category - preferred classification method
* category 0..* MS
* category ^short = "Document categorization (preferred over type)"
* category ^definition = """
High-level categorization of the document. This is the PREFERRED method for document classification in Nexus EMR.
Multiple categories can be assigned to provide different perspectives on the document's purpose and content.
Common categories include:
- Received correspondence (consult letters, discharge summaries from other institutions)
- Scanned paper and incoming faxes
- Diagnostic documents (lab or imaging reports delivered as files rather than as DiagnosticReport)
- Legal and administrative documents (consent forms, advance directives, insurance forms)
- Patient-supplied documents
Note what is NOT here since the 2026-08-06 narrowing: progress notes and consultation notes
AUTHORED in this EMR are `NexusEmrCoreComposition`, not DocumentReference. A consult note
*received* as a PDF is still a DocumentReference -- the distinction is the form the content
arrives in, not the clinical genre.
Use standard terminologies (LOINC, SNOMED CT) for maximum interoperability.
"""
* category.text 0..1 MS
* category.text ^short = "Plain text category description"
// Subject: Who the document is about. MS per CA-Core.
//
// `0..1` rather than `1..1`, guarded by `nexus-documentreference-subject-unless-template`: a form
// TEMPLATE is about nobody. Read the cardinality with that invariant, not on its own -- for every
// document that is not a template the requirement is exactly what it was.
* subject 0..1 MS
* subject ^short = "The patient the document is about"
* subject ^comment = "Required unless this is a form template."
* subject ^definition = """
The patient that this document pertains to. Required for every document EXCEPT a form template,
which is the tenant-wide blank of a form type and is about no patient; the
`nexus-documentreference-subject-unless-template` invariant states that rule in evaluable form.
When present it must reference a valid NexusEmrCorePatient resource, and the reference should use
the patient's identifier for reliable cross-system identification.
While the FHIR standard allows documents about other subjects (Device, Practitioner, Group), Nexus EMR currently
only supports patient-centric documents to align with Canadian healthcare requirements.
"""
* subject only Reference(NexusEmrCorePatient)
// Field mapping: which fillable fields of a TEMPLATE's file a chart value pre-fills. Only a
// template carries it -- `nexus-documentreference-field-mapping-only-on-template` states that
// rule in evaluable form -- and a template without one simply opens blank.
* extension contains NexusFormTemplateFieldMapping named fieldMapping 0..1 MS
* extension[fieldMapping] ^short = "Fillable fields a chart value pre-fills -- form templates only"
* extension[fieldMapping] ^definition = """
Which fillable fields of this template's file a chart value pre-fills when a form is started
from it: one rule per field, naming the field as the file names it and the chart value (from
`CodeSystem/nexus-form-chart-value`) that fills it. Present only on a form template. Absent, or
naming no field the file carries, the form opens blank; present, every pre-filled value stays
editable.
"""
// Description: Human-readable description
* description 0..1 MS
* description ^short = "Human-readable description of document content"
* description ^definition = """
A human-readable description of the document's content and purpose. While optional, this field is strongly
recommended as it:
- Provides quick context without opening the document
- Improves searchability and discoverability
- Helps users identify relevant documents quickly
- Supports accessibility requirements
Should be concise but informative (typically 1-2 sentences).
Examples:
- "Complete blood count showing mild anemia, hemoglobin 10.2"
- "Cardiology consultation for chest pain, recommending stress test"
- "Discharge summary following 5-day admission for pneumonia"
"""
// Authenticator: Who verified the document
* authenticator 0..1 MS
* authenticator ^short = "Practitioner who verified this document"
* authenticator ^definition = """
The practitioner who has legally authenticated or verified this document, taking responsibility for its content.
This represents medical/legal responsibility rather than authorship. The authenticator:
- Must have appropriate authority/credentials
- Takes responsibility for document accuracy
- May or may not be the document author
- Should be a single practitioner (not multiple)
Typically the attending physician, consultant, or supervising practitioner.
References a **Practitioner** -- the primary provider identity in this IG. A
**PractitionerRole** reference is also permitted, for the cases where the clinic/role binding
is part of what is being asserted (e.g. authentication performed in a specific role at a
specific organization, which Practitioner cannot express since it has no `organization`).
"""
* authenticator only Reference(NexusEmrCorePractitionerRole or NexusEmrCorePractitioner)
// Custodian: Organization maintaining the document
* custodian 1..1 MS
* custodian ^short = "Organization responsible for document maintenance"
* custodian ^definition = """
The organization that is responsible for maintaining the authoritative source of this document and controlling
access to it. This is a REQUIRED field that identifies:
- Who has stewardship of the document
- Where to direct queries about the document
- Who is responsible for retention policies
- Who manages access permissions
Typically the organization that created the document or currently manages the patient's care.
Must reference a valid NexusEmrCoreOrganization resource.
"""
* custodian only Reference(NexusEmrCoreOrganization)
// Content: Document attachments - supports multiple documents per reference
* content 1..* MS
* content ^short = "Document attachment(s) -- submitted inline, stored as files, read back by URL"
* content ^definition = """
The document content and its metadata. Each content element is one attachment. Multiple
attachments per DocumentReference are supported (a referral letter plus supporting results),
but most cases are a single document.
THE ROUND TRIP -- what a writer sends is not what a reader gets back.
WRITING. Submit the document inline: `contentType` plus base64 in `attachment.data`, with no
`url`. On create or update the gateway stores the bytes, then rewrites the attachment before
persisting it: `url` is set to the stored-document address, `size` and `hash` (SHA-1) are
computed and filled in, and `data` is cleared. Writers SHOULD NOT compute `size`, `hash`, or
`url` themselves.
READING. Expect `url` and no `data`. Fetch the bytes from the URL (see `content.attachment.url`
for the auth contract). Consumers MUST NOT assume `data` is populated.
SENDING BOTH IS A TRAP. The conversion is guarded on `url` being absent. An attachment carrying
BOTH `data` and a `url` bypasses storage entirely and the base64 is persisted inline in the FHIR
resource, where it will be echoed on every subsequent read. Send one or the other: `data` to
upload new content, `url` only to reference something already stored.
STABLE URLS ACROSS UPDATES. Updating a DocumentReference reuses the existing stored-document
identity, so the URL does not churn when metadata changes. (Note this is DocumentReference-only
behaviour; `DiagnosticReport.presentedForm` runs through the same middleware but without the
existing-document lookup, so its attachments get a fresh URL on each update.)
At least one of `data` or `url` MUST be present per attachment (invariant
`attachment-has-data-or-url`) -- which, given the above, means "inline on the way in, URL on the
way out."
"""
* content.attachment 1..1 MS
* content.attachment ^short = "The document: MIME type, content (inline on write / URL on read), and file metadata"
* content.attachment ^definition = """
The attachment carrying the document. Required.
Provides MIME type identification, the content itself (inline base64 on write, a stored-file URL
on read -- see `content` for the round trip), a human-readable title, size, hash, and language.
`size` and `hash` are populated by the gateway during storage; writers need not supply them.
"""
* content.attachment.contentType 1..1 MS
* content.attachment.contentType ^short = "MIME type (e.g., 'application/pdf')"
* content.attachment.contentType ^definition = """
MIME type identifying the document format. This is REQUIRED to ensure proper handling and display of the document.
Common values:
- 'application/pdf' - PDF documents (most common)
- 'text/plain' - Plain text documents
- 'text/html' - HTML formatted documents
- 'text/rtf' - Rich text format
- 'image/jpeg' - JPEG images (scanned documents)
- 'image/png' - PNG images
- 'application/msword' - Microsoft Word
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - Word DOCX
The MIME type must accurately reflect the actual content format.
"""
* content.attachment.data 0..1 MS
* content.attachment.data ^short = "Base64 document content -- the UPLOAD channel; normally absent on read"
* content.attachment.data ^definition = """
The document content as base64-encoded binary. This is the upload channel: populate it (with no
`url`) to submit a new document.
NORMALLY ABSENT ON READ. The gateway clears `data` once the bytes are stored, so a reader gets
`url` instead. Consumers MUST NOT assume this element is populated, and MUST NOT treat its
absence as an empty document.
Do not send `data` and `url` together -- see `content`. That combination skips storage and
persists the base64 inline permanently.
Implementation notes:
- Line breaks in the base64 string should be avoided; standard alphabet (A-Z, a-z, 0-9, +, /).
- Large documents: no explicit size threshold is enforced by the gateway, and the whole body is
buffered in memory during conversion. Very large inline submissions are a practical risk
(request-body limits and memory), not a specified one -- prefer keeping documents modest and
raise it with the platform team rather than assuming a limit exists.
Example encoding (JavaScript):
```javascript
const base64Data = Buffer.from(fileContent).toString('base64');
```
Example encoding (Python):
```python
import base64
base64_data = base64.b64encode(file_content).decode('utf-8')
```
"""
// NOT Must Support, deliberately, and this is the one element on the profile where MS would
// contradict the profile's own writing contract. Must Support binds the PRODUCER: it says a
// writer has to be able to populate the element. This one is written BY THE GATEWAY during
// storage, and the round-trip section above tells writers the opposite -- "submit the document
// inline ... with no `url`", "writers SHOULD NOT compute `size`, `hash`, or `url` themselves",
// and sending both is named as a trap because the conversion is guarded on `url` being absent.
// A producer that must-supported this would have to either mint a File Storage Service address
// for a file it has not stored, or send both and silently bypass storage. Readers are already
// served by the invariant that every attachment carries data or url.
* content.attachment.url 0..1
* content.attachment.url ^short = "Absolute URL to the stored document -- the READ channel; set by the gateway"
* content.attachment.url ^definition = """
Where the document bytes can be fetched. This is the read channel, and for gateway-ingested
documents it is written BY the gateway during storage -- clients uploading new content should
leave it empty and send `data`.
SHAPE. An absolute URL served by the platform's File Storage Service:
https://{host}/fss/api/v1/file/{documentId}
This is NOT a FHIR `Binary` reference (this platform implements no `Binary` endpoint), and NOT
a pre-signed or SAS blob URL. It is a normal API endpoint.
FETCHING IT. The URL is not self-authorizing. Retrieval requires the caller's own credentials:
a bearer token carrying the file-read permission, and the request resolves within the caller's
tenant -- a document belonging to another tenant is not found, regardless of the identifier. A
client that treats this like a public or signed download link will get a 401, not a document.
Reads are audited.
STABILITY. The URL is permanent for the life of the document -- no expiry, no rotation -- and
survives updates to the DocumentReference (the gateway reuses the stored-document identity).
It may therefore be cached and stored.
SUPPLYING A URL YOURSELF. Permitted, for referencing content already held by the platform, but
validated: the host must be trusted, and an untrusted host is rejected with a 400 and an
OperationOutcome directing you to upload via `data` instead. Do not point this element at
arbitrary external systems -- content that lives outside the platform should be ingested, not
linked.
"""
* content.attachment.title 0..1 MS
* content.attachment.title ^short = "Document title for display"
* content.attachment.title ^definition = """
Human-readable title for the document. While optional, this field is strongly recommended for user experience.
The title should be:
- Descriptive and meaningful
- Suitable for display in document lists
- Include relevant context (e.g., date, type)
- 50-100 characters typically
Examples:
- "Discharge Summary - April 15, 2025"
- "CBC Results - Hemoglobin 10.2"
- "Cardiology Referral - Dr. Smith"
- "Chest X-Ray Report - Normal"
"""
* content.attachment.creation 0..1
* content.attachment.creation ^short = "Date/time document was created"
* content.attachment.creation ^definition = """
The date/time when the document was originally created (not when the DocumentReference was created).
Useful for:
- Distinguishing between multiple versions
- Understanding document timeline
- Sorting documents chronologically
- Audit trail purposes
Format: FHIR dateTime (e.g., "2025-04-20T10:00:00-06:00")
"""
* content.attachment.language 0..1
* content.attachment.language ^short = "Language of document content"
* content.attachment.language ^definition = """
BCP-47 language tag indicating the human language of the document content. Important for:
- Multilingual healthcare settings
- Accessibility requirements
- Content filtering/searching
- Translation workflows
Common values:
- 'en-CA' - Canadian English
- 'fr-CA' - Canadian French
- 'en' - English (generic)
- 'fr' - French (generic)
- 'es' - Spanish
Example: A discharge summary in French would have language = 'fr-CA'
"""
// ⚠ THIS PROFILE AND Composition DISAGREE ABOUT WHERE THE SAME FACTS LIVE, and the mismatch is
// inherited from base R4 rather than introduced here. A reader who learns one and assumes the
// other will look in the wrong place three times:
//
// what DocumentReference Composition
// ------------------------- ------------------------- ---------------------
// when the care happened context.period event.period
// what kind of care context.event event.code
// the visit context.encounter (NESTED) encounter (TOP level)
//
// So DocumentReference puts `context` at the top and `event` inside it; Composition puts `event`
// at the top and `code` inside it -- the same two words, nested the opposite way round. And the
// encounter link sits at a different depth in each. Nothing here can fix that; it is written down
// so it costs a reader one paragraph instead of one debugging session.
* context.encounter 0..* MS
* context.encounter ^short = "Related clinical encounter(s)"
* context.encounter ^definition = """
Encounter(s) related to the document content. Links the document to specific clinical visits, admissions, or
other healthcare interactions. Multiple encounters can be referenced if the document spans multiple visits.
Examples:
- Discharge summary → Inpatient admission encounter
- Consultation note → Outpatient consultation encounter
- Operative report → Surgical encounter
- Progress note → Daily hospital round encounter
Providing encounter context enables:
- Grouping documents by visit
- Understanding care continuity
- Encounter-based searches
- Billing/administrative workflows
"""
* context.encounter only Reference(NexusEmrCoreEncounter)
// THE BACK-POINTER, and it is the SECOND link rather than the only one.
//
// A rendered artifact -- the merged PDF that went out with a letter or a referral -- points back at
// what it was assembled from: the attachment packet (a `List` profiled as NexusAttachmentPacket)
// and the host the packet travelled with. Ontario eReferral profiles this same element the same
// way, targeting its ServiceRequest with `reference` 1..1, so the pattern is not ours alone.
//
// WHAT CHANGED IN 1.24.0 IS THAT IT STOPS BEING THE ONLY LINK. The first attachment design had the
// host reachable ONLY by searching this element backwards, which meant a consumer had to run
// `DocumentReference?related=<host>` to discover what a letter carried. The forward link now lives
// on the host (one `Composition.section.entry`, or `ServiceRequest.supportingInfo`), and this
// element is the return path for a reader that starts from the document.
//
// DO NOT RELY ON SEARCHING IT UNTIL IT IS MEASURED. `related` is NOT among the search parameters
// the server CapabilityStatement declares for DocumentReference (`identifier` and `description`
// are), and this store's documented behaviour for a parameter it does not recognise is to DROP IT
// SILENTLY rather than error. So `DocumentReference?related=Composition/{id}` may be returning the
// whole compartment with the client rendering whatever came back, which looks identical to working.
// Measure it the way the template identifier search was measured before List exposure was
// declared: a bogus `related` value that returns rows means no filtering is happening. Until then,
// resolve the reference rather than search for it. FHIR-100 carries the probe and the decision
// that follows it: declare and index the parameter, or stop searching it.
* context.related 0..* MS
* context.related ^short = "What this document was assembled from or sent with -- the packet, and its host"
* context.related ^definition = """
Other resources this document is related to. For a rendered outbound artifact this is the BACK
POINTER: the attachment packet whose members it renders, and the host that packet travelled with
(a letter's `Composition`, a referral's `ServiceRequest`).
The FORWARD link is on the host and is the one to navigate: a letter names its packet in one
`Composition.section.entry`, a referral in `ServiceRequest.supportingInfo`. This element exists so
a reader that starts from the document can get back, not so the relationship can be discovered by
search -- `related` is not a declared search parameter on this server.
"""
* context.period 0..1 MS
* context.period ^short = "Time period of documented service. Only 'start' expected"
* context.period ^definition = """
The time period over which the service described by the document was provided. This represents the clinical
relevance timeframe, not when the document was created. Critical for understanding temporal context.
Examples:
- Discharge summary: Admission to discharge dates
- Consultation note: Consultation appointment time
- Progress note: Specific day of care
- Procedure report: Surgery start to end time
If only a point in time is relevant, use 'start' only.
For ongoing care, 'end' may be absent.
"""
* context.period.start 1..1 MS
* context.period.end 0..1
// Author and Date fields
* author 0..* MS
* author ^short = "Who wrote the document"
* author ^definition = """
Identifies who was responsible for writing the document content. Can include multiple authors for collaborative
documents. Note the distinction:
- Author: Who wrote/created the content
- Authenticator: Who legally verified/signed the document
- Custodian: Organization maintaining the document
- in EMRs, you probably want to be using 'authenticator' rather than 'author' here.
- eg: 'author' may be a medical student, 'authenticator' could be the doc signing off.
- 'authenticator' is the person who is medically responsible for the content of this document.
Authors can only be EMR users in this context, referenced as a **Practitioner** (the primary
provider identity in this IG) or as a **PractitionerRole** where the clinic/role binding is
part of the assertion.
Order matters - list primary author first.
"""
* author only Reference(NexusEmrCorePractitionerRole or NexusEmrCorePractitioner)
* date 0..1 MS
* date ^short = "When DocumentReference was created (not document date)"
* date ^definition = """
When this DocumentReference resource was created in the system. This is NOT necessarily when the document itself
was created or when the documented service occurred.
Timing relationships:
- date: When DocumentReference was created (this field)
- content.attachment.creation: When document was created
- context.period: When clinical service occurred
Example: A discharge summary for April 10-15 admission might be:
- Service period: 2025-04-10 to 2025-04-15
- Document created: 2025-04-15T14:00:00
- DocumentReference created: 2025-04-16T09:00:00 (next day upload)
This field is primarily for technical/audit purposes.
"""
// CQL PRIMARY CODE PATH. Names the code-valued element a bare CQL retrieve filters on, so
// `[DocumentReference: "some-code"]` knows what to compare. Base R4's own CQL ModelInfo declares no
// `primaryCodePath` for this resource, and the consequence is not a compile error: the
// retrieve COMPILES, the translator only warns, and the criterion silently filters on
// nothing while its data-requirements manifest emits a `codeFilter` with no `path` (which
// violates FHIR's own drq-1 invariant). Declaring it here is what makes the natural
// authoring form correct rather than merely accepted.
//
// The extension is HL7's own, from hl7.fhir.uv.extensions.r4 which this IG already depends
// on -- not a Nexus canonical. Read by ts/codegen/cql/gen-modelinfo.ts.
* ^extension[+].url = $cql-primary-code-path
* ^extension[=].valueString = "type"