Repository navigation
feat(operations): add Patient $purge for GDPR erasure - #106
Merged
Merged
Conversation
A FHIR delete keeps the data in history, so it cannot serve an erasure request. Patient $purge (FHIR 6.0.0-ballot3) is now served for R4 and R5: it hard-deletes every current and historical version of the Patient compartment and then of the Patient, publishes no events, and returns an OperationOutcome with the removed counts. AuditEvent and Group are kept. The Patient is matched by id, not through 'link', and is removed last so that a failed run can be retried. Before deleting anything the operation checks that the compartment search parameters are supported (501 if not). A server without the Patient compartment answers 405. ResourceManager.purgeResources removes documents from both collections and refuses an empty query. DocumentManager.removeDocuments now takes the target collection and refuses any query that trivially matches the whole collection, as a last check before deleteMany. The operation is opt-in: repofyr-operations ships patient-purge.json, and a deployment adds it to its operations-path and CapabilityStatement.
tnamli
approved these changes
Oct 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the FHIR Patient
$purgeoperation (Patient-purge, FHIR 6.0.0-ballot3) for R4 and R5, to serve GDPR erasure requests. A FHIR delete keeps the data in history;$purgeremoves it for good.POST [base]/Patient/[id]/$purgepermanently deletes every current and historical version of the resources in the patient's compartment, then the Patient itself, and returns200with an OperationOutcome giving the number of removed versions per resource type.Also opens
4.1.0-SNAPSHOT: a new operation is additive, so this is a minor release.Behaviour
AuditEvent, to preserve the audit trail;Group, since a shared cohort would otherwise be removed for every member.linkstays.501naming it and removes nothing. A server without the Patient compartment answers405.Safety against wiping a collection
ResourceManager.purgeResourcesrefuses parameters that don't resolve to a single Mongo query.DocumentManager.removeDocumentsrefuses any query that trivially matches the whole collection ({},{$and: []}, an$orwith an empty branch, or a nesting of these). This is the last check beforedeleteMany.Enabling it (opt-in)
Neither base definition set contains this operation. To enable it, a deployment must:
repofyr-operations/src/main/resources/patient-purge.jsoninto itsfhir.initialization.operations-path;Patientin its CapabilityStatement;rest.compartment.The default R5 CapabilityStatement declares no compartment, so a stock R5 setup answers
405until it does.docker/sample-setupdeliberately leaves it out.Tests
FHIRPurgeOperationTest(R4 endpoint, 13 tests) checks that:actor) are purged, and so is an Appointment shared with another patient;404;PatientPurgeOperationHandlerTest: the supported-parameter check (4 tests).SmartAuthorizerTestnow builds its configuration with the operations path and the default operation table, asFhirConfigurationManagerdoes.R5ServerBootTestpins.Full reactor: 351 tests, BUILD SUCCESS (
repofyr-server-r4179).Reviewer notes
patient-purge.jsoncopies HL7's ballot definition (version: 6.0.0-ballot3,status: draft). One difference:affectsStateistruerather than HL7'sfalse, so the operation can only be called with POST.information, becausesuccessexists only from FHIR 6.4.1.0 - Unreleasedsection, and the module README documents the operation.