Condition

DSP condition resources map almost directly onto FHIR Condition. The fit is near-perfect; the only extensions needed are DSP-specific metadata (spoken forms, transcript turn provenance, confidence).

DSP content_type

condition

FHIR target

Condition (R4) + US Core Condition-Problems / Condition-Encounter-Diagnosis

Field-by-field

DSPFHIR R4Round-trip mechanism
idCondition.idNative — exact
descriptionCondition.code.textNative — exact
condition_concept.codes (SNOMED / ICD-10)Condition.code.coding[]Native — exact (multi-coded)
condition_concept.concept_idCondition.code.extension[dsp-concept-id]DSP extension — exact
clinical_statusCondition.clinicalStatusNative — exact
verification_statusCondition.verificationStatus + extension[dsp-assertion-category]DSP nuances (asserted vs history) preserved on the extension
categoryCondition.categoryNative — exact
severityCondition.severityNative — bind to SNOMED 24484000/6736007/255604002
onsetCondition.onset[x]Native — exact
abatementCondition.abatement[x]Native — exact
stageCondition.stageNative — exact
evidenceCondition.evidence.code.textNative — exact
body_siteCondition.bodySiteNative; prefer SNOMED body structure codes
notesCondition.note.textNative — exact
confidence_scoreextension[dsp-confidence-score]DSP extension — exact
spoken_formsextension[dsp-spoken-forms] (repeating)DSP extension — exact
provenance (turn indices)extension[dsp-transcript-turn-ref] (one per index)One extension per index, each with a versioned DocumentReference reference — see indexing
parent_resourceCondition.encounterNative — exact
children_resourcesInverse via Observation.focus, ServiceRequest.reasonReference, etc.Recovered by traversal at read
external_referenceidentifier + meta.source + extension[dsp-linkage-confidence]DSP extension — exact

Every DSP-originated field lands in either a native FHIR field or a dsp-* extension. The canonical $graphql read reconstructs the DSP payload directly from those slots — no inverse mapping engine required.

Side-by-side example

DSP

{
  "id": "condition-001",
  "context": { "content_type": "condition" },
  "description": "Moderate osteoarthritis of the right knee",
  "condition_concept": {
    "text": "Moderate osteoarthritis of the right knee",
    "concept_id": "dragon-cid-00172",
    "codes": [
      {"system":"snomed","identifier":"239873007"},
      {"system":"icd10","identifier":"M17.11"}
    ]
  },
  "clinical_status": "active",
  "verification_status": "confirmed",
  "category": "encounter-diagnosis",
  "severity": "moderate",
  "body_site": "right knee",
  "provenance": [11, 15],
  "confidence_score": 0.94,
  "spoken_forms": ["arthritis in the right knee"]
}

FHIR R4 (DSP-FHIR profile)

{
  "resourceType": "Condition",
  "id": "condition-001",
  "meta": {
    "profile": ["https://dsp-fhir.org/StructureDefinition/DspCondition"],
    "source":  "https://dsp-fhir.org/source/dsp-payload-abc"
  },
  "subject":   {"reference":"Patient/pat-67890"},
  "encounter": {"reference":"Encounter/enc-12345"},

  "clinicalStatus":     {"coding":[{"system":"http://terminology.hl7.org/CodeSystem/condition-clinical","code":"active"}]},
  "verificationStatus": {"coding":[{"system":"http://terminology.hl7.org/CodeSystem/condition-ver-status","code":"confirmed"}]},
  "category":[{"coding":[{"system":"http://terminology.hl7.org/CodeSystem/condition-category","code":"encounter-diagnosis"}]}],
  "severity": {"coding":[{"system":"http://snomed.info/sct","code":"6736007","display":"Moderate"}]},

  "code": {
    "text": "Moderate osteoarthritis of the right knee",
    "coding": [
      {"system":"http://snomed.info/sct","code":"239873007"},
      {"system":"http://hl7.org/fhir/sid/icd-10-cm","code":"M17.11"}
    ],
    "extension": [
      {"url":"https://dsp-fhir.org/StructureDefinition/dsp-concept-id",
       "valueString":"dragon-cid-00172"}
    ]
  },

  "bodySite":[{"text":"right knee"}],

  "extension":[
    {"url":"https://dsp-fhir.org/StructureDefinition/dsp-confidence-score",
     "valueDecimal":0.94},

    {"url":"https://dsp-fhir.org/StructureDefinition/dsp-spoken-forms",
     "valueString":"arthritis in the right knee"},

    {"url":"https://dsp-fhir.org/StructureDefinition/dsp-assertion-category",
     "valueCode":"asserted"},

    // One extension per turn index. The transcript reference is version-pinned (R1)
    // so the integer index remains valid across re-transcription.
    {"url":"https://dsp-fhir.org/StructureDefinition/dsp-transcript-turn-ref",
     "extension":[
       {"url":"transcript","valueReference":{"reference":"DocumentReference/dr-transcript-001/_history/3"}},
       {"url":"turn","valueInteger":11}
     ]},
    {"url":"https://dsp-fhir.org/StructureDefinition/dsp-transcript-turn-ref",
     "extension":[
       {"url":"transcript","valueReference":{"reference":"DocumentReference/dr-transcript-001/_history/3"}},
       {"url":"turn","valueInteger":15}
     ]}
  ]
}
Indexing & grounding. DSP's provenance: [11, 15] is two integer offsets into a transcript. The IG models each offset as one dsp-transcript-turn-ref extension carrying a version-pinned DocumentReference reference and a valueInteger. One extension per index keeps them ordered, queryable, and re-transcription-safe (per R1 — Turn-index stability). Resolving the underlying turn text is a follow-on read of the referenced DocumentReference attachment; see $ground.
Lossless assertion. DSP's assertion axis (asserted / history / denied / suspected) does not bijectively map to FHIR's verificationStatus (asserted ∪ history → confirmed). The IG always preserves the original DSP value on extension[dsp-assertion-category], and the canonical read prefers that extension before falling back to verificationStatus.

