|
6 min de lectura
|

$purge: Elimine permanentemente los datos del paciente con una sola llamada FHIR

Resumen del artículo

La operación $purge de FHIR R6 elimina permanentemente a un Patient y todos los recursos de su compartimento, incluido el historial de versiones. Aidbox 2602 la implementa con modos síncrono y asíncrono, definiciones de compartimento personalizadas y registro de auditoría.

Resumir este artículo con:
ChatGPTPerplexityClaudeGrok

El DELETE estándar de FHIR es una eliminación lógica. El recurso se marca como eliminado, pero su historial de versiones permanece intacto: cada estado anterior sigue siendo recuperable a través de _history. Para la mayoría de los flujos de trabajo clínicos, esto es exactamente lo que se necesita: un registro de auditoría inmutable.

Pero las normativas no siempre están de acuerdo.

El artículo 17 del GDPR reconoce a las personas el «derecho al olvido». Las políticas de retención de datos tienen fechas de caducidad, incluso si se sitúan 100 años después del fallecimiento. Cuando llega el momento de eliminar realmente los datos de un paciente, una eliminación lógica no es suficiente. Es necesario borrar los datos de forma permanente en cada versión de cada recurso.

Esta brecha —entre la semántica de eliminación lógica predeterminada de FHIR y los requisitos normativos de eliminación física— es lo que la operación $purge fue diseñada para cerrar.

De la discusión en Zulip a la estandarización en FHIR R6

La operación $purge surgió de años de debate en la comunidad en FHIR Zulip, a partir de 2018.

La pregunta central era: ¿cómo debería FHIR gestionar el borrado permanente de datos? Se propusieron varios nombres —$erase, $expunge, $gdpr-delete— y ya existían distintas implementaciones. HAPI FHIR disponía de $expunge, pero solo eliminaba recursos previamente marcados como borrados de forma lógica.

La decisión de diseño clave fue el alcance: ¿debería /Patient/1/$purge borrar únicamente el recurso Patient en sí, o todo lo que pertenece al compartimento del paciente? La comunidad se decantó por la segunda opción: el servidor debería asumir la complejidad de localizar y eliminar todos los recursos del compartimento.

El trabajo de especificación formal continuó en 2023, abordando los códigos de respuesta, la semántica de eliminación del historial y los ámbitos SMART. El resultado fue que $purge se incorporó a FHIR R6 como operación normativa, sustituyendo las implementaciones específicas de cada proveedor por un estándar unificado.

Aidbox 2602: $purge en la práctica

A partir de la versión 2602, Aidbox implementa la operación $purge de FHIR R6. Un único POST elimina de forma permanente el recurso Patient y todos los recursos de su compartimento —Observations, Conditions, Encounters, MedicationRequests y todas sus versiones históricas.

La operación utiliza la definición del compartimento Patient para determinar qué recursos pertenecen a un paciente. Para cada tipo de recurso del compartimento, Aidbox consulta los parámetros de búsqueda correspondientes a fin de encontrar todos los recursos que referencian Patient/<id>:

POST /fhir/Patient/pt-1/$purge Load compartment definition Delete Patient/pt-1 Delete Observations Delete Conditions Delete Encounters Delete ...

Una purga síncrona básica consiste en un único POST:

POST /fhir/Patient/pt-1/$purge
Content-Type: application/json

Respuesta:

{
  "resourceType": "OperationOutcome",
  "issue": [
    {
      "severity": "fatal",
      "code": "informational",
      "diagnostics": "All resources for Patient/pt-1 were purged"
    }
  ]
}

Una vez completada la operación, cualquier solicitud relativa al paciente o sus recursos devuelve 404 Not Found, no 410 Gone. Los datos han dejado de existir.

Modo asíncrono para compartimentos grandes

Algunos pacientes acumulan miles de recursos a lo largo de años de atención. Eliminar todos esos recursos de forma síncrona podría provocar tiempos de espera excesivos.

Añada la cabecera Prefer: respond-async para ejecutar la purga en segundo plano:

