Correction Task Profile¶
| Canonical | ../StructureDefinition/nexus-correction-task |
|---|---|
| Status | draft · 1.26.0 |
| Base | Task Profile (constraint) |
| Source | FSH · JSON |
A patient's request to correct their own record, or to log a disagreement where a correction was refused, carried as an ordinary clinical task with the statutory correction vocabulary. Same worklist, same shape, narrower status set. AN ACCESS REQUEST IS NOT HELD TO THIS PROFILE. Every code in this vocabulary describes a correction or a disagreement, so a request to be given a copy of the record has no terminal state here it could truthfully reach. It shares the privacy-request worklist bin and stays on the base clinical task, which binds the wider set.
FSH
The authored source of truth: resources/StructureDefinition-nexus-correction-task.fsh (edit on GitHub). One FSH file may define several related artifacts.
// StructureDefinition-nexus-correction-task.fsh
// A patient's request to correct their own record, as a clinical task.
//
// WHY A PROFILE AND NOT JUST A CODE. Until 1.26.0 this guide deliberately had no correction task
// profile, and the reason written down was that "privacy work has to land in the same worklist as
// everything else, and that worklist reads this profile". That reason was wrong on the facts: a
// worklist searches `Task?owner=...`, and every Task comes back whatever `meta.profile` says.
// Nothing in this estate filters a task query by profile, so a second profile costs nothing in
// reachability -- these tasks appear in the same inbox, sorted into the same bins, as before.
//
// What the profile buys is the thing a code cannot: the correction lifecycle is the STATUTORY
// record of a decision about someone's chart, and it needs a vocabulary of its own that is closed
// and is not available to ordinary work. The base profile's binding admits both vocabularies
// because a FHIR binding cannot be conditional on a sibling element; this profile narrows it to
// the correction half, which is a legitimate narrowing of a required binding and therefore valid
// derivation. Ordinary tasks are kept off the correction codes from the other direction, by
// `nexus-task-bizstatus-scope` on the base.
//
// A CORRECTION TASK IS STILL AN ORDINARY TASK. It derives from the clinical task profile rather
// than from Task, so every constraint that profile makes still holds and every consumer that reads
// clinical tasks reads these unchanged. The narrowing is additive.
//
// ⚠ WRITERS MUST DECLARE IT. `meta.profile` carries no weight unless it is written, and today
// nothing in this estate stamps a profile onto a Task at all. Until the privacy path does, an
// instance is held to the base profile alone -- which still blocks a correction code on a
// non-privacy task, but does not hold a privacy task to the correction vocabulary. Declaring the
// profile is what closes that second half.
Profile: NexusCorrectionTask
Parent: NexusEmrCoreClinicalTask
Id: nexus-correction-task
Title: "Correction Task"
Description: "A patient's request to correct their own record, or to log a disagreement where a correction was refused, carried as an ordinary clinical task with the statutory correction vocabulary. Same worklist, same shape, narrower status set. AN ACCESS REQUEST IS NOT HELD TO THIS PROFILE. Every code in this vocabulary describes a correction or a disagreement, so a request to be given a copy of the record has no terminal state here it could truthfully reach. It shares the `privacy-request` worklist bin and stays on the base clinical task, which binds the wider set."
* ^url = "../StructureDefinition/nexus-correction-task"
* ^status = #draft
// NO `insert NoResourceNoteExtension` HERE. The parent profile (nexus-emr-core-clinical-task) already
// asserts it and constraints are INHERITED, so re-asserting duplicates the key in this
// profile's snapshot -- ill-formed, and rendered twice in the Constraints table.
* ^experimental = false
* ^date = "2026-09-14"
* ^publisher = "WELLSTAR Technologies Corp."
// The bin. Required here where the base leaves it optional: a correction task that does not say it
// is privacy work is indistinguishable from ordinary work in the one place a reader looks.
* code 1..1 MS
// PATTERN, NOT FIXED. `(exactly)` compiles to `fixedCodeableConcept`, which R4 defines as "SHALL be
// exactly the value ... missing elements/attributes must also be missing" -- so it forbids a
// `display`, and it forbids the SECOND coding this profile's own comment tells a producer to send.
// It also made the profile's only example non-conformant, and would have made dual conformance with
// HL7's `patient-correction-task` impossible, since that profile binds `Task.code` required with no
// fixed value. R4's own guidance on `fixed[x]` says it is "not recommended for Coding and
// CodeableConcept". A pattern pins the bin and leaves the rest open.
* code = NexusTaskCodeCS#privacy-request
* code ^short = "Always `privacy-request`"
* code ^comment = "Fixed, and required where the base profile leaves `code` optional. This is the worklist bin for work arising from someone exercising a right over their own record -- access, correction, or a disagreement to be logged where a correction was refused. It is NAMED FOR THE RIGHT, NOT THE OUTCOME: which of the three this task is, and where it has got to, are read off `businessStatus` and off the optional second `code` coding from the international correction task-type system. THE BIN IS WIDER THAN THIS PROFILE. It also carries access requests, which this profile does not cover, so `code = privacy-request` is not on its own a statement that a task conforms here -- a consumer that needs the correction shape reads `meta.profile`, or reads the correction vocabulary off `businessStatus`."
// The statutory lifecycle. A narrowing of the base's required binding, not a replacement.
* businessStatus 1..1 MS
* businessStatus from NexusCorrectionBusinessStatus (required)
* businessStatus ^short = "Where the correction request has got to"
* businessStatus ^definition = "The correction lifecycle from HL7's Patient Request for Corrections guide: queued, in-review, waiting-for-information, requester-cancelled, accepted, partial-accept, amendment-completed, denied, disagreement-logged, completed. `completed` does NOT mean the work is over. HL7 defines it as the state where a disagreement has been logged AND a formal rebuttal provided; a request that was accepted and amended ends at `amendment-completed`, and one refused without a rebuttal ends at `disagreement-logged`. Do not reach for it because a task is finished."
* businessStatus ^comment = "REQUIRED here, and required on this profile rather than optional as it is on the base: a correction request always has a position in its lifecycle, and an absent one is indistinguishable from a request nobody has looked at. `denied` is the load-bearing value -- it is the refusal that entitles the requester to file a statement of disagreement, and the Statement of Disagreement profile's `partOf` points back at the task that reached it. A refusal is a task whose `status` is `completed` and whose `businessStatus` is `denied`: `failed` would say the system broke, which loses the only fact the statute cares about. The vocabulary is HL7's rather than this guide's on purpose -- the concepts are not local, and a reader outside this estate should not need our value set to understand the outcome."
// NOT CONSTRAINED HERE, though it was tempting: `restriction.period.end`, the statutory response
// deadline. The base profile already documents that this is where a privacy request's legal clock
// lives, and requiring it would be defensible -- but it is a different question from which
// vocabulary the status draws on, and making it mandatory would invalidate stored privacy tasks
// that predate the rule. A deadline is worth requiring; it is worth doing deliberately, with a
// migration, rather than as a side effect of closing a binding.