DSP → FHIR (write projection)

On ingest the server projects the DSP condition onto a profiled Condition using the field landings shown above. The IG ships an executable FHIR Mapping Language skeleton as a reference implementation; partners are not required to use FML in production — a hand-written projection that satisfies the same field mapping is conformant.

map "https://dsp-fhir.org/StructureMap/DspConditionToCondition" = "DspConditionToCondition"

uses "https://dsp-fhir.org/StructureDefinition/DspConditionResource" alias DspCondition as source
uses "http://hl7.org/fhir/StructureDefinition/Condition" alias Condition as target

group DspConditionToCondition(source src : DspCondition, target tgt : Condition) {
  src.id as id -> tgt.id = id;

  src.payload as p then {
    // Primary code path: structured code+system
    p.code as c -> tgt.code as code, code.coding as coding then {
      c -> coding.code = c;
      p.code_system as sys -> coding.system = sys;
      p.display as d -> coding.display = d;
    } "code";
    // Fallback: display text only
    p.display as d -> tgt.code as code, code.text = d "display-fallback";

    // Assertion category -> verificationStatus + preserve as extension
    p.assertion as a -> tgt.extension as ext then {
      a -> ext.url = 'https://dsp-fhir.org/StructureDefinition/dsp-assertion-category',
           ext.value = create('code') as v, v.value = a;
    } "assertion-ext";
    p.assertion as a where (a = 'asserted' or a = 'history') -> tgt.verificationStatus as vs,
      vs.coding as co, co.system = 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
      co.code = 'confirmed' "verif-confirmed";
    p.assertion as a where a = 'denied' -> tgt.verificationStatus as vs,
      vs.coding as co, co.system = 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
      co.code = 'refuted' "verif-refuted";
    p.assertion as a where a = 'suspected' -> tgt.verificationStatus as vs,
      vs.coding as co, co.system = 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
      co.code = 'provisional' "verif-provisional";

    // Concept id hangs off the CodeableConcept
    p.concept_id as cid -> tgt.code as code, code.extension as ext then {
      cid -> ext.url = 'https://dsp-fhir.org/StructureDefinition/dsp-concept-id',
             ext.value = create('string') as v, v.value = cid;
    } "concept-id";
  };

  // Resource-level metadata
  src.confidence as conf -> tgt.extension as ext then {
    conf -> ext.url = 'https://dsp-fhir.org/StructureDefinition/dsp-confidence-score',
            ext.value = create('decimal') as v, v.value = conf;
  } "confidence";

  // One extension per turn index. The version-pinned 'transcript' element is added by the
  // controller before persisting (it is not in the DspResource source — see R1).
  src.transcript_turn_refs as t -> tgt.extension as ext then {
    t -> ext.url = 'https://dsp-fhir.org/StructureDefinition/dsp-transcript-turn-ref',
         ext.extension as turnExt,
         turnExt.url = 'turn',
         turnExt.value = create('integer') as v, v.value = t;
  } "turn-ref";

  src.spoken_forms as sf -> tgt.extension as ext,
    ext.url = 'https://dsp-fhir.org/StructureDefinition/dsp-spoken-forms',
    ext.value = create('string') as v, v.value = sf "spoken-form";

  // Default clinicalStatus - caller may override on ingest
  src -> tgt.clinicalStatus as cs, cs.coding as co,
    co.system = 'http://terminology.hl7.org/CodeSystem/condition-clinical',
    co.code = 'active' "clinical-default";
}

FHIR → DSP (canonical $graphql read)

