Skip to content

Fix Patient $purge Purging Resources of Other Patients - #4605

Open
alexanderkiel wants to merge 1 commit into
mainfrom
claude/4596-purge-graph-definition
Open

alexanderkiel wants to merge 1 commit into
mainfrom
claude/4596-purge-graph-definition

Conversation

@alexanderkiel

@alexanderkiel alexanderkiel commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Closes: #4596

Changes

  • ig: new FSH instance PatientPurge (input/fsh/patient-purge.fsh). It produces the GraphDefinition https://blaze-server.org/fhir/GraphDefinition/PatientPurge|1, using R5 cross-version extensions. The IG validator passes with 0 errors.
  • graph-definition: new pure function gd/rev-links. It takes a compiled graph and returns its [type code] tuples. It returns an incorrect anomaly if the graph is outside the restricted subset:
    • the start node isn't Patient
    • a link doesn't start at the start node
    • a link has a path
    • the params aren't a single <code>={ref}
    • the param has a modifier
    • a link goes to another Patient node
    • a link goes to an abstract type
  • db:
    • [:patient-purge id graph] / tx-cmd key :graph (url|version, optional).
    • expand "patient-purge" resolves the GraphDefinition in db-before by url, version and _security=…AccessControl|internal. It pulls it and runs gd/compile and gd/rev-links. It checks that every code is a reference search param of its type that targets Patient. The resulting tuples feed the existing rev-include loop. Without :graph, it keeps the compartment-based expansion.
    • Failures are faults (500), because only Blaze passes the canonical of a GraphDefinition it installed: the GraphDefinition is missing, isn't unique or is invalid. The message names the canonical.
    • The referential integrity message now lists up to 10 referencing resources, followed by and others if there are more. Before, it named one.
  • operation-patient-purge:
    • At prep time, the module copies GraphDefinition-PatientPurge.json from the IG, like the job modules do.
    • At init, it parses that JSON. If no internal copy exists yet, it installs it with a conditional create on url, version and _security, using p/internal. On install it adds the internal security label (current system only) and the read-only tag (both systems).
    • The handler passes the canonical url|version with the purge command.
    • The config now needs :parsing-context, :clock and :rng-fn. blaze.edn is updated.

Link decisions (please review)

The links are in modules/ig/input/fsh/patient-purge.fsh. Each uses the param for the patient the resource is about, e.g. Observation subject, Coverage beneficiary, CareTeam subject, ResearchSubject individual.

These types get no link, because the element can hold several patients: Account (subject 0..*), Appointment, AuditEvent, Group, Patient, Person, Schedule.

Provenance is linked via patient, although target can hold several patients. The Synthea test data has one Provenance per patient, targeting that patient. Without the link, nearly every purge in the integration test would fail on referential integrity.

API Behaviour

These changes are visible to clients:

  • $purge no longer erases resources that reference the patient in a non-focal role.
  • With referential integrity, such resources make the purge fail with 409, listing the referencing resources.
  • Delete conflicts now list up to 10 referencing resources.

docs/api/operation/patient-purge.md has a "Selected Resources" section, badged since 1.14.0, with a table of the compartment and GraphDefinition search params per type. docs/implementation/database.md documents the graph property and the expansion.

Tests

  • gd/rev-links: valid tuples, plus one anomaly per restricted-subset violation.
  • db, resources that must survive:
    • a Group member, an Observation performer and a Coverage subscriber survive the purge
    • without referential integrity the purge succeeds
    • with referential integrity it fails and lists the referencing resources, then succeeds once they're fixed
  • db, GraphDefinition lookup and validation, all failing with a fault:
    • a missing, other-version, unlabelled or duplicate GraphDefinition
    • an invalid graph and a graph outside the subset
    • unknown, non-reference and non-Patient codes
  • db, unit level: expand, prepare-op and tx-cmd spec tests.
  • purge module:
    • an Observation of another patient with the purged patient as performer survives without referential integrity
    • with referential integrity, that Observation makes the purge fail with 409
    • without the installed GraphDefinition, the purge fails with 500 and purges nothing
  • purge module, installation:
    • the GraphDefinition is installed from the IG with the label and tag
    • no transaction happens if it already exists
    • a client copy without the label isn't taken for Blaze's own
  • integration test (.github/scripts/patient-purge.sh):
    • before the purge, $graph with the purge GraphDefinition lists the selected resources
    • after the purge, none of them can be read any more
    • the total number of resources dropped by exactly that count
    • $graph is now also enabled for the patient-purge feature run in build.yml
  • integration test totals: check-resource-totals*.sh ignore GraphDefinition and StructureDefinition, and check-total-number-of-resources.sh ignores GraphDefinitions.

Rolling upgrades of the distributed variant are out of scope, as stated in the issue.

@alexanderkiel
alexanderkiel added this pull request to stack #4607 November 7, 2026 11:54
@alexanderkiel
alexanderkiel force-pushed the claude/4596-purge-graph-definition branch 2 times, most recently from 781ba35 to 331aa9b Compare November 7, 2026 12:29
Base automatically changed from claude/quirky-bohr-82fy7m to main November 7, 2026 12:34
@alexanderkiel
alexanderkiel force-pushed the claude/4596-purge-graph-definition branch 21 times, most recently from d3524d4 to 8de23fa Compare November 9, 2026 07:07
Closes: #4596
Signed-off-by: Alexander Kiel <alexanderkiel@gmx.net>
@alexanderkiel
alexanderkiel force-pushed the claude/4596-purge-graph-definition branch from 8de23fa to 1003da3 Compare November 9, 2026 20:02

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix Patient $purge Purging Resources of Other Patients

1 participant