Where FHIR stretches, and how we extend it
An honest inventory of DSP concepts that FHIR R4 does not model natively, and the design choices the IG has to make for each.
1. Transcript turns as provenance
DSP: provenance: [11, 15, 17] — integer indices into transcript.turns[].
FHIR gap: Provenance expects Reference(Any), not integer offsets. Transcript turns are not a FHIR resource.
Options:
- A — Emit turns as
Observationresources (one per turn) and reference them. Cleanest FHIR-native, highest resource count. - B — Store the turn array as a
DocumentReferenceJSON attachment; reference by fragment (DocumentReference/xyz#turn=15) viaProvenance.entity.what. Lightweight; fragment semantics are DSP-local. - C — Keep integer indices on each resource via
transcript-turn-refsextension; emit a singleProvenancethat references the transcript DocumentReference as a whole. Simplest round-trip; this site recommends it.
Pick Option C for day-1, with a documented path to B/A as consumers need richer traversal. Server-side surfacing via $ground (the one genuinely custom op in the IG).
2. confidence_score
DSP: 0..1 decimal on orders (and likely expanding).
FHIR gap: R4 has no element on MedicationRequest / ServiceRequest / Condition. R5 adds ClinicalImpression.certainty but not on request resources.
Pick: DSP extension confidence-score (valueDecimal) usable on any resource. Align its valueset with R5 certainty when a consumer asks for it via xver. Indexed via SearchParameter + cross-type search — no custom op.
3. payload_version
DSP: major.minor.revision + quality enum + key/value metadata.
FHIR gap: meta.versionId is a monotonic string, not structured; meta.tag is a flat Coding list.
Pick: Complex extension payload-version on Encounter (and on the root Composition for document-centric consumers). Surface a denormalized meta.tag so servers can query without parsing the extension. Advertise accepted/emitted versions via CapabilityStatement extension; normative rule R3 binds the behaviour.
4. spoken_forms
DSP: An array of strings ("HPI", "subjective") — the voice-command handles for a section or concept.
FHIR gap: CodeSystem.concept.designation is the closest analogue but lives on the terminology, not the instance.
Pick: Instance-level extension spoken-forms. Publish a companion CodeSystem of canonical spoken forms with designations; lookups close with standard CodeSystem/$lookup and ValueSet/$expand?filter= — no custom op.
5. update_status = NEW / UPDATED / DELETED
DSP: In-band state flag per resource.
FHIR gap: FHIR uses REST verbs + meta.versionId + history; no inline flag.
Pick: Prefer FHIR semantics — a transaction Bundle with POST (new), PUT (update), DELETE (deleted). If the DSP producer must retain the flag verbatim, expose it as a Provenance.activity code. Consumers read deltas via Encounter/$everything?_since= — no custom op.
6. display_description.locale (localized labels)
DSP: Per-locale labels for the section/concept.
FHIR: Use translation extension on string/Coding (http://hl7.org/fhir/StructureDefinition/translation).
Pick: Reuse the core translation extension. No DSP-specific extension needed.
7. Follow-up without an appointment
DSP: Provider-intent "see me in 2 weeks, PRN" — not a scheduled visit.
FHIR gap: Appointment is booked; ServiceRequest is generic.
Pick: DspServiceRequest-FollowUp profile on ServiceRequest with return-in, approximation, prn extensions. Downstream scheduling realizes it as Appointment.basedOn via PlanDefinition/$apply / ActivityDefinition/$apply — no custom op.
8. Search terms / synonyms
DSP: search_terms[] with a scope and free text.
FHIR gap: No UX-hint slot on clinical resources.
Pick: Extension search-terms (repeating complex). Consider indexing them server-side via SearchParameter for partner-side UIs.
9. Recording sources + session identifiers
DSP: DAXAPP, DAXKIT.haiku, DAXKIT.teams, PMM.
FHIR: Media.type + DSP recording-source extension (valueCode, bound to DSP CodeSystem). Normative rule R2 binds content access to a SMART-scoped Binary endpoint.
10. Encounter accompanied_by
DSP: Free-form name + relationship string ("Jane Doe", "Spouse").
FHIR: RelatedPerson referenced from Encounter.participant with type = SNOMED 303071001 (accompanying). Resolution via RelatedPerson/$match (mirrors base Patient/$match). If the identity is not resolvable, keep as participant.individual.display.
Open questions worth raising with the DSP team
- Will
confidence_scoreextend beyond orders to conditions / observations? (IG extension context should anticipate this.) - Is the
referralorder subtype schema public? (Currently 404s in the docs.) - Is there a planned
observation(vitals) resource? FHIRObservationis ready; the IG should define a profile even if DSP hasn't shipped one yet. - Will DSP adopt
SubscriptionTopicnatively, or is theexternal_callback_urlcustom forever? - Will turn indices ever need to be stable across revisions (for a refreshed transcript), or are they payload-local?