Specimen Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-specimen |
|---|---|
| Status | draft (experimental) · 1.26.0 |
| Base | Specimen (constraint) |
| Source | FSH · JSON |
Nexus EMR profile for Specimen -- the physical sample a lab result was produced from. Currently a pass-through type: the platform resolves ServiceRequest.specimen references and traverses into Specimen from DiagnosticReport, but reads none of its own fields. First pass; the heritage-EMR reconciliation is unresolved.
FSH
The authored source of truth: resources/StructureDefinition-nexus-emr-core-specimen.fsh (edit on GitHub). One FSH file may define several related artifacts.
// NexusEmrCoreSpecimen.fsh
// FIRST PASS. The physical sample a lab result was produced from.
//
// WHY THIS PROFILE EXISTS -- and the honest state of the evidence. This profile was cut from the
// 1.12.0 scope increase and then restored, so the reasoning is recorded here rather than left to
// be re-derived:
//
// * ONE real production site touches Specimen today:
// `EReferralService/.../ReferenceResolver/ServiceRequestReferenceResolver.cs:108-111`, which
// resolves and rewrites `ServiceRequest.specimen` references inside an eReferral message
// bundle. That is reference PLUMBING -- it never reads a Specimen's own fields.
// * The patient cache TRAVERSES into it: `_CONTAINMENT_FIELDS` maps
// `DiagnosticReport.(result, specimen, imagingStudy)`.
// * TypedFhir carries a frozen `lab-report.bundle.json` golden vector in which a Specimen rides
// inside a lab report. That exercises the CODEC, which is profile-agnostic, so it is not an
// argument for a profile.
// * The synthetic generator emits ~23 per corpus.
//
// No store, service or component reads `status`, `type` or `accessionIdentifier`. So this profile
// governs a type the platform currently only PASSES THROUGH -- which is exactly why the shape it
// pins is minimal and why the heritage-EMR question below is the thing that actually matters.
//
// FIRST-PASS SCOPE. Skeleton, dating, and the accession-identifier contract. Deliberately NOT
// settled: specimen `type` terminology (the SNOMED specimen hierarchy is large and no agreed
// subset exists), container/processing modelling (nothing consumes below study level), and the
// heritage-EMR reconciliation described on `accessionIdentifier` and `subject`.
Alias: $NexusEmrCoreSpecimen = ../StructureDefinition/nexus-emr-core-specimen
// Profile Definition
Profile: NexusEmrCoreSpecimen
Parent: Specimen
Id: nexus-emr-core-specimen
Title: "Specimen Profile"
Description: "Nexus EMR profile for Specimen -- the physical sample a lab result was produced from. Currently a pass-through type: the platform resolves ServiceRequest.specimen references and traverses into Specimen from DiagnosticReport, but reads none of its own fields. First pass; the heritage-EMR reconciliation is unresolved."
* ^url = $NexusEmrCoreSpecimen // Canonical URL from alias
* ^status = #draft
* insert NoResourceNoteExtension
* ^experimental = true
* . ^short = "Nexus EMR Specimen Core"
* . ^definition = """
A physical sample collected from a patient for examination.
In this platform, chiefly a pass-through and correlation resource: it links a result to the
sample and to the performing lab's accession. See the profile notes on the heritage-EMR
situation before building anything that depends on it being present.
"""
// THE effective date for this profile: when the sample was collected, falling back to when the lab
// received it. Collection is the clinically meaningful moment -- a result's relevance dates to the
// draw, not to the lab's intake.
* insert EffectiveDate([[collection.collectedDateTime | collection.collectedPeriod.start | receivedTime]])
* insert Salient(type, type, coded)
* insert Salient(status, status, code)
* insert Salient(date, [[collection.collectedDateTime | collection.collectedPeriod.start | receivedTime]], dateTime)
// SMART on FHIR exposure -- READ-ONLY. A Specimen arrives with the lab result it produced and is
// reached from `DiagnosticReport.specimen`; nothing in this estate authors one on its own, so no
// create, update or delete is offered and no scope grants one.
* insert SmartExposedReadOnly(specimen)
* 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 // Narrative element with human-readable summary
* text ^short = "Narrative"
* text ^definition = "A human-readable narrative summary of the NexusEmrCoreSpecimen resource for human interpretation."
// 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 the specimen"
* identifier ^definition = """
Identifiers for the specimen assigned by the collecting or receiving system.
A business identifier is recommended but not required (identifier is 0..*).
Distinct from `accessionIdentifier` below: this element is the specimen's own id in whatever system minted it; the accession is specifically the performing lab's.
⚠ HERITAGE EMR SITUATION -- UNRESOLVED. Heritage EMRs generally do NOT carry a first-class specimen record. A lab result arrives as an HL7 v2 message (or a rendered report) in which the specimen is implicit in the OBR segment, and no stable specimen identifier is minted at all. So for source-EMR-derived data this element is frequently absent, and where an ingest pipeline does populate it the value is typically synthesized rather than a real source key -- meaning it is NOT stable across re-ingests. Do not build correlation on it for heritage-sourced specimens; use `accessionIdentifier`, which the source message does carry. Whether ingest should mint synthetic specimen identifiers at all, and if so how to make them stable, is an open decision.
If no recognized system exists, implementers MAY invent a URI for the system.
"""
* insert SourceIdentifier(identifier)
// -----------------------------------------
// Accession identifier -- the reason this profile is worth having
// -----------------------------------------
* accessionIdentifier 0..1 MS
* accessionIdentifier ^short = "The performing lab's accession number"
* accessionIdentifier ^definition = """
The identifier assigned by the laboratory that processed the specimen.
This is the value that correlates a result back to the physical sample at the lab, and that reveals
when several results derive from a single draw. It is also what a human reads off a requisition when
phoning the lab, which makes it the identifier most often needed and most often missing.
⚠ HERITAGE EMR SITUATION -- UNRESOLVED. This is the one specimen field heritage EMRs reliably DO
carry, because it rides in the inbound HL7 v2 lab message. But it arrives without a governed system
URI: the accession is scoped to the performing lab and is not unique across labs, so two labs can
legitimately issue the same accession string. The IG does not yet define how to namespace it per
performing lab, so `accessionIdentifier.system` is currently unconstrained and inbound values may
collide. Treat an accession as unique only WITHIN a known performing organization until this is
resolved.
"""
* accessionIdentifier ^comment = "Do not merge with `identifier` -- an accession is lab-scoped and is not a substitute for a specimen identifier. See the definition for the unresolved cross-lab namespacing gap."
* status 0..1 MS
* status ^short = "available | unavailable | unsatisfactory | entered-in-error"
* status ^comment = "`unsatisfactory` is clinically meaningful -- a rejected sample means the test was NOT performed, and a consumer treating the linked result as pending rather than failed will wait forever. 0..1 in R4, so absence must be tolerated and must NOT be read as `available`. Heritage-EMR-derived specimens usually carry no status at all."
* type 0..1 MS
* type ^short = "The kind of sample (blood, urine, swab, ...)"
* type ^comment = "⚠ FIRST PASS -- no binding. The SNOMED specimen hierarchy is large and no agreed subset exists for this EMR. Readers MUST tolerate text-only. Heritage-EMR data typically supplies at most a free-text specimen-source string from the HL7 v2 OBR segment, so text-only is the expected shape, not the exception. 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)."
* subject 0..1 MS
* subject ^short = "The patient the sample came from"
* subject only Reference(NexusEmrCorePatient)
* subject ^definition = """
The patient the specimen was collected from.
0..1 in R4 (a specimen can be environmental or device-derived) and left optional here. Anything
appearing in a patient chart MUST carry it.
⚠ HERITAGE EMR SITUATION -- UNRESOLVED. Where a Specimen is synthesized during lab ingest, the
patient link is inferred from the enclosing DiagnosticReport rather than carried by the source
message. That inference is only as good as the report's own patient matching, so a mis-matched
report propagates its error into the specimen silently. Whether ingest-synthesized specimens should
assert `subject` at all -- versus leaving it absent and letting consumers reach the patient through
`DiagnosticReport.subject` -- is unresolved.
"""
* receivedTime 0..1 MS
* receivedTime ^short = "When the lab received the sample"
* request 0..* MS
* request ^short = "The order this sample was collected for"
* request only Reference(NexusEmrCoreServiceRequest)
* request ^comment = "The inverse of `ServiceRequest.specimen`, which the eReferral reference resolver rewrites when relaying a message bundle. Per the logical-reference model these MAY be identifier-only."
// -----------------------------------------
// Collection
// -----------------------------------------
* collection 0..1 MS
* collection ^short = "How and when the sample was collected"
* collection.collected[x] 0..1 MS
* collection.collected[x] ^short = "When the sample was collected"
* collection.collected[x] ^comment = "THE effective date for this profile, preferred over receivedTime. A choice of dateTime or Period in R4 -- handle both. Heritage-EMR lab messages often carry only the received/report time, in which case this is absent and the effective date falls through to `receivedTime`."
* collection.collector 0..1 MS
* collection.collector ^short = "Who collected the sample"
* collection.collector only Reference(NexusEmrCorePractitioner or NexusEmrCorePractitionerRole)
* collection.bodySite 0..1 MS
* collection.bodySite ^short = "Where on the body the sample was taken from"
* collection.bodySite ^comment = "Readers MUST tolerate text-only."