The reverse direction is a read, not a transform. Standard FHIR $graphql selects every native field and DSP-namespaced extension that the write projection populated. A small adapter renames the result into the DSP shape. No FML inverse engine is required, and no DSP-originated field is lost — every input slot has a defined output slot.

Canonical query

POST [fhir-base]/$graphql with the condition id (or fan out from ConditionList(encounter:) to retrieve every Condition on an encounter):

query DspCondition($id: ID!) {
  Condition(id: $id) {
    id
    meta { profile source versionId lastUpdated }

    code {
      text
      coding { system code display }
      conceptId: extension(url: "https://dsp-fhir.org/StructureDefinition/dsp-concept-id") {
        valueString
      }
    }

    clinicalStatus     { coding { system code } }
    verificationStatus { coding { system code } }
    category           { coding { system code } }
    severity           { coding { system code display } text }
    bodySite           { coding { system code display } text }
    note               { text }

    # Native onset/abatement choice fields
    onsetDateTime
    onsetString
    abatementDateTime

    # DSP-originated metadata as primitive extensions
    confidence: extension(url: "https://dsp-fhir.org/StructureDefinition/dsp-confidence-score") {
      valueDecimal
    }
    spokenForms: extension(url: "https://dsp-fhir.org/StructureDefinition/dsp-spoken-forms") {
      valueString
    }
    assertion: extension(url: "https://dsp-fhir.org/StructureDefinition/dsp-assertion-category") {
      valueCode
    }

    # One repeating extension per turn index, each with its own versioned transcript ref
    turnRefs: extension(url: "https://dsp-fhir.org/StructureDefinition/dsp-transcript-turn-ref") {
      transcript: extension(url: "transcript") { valueReference { reference } }
      turn:       extension(url: "turn")       { valueInteger }
    }
  }
}

DSP reconstruction adapter

The adapter is a deterministic shape-rename. It prefers dsp-* extensions over derived FHIR fields where the IG has guaranteed exact preservation (e.g. assertion):

function toDspCondition(c) {
  const turnRefs = c.turnRefs ?? [];
  return {
    id: c.id,
    context: { content_type: 'condition' },
    description: c.code?.text,
    condition_concept: {
      text: c.code?.text,
      concept_id: c.code?.conceptId?.[0]?.valueString,
      codes: (c.code?.coding ?? []).map(toDspCode),
    },
    clinical_status:     c.clinicalStatus?.coding?.[0]?.code,
    verification_status: c.verificationStatus?.coding?.[0]?.code,
    // Prefer the lossless DSP extension; fall back to verificationStatus
    assertion: c.assertion?.[0]?.valueCode
            ?? deriveAssertion(c.verificationStatus),
    category:  c.category?.[0]?.coding?.[0]?.code,
    severity:  normalizeSeverity(c.severity),
    body_site: c.bodySite?.[0]?.text ?? c.bodySite?.[0]?.coding?.[0]?.display,
    onset:     c.onsetDateTime ?? c.onsetString,
    abatement: c.abatementDateTime,
    notes:     c.note?.map(n => n.text),
    confidence_score: c.confidence?.[0]?.valueDecimal,
    spoken_forms:     c.spokenForms?.map(e => e.valueString) ?? [],
    provenance:       turnRefs.map(t => t.turn?.valueInteger),
    transcript_ref:   turnRefs[0]?.transcript?.valueReference?.reference,
  };
}
No data loss. Every DSP-originated field has a declared FHIR landing — native or dsp-* extension — and the canonical read selects each one explicitly. Profile-added defaults (status, intent, hardcoded categories, terminology canonicalization) are profile shape, not DSP data, and are intentionally not reconstructed.

Servers without $graphql can use the documented REST fallback — see $graphql fallbacks. The same field landings apply.

SQL-on-FHIR v2 ViewDefinitions that flatten every field above — including DSP extensions — into a tabular projection. Runnable as-is on any spec-conformant engine (Pathling, sof-exec, Aidbox SQL-on-FHIR, Databricks). See the SQL-on-FHIR v2 spec. These ViewDefinitions also ship as JSON in the IG zip.

dsp_condition — DSP Condition

Flattens a DSP condition resource: status, severity, onset, abatement, primary code.

