Provenance Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-provenance |
|---|---|
| Status | draft · 1.26.0 |
| Base | Provenance (constraint) |
| Source | FSH · JSON |
Attribution for AI-mediated and cross-boundary writes: what was produced, when, by which agent (human or non-human), from what inputs, and -- for generated text -- which verbatim source passage each statement rests on. Used standalone against a produced resource, and contained in an AI-suggestion review Task against the suggestion contained alongside it.
TypedFhir API / Pydantic schema
The typed accessor surface Provenance exposes for Provenance — generated from this IG's compiled profile; each typed accessor has a validating raw-FHIR twin (xRaw) where marked. The three ports are parity-enforced.
The AI-facing shape: from typed_fhir.facade.generated.schemas import ProvenanceSchema — model_json_schema() is a structured-output / tool definition; instantiating validates an extraction. Generated source.
class ProvenanceSchema(BaseModel):
"""AI-facing shape of the Provenance profile: the facade's typed accessor
surface (curated + salient fields) as a pydantic model. `model_json_schema()` is a
structured-output / tool schema; instantiating validates an extraction."""
model_config = ConfigDict(extra="forbid")
target: Reference | None = Field(
None,
description=(
"The resource(s) this provenance describes. The resources produced or changed by the "
"activity. For an AI write-back this is the resource the AI produced -- the drafted "
"DocumentReference, the suggested MedicationRequest, the Task. Multiple targets are "
"permitted and are the normal case for a single AI action that writes a bundle: one "
"Provenance covering the set is preferable to one per resource, because the action "
"was one decision. Note: Per the Nexus EMR logical-reference model these MAY be "
"identifier-only. A consumer resolving provenance MUST handle a reference with no "
"literal `reference` -- this is the single most common cause of provenance appearing "
"'missing' when it is present. Provenance.target — 1..*"
),
)
recorded: FuzzyDate | None = Field(
None,
description=(
"When this provenance record was created. The instant of time at which the activity "
"was recorded. Note: This can be a little different from the time stamp on the "
"resource if there is a delay between recording the event and updating the provenance "
"and target resource. Provenance.recorded — 1..1"
),
)
reason: Concept | None = Field(
None,
description=(
"Reason the activity is occurring. The reason that the activity was taking place. "
"Provenance.reason — 0..*"
),
)
activity: Concept | None = Field(
None,
description=(
"What kind of activity produced the target. An activity is something that occurs over "
"a period of time and acts upon or with entities; it may include consuming, "
"processing, transforming, modifying, relocating, using, or generating entities. "
"Note: Deliberately unbound. R4's example binding (`provenance-activity-type`) does "
"not anticipate AI-mediated authorship -- draft-generated, AI-suggested, "
"human-accepted -- and asserting it would mis-describe the data. Treat the activity "
"vocabulary as open and read `activity.text`, which is what the examples carry. A "
"validator run against the base spec will warn that no code was supplied; that "
"warning is expected here. Provenance.activity — 0..1. codes (extensible): ADM | ALY "
"| ANONY | APPEND | ATND | AUT | AUTHEN | BBY | …"
),
)
agent: dict | None = Field(
None,
description=(
"Who took part in the action. Who or what was responsible for the activity. For an "
"AI-mediated action there are normally TWO agents and both matter: • the **non-human "
"agent** that generated the content -- a Device, identifying the harness and, where a "
"consumer needs it, the model; • the **human** who reviewed, accepted or attested to "
"it -- a Practitioner. Recording only the human makes AI-drafted content "
"indistinguishable from human-authored content, which is the specific outcome this "
"profile exists to prevent. Recording only the AI loses accountability. Note: "
"Includes the AI agent and its human supervisor where content was AI-drafted. "
"Provenance.agent — 1..*"
),
)
entity: dict | None = Field(
None,
description=(
"The inputs the activity derived from -- for AI, the record context it was given. The "
"resources the activity used as input. For an AI action this is the record context "
"the model was given: the resources drawn from the patient compartment that informed "
"the output. This is what makes an AI output auditable rather than merely "
"attributable -- \"this draft was generated from these twelve resources\" is a "
"reviewable claim, where \"this draft came from the harness\" is not. Note: Records "
"WHICH RESOURCES the activity read, and stays at that grain deliberately: "
"statement-level attribution -- which generated sentence rests on which passage -- "
"rides the `attributedFact` extension instead, and a citation there MAY point back to "
"the entity it was drawn from. For a chart-wide compartment load, listing every "
"member may still be prohibitively large, and a summarizing convention (the "
"compartment snapshot's own identifier rather than each member) is the expected "
"direction for that case. Provenance.entity — 0..*"
),
)
date: FuzzyDate | None = Field(
None,
description=(
"When the activity happened. The period during which the activity occurred. Note: "
"Preferred over `recorded` as THE date. A provenance written asynchronously (a queued "
"write-back) has a `recorded` well after the action; dating the action to the "
"bookkeeping timestamp misplaces it in every timeline. Salient field — "
"occurredDateTime | occurredPeriod.start | recorded"
),
)