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 Observation resources (one per turn) and reference them. Cleanest FHIR-native, highest resource count.
  • B — Store the turn array as a DocumentReference JSON attachment; reference by fragment (DocumentReference/xyz#turn=15) via Provenance.entity.what. Lightweight; fragment semantics are DSP-local.
  • C — Keep integer indices on each resource via transcript-turn-refs extension; emit a single Provenance that 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