Validación de Recursos FHIR: Capas, Herramientas y Patrones de Producción
La validación FHIR es el proceso de verificar que una instancia de recurso se ajusta a la especificación FHIR, los perfiles aplicables y las vinculaciones de conjuntos de valores que esos perfiles declaran. Opera como una pila de capas, cada una de las cuales debe superarse para que un recurso sea completamente conforme: estructura (el recurso se parsea y contiene solo elementos definidos), cardinalidad (conteos mínimo/máximo de elementos), tipos de datos (los primitivos coinciden con sus tipos declarados — un dateTime debe ser un instante ISO 8601 válido, un code no debe contener espacios en blanco), invariantes (reglas de co-ocurrencia FHIRPath como "una Observation DEBE tener un valor o un dataAbsentReason"), y terminología (los valores codificados son válidos contra sus conjuntos de valores vinculados). Las capas no tienen el mismo costo: la descripción general oficial de validación es explícita en que los enfoques de esquema/schematron son los menos capaces precisamente porque no están conectados a un servidor de terminología — y la terminología es donde vive gran parte de la seguridad semántica [1].
El Validador Oficial: Un Motor, Muchas Caras
La herramienta principal es el Validador FHIR oficial de HL7 (validator_cli.jar), mantenido por el equipo central de FHIR y utilizado para validar cada ejemplo publicado en la propia especificación. Acepta instancias en JSON o XML, carga paquetes de guías de implementación desde el registro de paquetes FHIR y reporta problemas con detalle de ruta, línea y columna [3]:
java -jar validator_cli.jar observations/*.json \
-version 4.0 \
-ig hl7.fhir.us.core#6.1.0 \
-profile http://hl7.org/fhir/us/core/StructureDefinition/us-core-blood-pressure \
-output validation-report.json # OperationOutcome con detalle por problema
Un hecho arquitectónico importante de la especificación: las operaciones de validación del lado del servidor generalmente usan o derivan del mismo código de validación. Esto significa que la operación $validate expuesta por los servidores FHIR se comporta de forma consistente con el pipeline de CI — mismo motor, mismas advertencias (en particular, es tan bueno como el servidor de terminología que lo respalda). Invocarla es un simple POST [2]:
POST [base]/Observation/$validate?profile=http://hl7.org/fhir/StructureDefinition/heartrate HTTP/1.1
Content-Type: application/fhir+json
{ "resourceType": "Observation", ... }
{
"resourceType": "OperationOutcome",
"issue": [{
"severity": "error",
"code": "code-invalid",
"details": { "text": "The code '8867-4x' is not valid in the value set 'Heart Rate LOINC'" },
"expression": ["Observation.code.coding[0].code"]
}]
}
La operación también acepta un parámetro mode (create, update, delete) para que un servidor pueda verificar adicionalmente si el contenido sería aceptado — por ejemplo, restricciones de unicidad en una creación — más allá de si simplemente es válido.
Tres Patrones de Integración
1. Gate en CI/CD. Ejecutar la CLI del Validador contra un corpus de instancias de ejemplo en cada commit que toque perfiles o código de mapeo. Esto detecta regresiones de conformidad antes de que se fusionen — en nuestra experiencia, el lugar más económico para detectarlas por un orden de magnitud. Mantener un conjunto curado de instancias conocidas-buenas y conocidas-malas; un cambio de perfil que repentinamente hace que una instancia conocida-mala pase es tan regresión como uno que falla una instancia conocida-buena.
2. Aplicación en el límite de la API. Rechazar recursos no conformes en el primer punto de entrada. En HAPI FHIR esto está integrado: el RequestValidatingInterceptor valida los recursos entrantes (creaciones, actualizaciones, transacciones) y puede configurarse para agregar encabezados de respuesta, añadir al OperationOutcome devuelto, o fallar la solicitud con HTTP 422 Unprocessable Entity; un ResponseValidatingInterceptor hace lo mismo para los recursos salientes [4]. Para repositorios respaldados por JPA, el RepositoryValidatingInterceptor va más lejos, aplicando reglas en los puntos de corte de almacenamiento — por ejemplo, exigiendo que cada Patient declare y valide exitosamente contra US Core — de modo que los datos se verifican exactamente como se persistirán, ya sea que lleguen via HTTP o una llamada Java interna:
ruleBuilder.forResourcesOfType("Patient")
.requireAtLeastProfile("http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient")
.and()
.requireValidationToDeclaredProfiles();
3. Auditoría por lotes. Validar datos históricos cargados desde sistemas legados de forma asíncrona, produciendo informes de conformidad en lugar de rechazos. Este es el patrón correcto cuando los datos ya existen y el rechazo no es una opción — el objetivo es una lista de remediación priorizada, no un gate.
Rendimiento: Validar Todo, Solo No Todo en Línea
La validación completa de perfiles es costosa — las invariantes FHIRPath profundas, la resolución de slicing y las comprobaciones de terminología contra grandes conjuntos de valores consumen tiempo real por recurso, y la propia documentación de HAPI FHIR advierte que las implicaciones de rendimiento de ejecutar su validador de instancias en un sistema de producción siempre merecen consideración [5]. En nuestra experiencia, las latencias por recurso que son perfectamente aceptables en un pipeline por lotes se convierten en el cuello de botella de una API en tiempo real de alto rendimiento, y los round-trips de terminología suelen ser el costo dominante. Estrategias que funcionan en la práctica:
- Cachear agresivamente: las instantáneas de perfiles compilados, las expansiones de terminología y los resultados de
$validate-codeson altamente cacheables; el comportamiento con caché fría y cálida difiere enormemente. - Dividir la pila: aplicar validación estructural y de cardinalidad barata sincrónicamente en la capa de API, y ejecutar validación completa de perfil + terminología de forma asíncrona en un worker de fondo con reporte de errores y alertas.
- Muestrear cuando el volumen lo exige: validar una muestra estadística del tráfico de producción más el 100% del tráfico de nuevos socios de integración detecta problemas sistémicos sin pagar el costo completo por solicitud.
- Hacer benchmark con los propios perfiles y volúmenes: el costo de validación varía tanto con la complejidad del perfil, la profundidad del slicing y el tamaño del conjunto de valores que solo las mediciones contra la carga de trabajo real son significativas — incorporarlas a las pruebas de pre-producción, no descubrirlas en producción.
Patrones de Despliegue de Validación de un Vistazo
| Patrón | Dónde Ejecuta | Impacto de Latencia | Mejor Para |
|---|---|---|---|
| Gate CI/CD | Pipeline de build (Validator CLI) | Ninguno en tiempo de ejecución | Detectar regresiones de perfiles y mapeos antes de fusionar |
| Interceptor de solicitudes | Pipeline de solicitudes del servidor (e.g., HAPI rechazo 422) | En línea, por solicitud | Contratos de conformidad estrictos en el límite de la API |
| Reglas de repositorio | Puntos de corte de almacenamiento (e.g., HAPI RepositoryValidatingInterceptor) | En línea, por escritura | Aplicar declaraciones de perfil en todo lo persistido |
| Worker asíncrono / fondo | Cola tras la ingestión | Casi cero en línea | Validación completa de perfil + terminología a alto rendimiento |
| Auditoría por lotes | Offline sobre datos almacenados | Ninguno | Migraciones de legado, reportes periódicos de calidad de datos |
El Rol de CaboLabs
La validación es donde los perfiles dejan de ser documentos y empiezan a aplicarse — y diseñar dónde y con qué rigor aplicarlos es una decisión de ingeniería con consecuencias directas en el rendimiento y la calidad de datos. CaboLabs construye arquitecturas de validación para plataformas de salud: pipelines de Validator CLI en CI, configuraciones de interceptores y reglas de repositorio de HAPI FHIR, workers de validación asíncrona con reportes de conformidad, y la infraestructura de terminología que hace que la validación de valores codificados funcione realmente. Aplicamos la misma disciplina de conformidad a openEHR, donde nuestro repositorio de datos clínicos Atomik valida cada composición contra sus plantillas openEHR en la ingestión — calidad de datos basada en estándares aplicada en la capa de persistencia, no esperada aguas abajo.
Si su servidor FHIR acepta datos que no debería, su validación es demasiado lenta para ejecutarse en producción, o está diseñando la aplicación de conformidad para una nueva plataforma, contáctenos en cabolabs.com — le ayudaremos a validar todo sin ralentizar nada.