{
  "resourceType": "ViewDefinition",
  "url": "https://dsp-fhir.org/ViewDefinition/dsp-condition",
  "name": "dsp_condition",
  "title": "DSP Condition",
  "status": "draft",
  "description": "Flattens a DSP condition resource: status, severity, onset, abatement, primary code.",
  "resource": "Condition",
  "fhirVersion": [
    "4.0.1"
  ],
  "select": [
    {
      "column": [
        {
          "name": "id",
          "path": "id",
          "type": "id",
          "description": "Server-assigned logical id."
        },
        {
          "name": "version_id",
          "path": "meta.versionId",
          "type": "id",
          "description": "FHIR version id (drives NEW/UPDATED classification)."
        },
        {
          "name": "last_updated",
          "path": "meta.lastUpdated",
          "type": "instant",
          "description": "Instant of last mutation."
        },
        {
          "name": "meta_source",
          "path": "meta.source",
          "type": "uri"
        },
        {
          "name": "payload_version",
          "path": "meta.tag.where(system='https://dsp-fhir.org/CodeSystem/payload-version').code.first()",
          "type": "code",
          "description": "DSP payload version this resource was last emitted under."
        },
        {
          "name": "confidence_score",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/confidence-score').value.ofType(decimal)",
          "type": "decimal",
          "description": "DSP confidence (0..1)."
        },
        {
          "name": "transcript_ref",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/transcript-turn-refs').extension('transcript').value.ofType(Reference).reference",
          "type": "string",
          "description": "DocumentReference/<id>/_history/<v> that pins the transcript version for turn indices."
        },
        {
          "name": "turn_indices",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/transcript-turn-refs').extension('turn').value.ofType(integer)",
          "type": "integer",
          "collection": true,
          "description": "Turn indices joined by $ground into transcript content."
        },
        {
          "name": "spoken_forms",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/spoken-forms').extension('form').value.ofType(string)",
          "type": "string",
          "collection": true
        },
        {
          "name": "search_terms",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/search-terms').extension('term').value.ofType(string)",
          "type": "string",
          "collection": true
        },
        {
          "name": "subject_patient_id",
          "path": "subject.reference.substring(8)",
          "type": "string"
        },
        {
          "name": "encounter_id",
          "path": "encounter.reference.substring(10)",
          "type": "string"
        },
        {
          "name": "clinical_status",
          "path": "clinicalStatus.coding.code.first()",
          "type": "code"
        },
        {
          "name": "verification_status",
          "path": "verificationStatus.coding.code.first()",
          "type": "code"
        },
        {
          "name": "category_code",
          "path": "category.coding.where(system='http://terminology.hl7.org/CodeSystem/condition-category').code.first()",
          "type": "code"
        },
        {
          "name": "severity_code",
          "path": "severity.coding.code.first()",
          "type": "code"
        },
        {
          "name": "code_text",
          "path": "code.text",
          "type": "string"
        },
        {
          "name": "snomed_code",
          "path": "code.coding.where(system='http://snomed.info/sct').code.first()",
          "type": "code"
        },
        {
          "name": "icd10_code",
          "path": "code.coding.where(system='http://hl7.org/fhir/sid/icd-10-cm').code.first()",
          "type": "code"
        },
        {
          "name": "primary_display",
          "path": "code.coding.display.first()",
          "type": "string"
        },
        {
          "name": "body_site_code",
          "path": "bodySite.coding.code.first()",
          "type": "code"
        },
        {
          "name": "onset_datetime",
          "path": "onset.ofType(dateTime)",
          "type": "dateTime"
        },
        {
          "name": "onset_string",
          "path": "onset.ofType(string)",
          "type": "string"
        },
        {
          "name": "abatement_datetime",
          "path": "abatement.ofType(dateTime)",
          "type": "dateTime"
        },
        {
          "name": "stage_summary",
          "path": "stage.summary.text.first()",
          "type": "string"
        },
        {
          "name": "recorded_date",
          "path": "recordedDate",
          "type": "dateTime"
        },
        {
          "name": "priority",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/dsp-resource-priority').value.ofType(code)",
          "type": "code"
        },
        {
          "name": "concept_id",
          "path": "extension('https://dsp-fhir.org/StructureDefinition/dsp-concept-id').value.ofType(string)",
          "type": "string"
        }
      ]
    }
  ]
}

dsp_condition_coding — DSP Condition coding (unnested)

One row per Condition.code.coding so SNOMED+ICD-10 co-codings are queryable.

{
  "resourceType": "ViewDefinition",
  "url": "https://dsp-fhir.org/ViewDefinition/dsp-condition-coding",
  "name": "dsp_condition_coding",
  "title": "DSP Condition coding (unnested)",
  "status": "draft",
  "description": "One row per Condition.code.coding so SNOMED+ICD-10 co-codings are queryable.",
  "resource": "Condition",
  "fhirVersion": [
    "4.0.1"
  ],
  "select": [
    {
      "column": [
        {
          "name": "condition_id",
          "path": "id",
          "type": "id"
        }
      ],
      "select": [
        {
          "forEach": "code.coding",
          "column": [
            {
              "name": "system",
              "path": "system",
              "type": "uri"
            },
            {
              "name": "code",
              "path": "code",
              "type": "code"
            },
            {
              "name": "display",
              "path": "display",
              "type": "string"
            },
            {
              "name": "user_selected",
              "path": "userSelected",
              "type": "boolean"
            }
          ]
        }
      ]
    }
  ]
}