Patrones de Cumplimiento PHI/PII en Salud
Patrones para proteger datos de pacientes, datos clínicos y datos financieros en aplicaciones de salud. Aplicables a HIPAA (EE. UU.), DISHA (India), GDPR (UE) y protección general de datos sanitarios.
Cuándo Usar
- Al construir cualquier característica que toque registros de pacientes
- Al implementar control de acceso o autenticación para sistemas clínicos
- Al diseñar esquemas de bases de datos para datos sanitarios
- Al construir APIs que devuelvan datos de pacientes o clínicos
- Al implementar pistas de auditoría o registro de actividades
- Al revisar código en busca de vulnerabilidades de exposición de datos
- Al configurar Seguridad a Nivel de Fila (RLS) para sistemas sanitarios multi-instalación
Cómo Funciona
La protección de datos sanitarios opera en tres capas: clasificación (qué es sensible), control de acceso (quién puede verlo) y auditoría (quién lo vio).
Clasificación de Datos
PHI (Información de Salud Protegida) — cualquier dato que pueda identificar a un paciente Y se relacione con su salud: nombre del paciente, fecha de nacimiento, dirección, teléfono, correo electrónico, números de identificación nacional (SSN, Aadhaar, número NHS), números de historial médico, diagnósticos, medicamentos, resultados de laboratorio, imágenes, detalles de pólizas y reclamaciones de seguros, registros de citas y admisiones, o cualquier combinación de lo anterior.
PII (Datos no sensibles de pacientes) en sistemas sanitarios: datos personales de clínicos/personal, estructuras de honorarios de médicos y montos de pago, salarios de empleados y datos bancarios, información de pago a proveedores.
Control de Acceso: Seguridad a Nivel de Fila
ALTER TABLE patients ENABLE ROW LEVEL SECURITY;
-- Limitar acceso por instalación
CREATE POLICY "staff_read_own_facility"
ON patients FOR SELECT TO authenticated
USING (facility_id IN (
SELECT facility_id FROM staff_assignments
WHERE user_id = auth.uid() AND role IN ('doctor','nurse','lab_tech','admin')
));
-- Registro de auditoría: solo inserción (a prueba de manipulaciones)
CREATE POLICY "audit_insert_only" ON audit_log FOR INSERT
TO authenticated WITH CHECK (user_id = auth.uid());
CREATE POLICY "audit_no_modify" ON audit_log FOR UPDATE USING (false);
CREATE POLICY "audit_no_delete" ON audit_log FOR DELETE USING (false);
Pista de Auditoría
Cada acceso o modificación de PHI debe ser registrado:
interface AuditEntry {
timestamp: string;
user_id: string;
patient_id: string;
action: 'create' | 'read' | 'update' | 'delete' | 'print' | 'export';
resource_type: string;
resource_id: string;
changes?: { before: object; after: object };
ip_address: string;
session_id: string;
}
Vectores de Fuga Comunes
Mensajes de error: Nunca incluir datos que identifiquen al paciente en mensajes de error enviados al cliente. Registrar detalles solo en el servidor.
Salida de consola: Nunca registrar objetos completos de pacientes. Usar identificadores internos opacos (UUIDs) — no números de historial médico, identificaciones nacionales o nombres.
Parámetros URL: Nunca poner datos que identifiquen al paciente en cadenas de consulta o segmentos de ruta que puedan aparecer en registros o en el historial del navegador. Usar solo UUIDs opacos.
Almacenamiento del navegador: Nunca almacenar PHI en localStorage o sessionStorage. Mantener PHI solo en memoria, obtener bajo demanda.
Claves de rol de servicio: Nunca usar la clave service_role en código del lado del cliente. Usar siempre la clave anónima/pública y dejar que RLS aplique el control de acceso.
Registros y monitoreo: Nunca registrar registros completos de pacientes. Usar solo identificadores de registro opacos (no números de historial médico). Sanitizar trazas de pila antes de enviarlas a servicios de seguimiento de errores.
Etiquetado de Esquema de Base de Datos
Marcar columnas PHI/PII a nivel de esquema:
COMMENT ON COLUMN patients.name IS 'PHI: patient_name';
COMMENT ON COLUMN patients.dob IS 'PHI: date_of_birth';
COMMENT ON COLUMN patients.aadhaar IS 'PHI: national_id';
COMMENT ON COLUMN doctor_payouts.amount IS 'PII: financial';
Lista de Verificación de Despliegue
Antes de cada despliegue:
- Sin PHI en mensajes de error o trazas de pila
- Sin PHI en console.log/console.error
- Sin PHI en parámetros URL
- Sin PHI en almacenamiento del navegador
- Sin clave service_role en código del cliente
- RLS habilitado en todas las tablas PHI/PII
- Pista de auditoría para todas las modificaciones de datos
- Tiempo de espera de sesión configurado
- Autenticación API en todos los endpoints PHI
- Aislamiento de datos entre instalaciones verificado
Ejemplos
Ejemplo 1: Manejo de Errores Seguro vs. Inseguro
// MALO — filtra PHI en el error
throw new Error(`Paciente ${patient.name} no encontrado en ${patient.facility}`);
// BUENO — error genérico, detalles registrados en el servidor con identificadores opacos
logger.error('Falló búsqueda de paciente', { recordId: patient.id, facilityId });
throw new Error('Registro no encontrado');
Ejemplo 2: Política RLS para Aislamiento Multi-Instalación
-- El médico de la Instalación A no puede ver pacientes de la Instalación B
CREATE POLICY "facility_isolation"
ON patients FOR SELECT TO authenticated
USING (facility_id IN (
SELECT facility_id FROM staff_assignments WHERE user_id = auth.uid()
));
-- Prueba: iniciar sesión como medico-instalacion-a, consultar pacientes de instalacion-b
-- Resultado esperado: 0 filas devueltas
Ejemplo 3: Registro Seguro
// MALO — registra datos identificables del paciente
console.log('Procesando paciente:', patient);
// BUENO — registra solo el identificador interno opaco
console.log('Procesando registro:', patient.id);
// Nota: incluso patient.id debe ser un UUID opaco, no un número de historial médico