POST /fhir/Patient/pt-1/$purge
Content-Type: application/json
Prefer: respond-async

El Patient se elimina de inmediato. Los recursos del compartimento son eliminados por procesos en segundo plano. La respuesta es un 202 Accepted con una cabecera Content-Location que apunta al endpoint de estado:

GET /fhir/$async/<operation-id>     # 202 mientras está en curso, 200 cuando finaliza
DELETE /fhir/$async/<operation-id>   # cancelar la operación

El número de trabajadores asíncronos concurrentes se controla mediante el parámetro BOX_SCHEDULER_EXECUTORS (valor predeterminado: 4).

El problema de los recursos compartidos: por qué importan los compartimentos personalizados

Imagine un recurso Group que representa una cohorte de ensayo clínico con 50 pacientes, o un recurso List que registra el panel de pacientes compartido de un equipo de atención. Estos recursos referencian a varios pacientes simultáneamente. Cuando se purga al Patient A, ¿debería eliminarse el Group completo, aunque los Patients B a Z sigan formando parte de él?

No existe una respuesta universalmente correcta. Eliminar el recurso entero rompe la integridad referencial para otros pacientes que aún lo referencian. Eliminar solo una parte —por ejemplo, retirar a un miembro de un Group— plantea sus propias preguntas: ¿deberían reescribirse también todas las versiones históricas de ese recurso para eliminar la referencia al paciente? ¿Y preserva el recurso modificado su semántica original?

La especificación central de FHIR deja deliberadamente este comportamiento en manos de los implementadores, y con razón. La respuesta correcta depende del modelo de datos, del contexto normativo y de cómo el sistema utiliza estos recursos compartidos.

$purge admite un parámetro compartmentDefinition que permite controlar con precisión qué tipos de recursos se incluyen en la purga. En lugar de utilizar el compartimento Patient predeterminado del servidor (que incluye Group, List y decenas de otros tipos), puede proporcionar una CompartmentDefinition personalizada que limite el alcance.

Por ejemplo, para purgar únicamente datos clínicos —excluyendo deliberadamente Group y List:

{
  "resourceType": "Parameters",
  "parameter": [
    {
      "name": "compartmentDefinition",
      "resource": {
        "resourceType": "CompartmentDefinition",
        "url": "http://example.com/purge-clinical-only",
        "name": "PurgeClinicalOnly",
        "code": "Patient",
        "status": "active",
        "search": true,
        "resource": [
          { "code": "Observation", "param": ["subject"] },
          { "code": "Condition", "param": ["subject"] },
          { "code": "Encounter", "param": ["subject"] },
          { "code": "MedicationRequest", "param": ["subject"] }
        ]
      }
    }
  ]
}

Esto proporciona un control explícito: purgar los datos clínicos individuales del paciente mientras los recursos compartidos permanecen intactos para que la lógica de la aplicación los gestione por separado.

La CompartmentDefinition personalizada debe tener code establecido como Patient y al menos una entrada de recurso con una lista param no vacía.

Garantías de seguridad integradas

Idempotente por diseño. Purgar un paciente que no existe (o que ya fue purgado) devuelve un resultado satisfactorio. Es posible volver a ejecutar $purge tras un fallo parcial sin preocuparse por errores.

Registro de auditoría. Cada purga exitosa crea un AuditEvent con action: "E" (Execute) y subtype: "$purge". La purga elimina los datos del paciente, pero el hecho de que se produjo queda registrado de forma permanente. Consulte cómo configurar el registro de auditoría para obtener instrucciones de configuración.

Primeros pasos

$purge está disponible en Aidbox a partir de la versión 2602. El endpoint sigue la especificación de FHIR R6:

POST /fhir/Patient/<patient-id>/$purge

No se requiere ninguna configuración adicional. Para consultar los detalles completos de la API y la referencia de parámetros, véase la documentación de $purge en Aidbox.

Compartir este artículo
Comments
Comments
Sign in
Loading comments...
Subscribe to our blog

Get the latest articles on FHIR, interoperability, and healthcare IT.