Caso de estudio · Servicio público digital

Conoce a tu Enfermera(o)

Prototipo de consulta pública de colegiatura que responde sin pedir identificación y sin guardar quién consultó, sobre un plan gratuito y sin infraestructura permanente.

Periodo
Agosto de 2026
Rol
Diseño, desarrollo y despliegue
Responsabilidad
Proyecto personal completo, de extremo a extremo

Contexto

Contexto

El Colegio de Enfermeros del Perú publica un validador para que cualquiera compruebe si quien la atiende está habilitada. Es una consulta legítima y frecuente: pacientes, clínicas y empleadores necesitan confirmarlo antes de aceptar una atención o firmar un contrato.

El servicio tiene una tensión incómoda: para responder necesita exponer parte de un padrón, pero exponerlo mal lo convierte en una fuente de extracción masiva. Y la solución habitual —pedir identificación al consultante— crea un problema nuevo: una base de datos de quién preguntó por quién. Este es un ejercicio personal para resolverla con las restricciones de una institución sin equipo técnico ni presupuesto.

Problema

Problema

Ofrecer una consulta pública de colegiatura que sea útil para una persona e inútil para quien quiera extraer el padrón completo, sin pedir identificación al consultante y sin depender de infraestructura que alguien deba mantener y pagar.

Consecuencias observadas

  • Pedir DNI o login genera un registro de quién consultó a quién, un dato sensible que hay que custodiar y justificar.
  • Permitir búsquedas parciales, comodines o listados convierte el validador en un exportador del padrón por goteo.
  • Conectar la web pública al sistema institucional expone el padrón maestro por una superficie que no controla quien lo administra.

Proceso

Proceso

  1. Delimitar qué se reemplaza y qué no

    El alcance quedó fijado en sustituir únicamente el validador legado, no en reconstruir el sitio institucional. Recortar el problema fue la primera decisión de diseño y la que hizo viable todo lo demás.

  2. Aislar la consulta del sistema que administra el padrón

    En lugar de conectar la aplicación al origen institucional, se diseñó una proyección pública independiente que recibe una exportación mínima.

  3. Construir tres adaptadores y probar que producen lo mismo

    Como se desconoce en qué formato entregaría los datos una institución real, se escribieron adaptadores para JSON, CSV y API/NDJSON, y se verificó que los tres producen un snapshot canónico idéntico.

  4. Frenar la extracción masiva y automatizar la verificación

    Búsqueda exacta sin comodines, cinco resultados como máximo, Turnstile validado en servidor y limitación de tasa en el borde. Sobre eso, una cadena de integración continua con la rama principal protegida.

Decisiones

Decisiones

No recolectar nada del consultante

Decisión
La consulta no pide registro, login ni DNI, y no se guarda ningún dato de quién consultó.
Razón
Un dato que no se recolecta no se puede filtrar ni hay que custodiarlo. Eliminar la obligación sale más barato que gestionarla.
Impacto
El abuso tuvo que frenarse por la forma de la consulta, no por la identidad de quien la hace.

Proyección pública aislada, con flujo en una sola dirección

Decisión
Origen privado, exportación mínima, validación, staging y activación atómica. La aplicación pública solo lee la proyección; nunca alcanza el origen.
Razón
Si la aplicación pública se ve comprometida, el atacante llega a una copia recortada y ya publicada, no al sistema institucional ni a sus credenciales.
Impacto
Si una carga falla, el snapshot anterior sigue activo y el servicio no se degrada.

Limitación de tasa en el borde en lugar de Redis

Decisión
Cinco solicitudes cada diez segundos por IP, con bloqueo temporal al excederlas, usando el propio borde de Cloudflare.
Razón
Redis habría añadido un servicio permanente que pagar, monitorear y parchear. El borde ya ve todo el tráfico y no agrega superficie que mantener.
Impacto
La línea base no requirió crear recursos facturables.

Un snapshot canónico como contrato de ingesta

Decisión
Tres adaptadores demostrativos (JSON, CSV y API/NDJSON) que convergen en un snapshot canónico con versión, checksum e invariantes verificadas.
Razón
Convierte la integración futura en un problema resuelto de antemano: el formato de origen deja de importar mientras el adaptador produzca el snapshot esperado.

Turnstile obligatorio y fail-closed

Decisión
Sin token válido no hay consulta. Se validan en servidor el token, el hostname y la acción, con un tiempo de espera controlado.
Razón
Un control que ante la duda deja pasar la petición no es un control. Prefiero que el servicio falle visiblemente antes que abrirse en silencio.

Alternativas

Alternativas descartadas

Identificar al consultante con RENIEC o PIDE

Alternativa
Exigir DNI verificado contra los servicios de identidad del Estado antes de permitir la consulta.
Motivo para descartarla
Resuelve el abuso creando un problema mayor: un registro permanente de quién consultó a quién, con obligaciones de custodia que la institución no puede asumir. Además levanta una barrera de acceso a un dato que debería ser público.

Reconstruir el portal institucional completo

Alternativa
Migrar todo el sitio del colegio junto con el validador.
Motivo para descartarla
Multiplica el alcance, el costo y el riesgo para resolver un problema localizado en una sola ruta.

Kubernetes, microservicios y un gestor de identidad

Alternativa
Desplegar la solución sobre un clúster con Keycloak y servicios separados.
Motivo para descartarla
Es la arquitectura que la industria consideraría seria y la que garantiza que el proyecto muera: nadie en la institución podría operarla ni pagarla.

Implementación

Implementación

Todo corre sobre Cloudflare Workers, con los datos en una base D1 que contiene solo la proyección pública. La búsqueda acepta una colegiatura exacta de cinco o seis dígitos —incluidos los ceros iniciales— o un nombre completo normalizado, y devuelve cinco coincidencias como máximo.

El acceso a la base usa consultas preparadas, un esquema JSON cerrado y límites explícitos de cuerpo, campos y longitud. No hay comodines, listados, paginación ni exportación.

Equivalencia verificada entre los tres adaptadores
{
  "synthetic": true,
  "sources": [
    { "source": "demo:postgres-view-json", "record_count": 60,
      "checksum_sha256": "fb404fa8338bb8eb8b8f67ed190b47a136cae8691640c1257dd0b934ea6e87db" },
    { "source": "demo:legacy-csv",         "record_count": 60,
      "checksum_sha256": "fb404fa8338bb8eb8b8f67ed190b47a136cae8691640c1257dd0b934ea6e87db" },
    { "source": "demo:api-ndjson",         "record_count": 60,
      "checksum_sha256": "fb404fa8338bb8eb8b8f67ed190b47a136cae8691640c1257dd0b934ea6e87db" }
  ],
  "equivalent": true
}

Apoyo técnico

Cloudflare Workers y D1
Ejecutar el servicio y almacenar la proyección pública sin un proceso permanente que pagar y parchear.
Cloudflare Turnstile
Verificar que la consulta proviene de una persona, sin identificarla.
GitHub Actions con CodeQL, ZAP y Dependabot
Bloquear la integración ante hallazgos de análisis estático, dependencias vulnerables o alertas dinámicas.

Resultados

Resultados

Consulta pública operativa sin registro de consultantes

Verificado

El servicio responde consultas de colegiatura sin pedir identificación y sin crear ninguna base de datos de quién consultó.

Alcance: Despliegue de demostración con datos sintéticos, accesible públicamente.

Integración futura resuelta como contrato, no como promesa

Verificado

Tres formatos de origen distintos producen un snapshot idéntico, verificado por checksum y respaldado por pruebas que detectan alteraciones y dejan sin activar cualquier carga incompleta.

Alcance: Adaptadores demostrativos sobre orígenes simulados, no sobre el padrón real.

Cadena de verificación automática y bloqueante

Verificado

Ningún cambio llega a producción sin pasar por la cadena completa de comprobaciones, y cualquiera de ellas puede detenerlo. La revisión de agosto de 2026 cerró sin vulnerabilidades conocidas en el lockfile.

Alcance: Cada cambio hacia la rama principal, que está protegida y solo admite integración por pull request.

Sin recursos facturables en la línea base

Verificado

La arquitectura desplegada no requirió crear recursos de pago ni procesos permanentes.

Alcance: Línea base vigente al cierre de la revisión de agosto de 2026.

Registros por adaptador
60 en los 3
Padrón sintético de demostración.
Coincidencia de checksum
3 de 3
Adaptadores JSON, CSV y API/NDJSON.
Máximo de resultados
5
API pública de consulta.
Limitación de tasa
5 por 10 s / IP
API pública, con bloqueo temporal al excederla.

Límites

Límites

Los datos son sintéticos y el proyecto no es institucional

El padrón está generado y no existe encargo ni relación con el Colegio de Enfermeros del Perú. El servicio no consulta el registro real ni emite verificaciones oficiales.

Impacto: Cualquier adopción real exigiría autorización, acceso al origen y validación del catálogo oficial.

Las reglas WAF administradas no están habilitadas

Requieren un plan superior al gratuito. Como control compensatorio se añadió un smoke HTTP de bajo volumen junto al baseline dinámico.

Impacto: La defensa ante patrones conocidos es menor que la de un despliegue con WAF administrado.

La ingesta remota está desactivada

El CLI de carga opera en simulación por defecto y solo escribe con confirmación explícita de la versión y las variables de cuenta.

Impacto: El circuito de actualización está diseñado y probado, pero no ejercitado contra datos reales.

Aprendizaje

Aprendizaje

  • Diseñar para no recolectar un dato es más barato que diseñar para protegerlo. Al no guardar quién consulta, desaparece una categoría entera de obligaciones en lugar de tener que administrarla.
  • Una afirmación de seguridad sin comprobación automática es una intención. El checksum idéntico entre tres adaptadores vale más que cualquier párrafo asegurando que la ingesta es equivalente.
  • La capacidad de mantenimiento del destinatario es un requisito de diseño. Una arquitectura que la institución no puede operar ni pagar es una solución que fracasa más tarde, no una solución mejor.

Evidencia

Registro de evidencia

Código fuente y documentación del prototipo

Pública

Repositorio público con la aplicación, los adaptadores, el esquema, las pruebas y la documentación de arquitectura y seguridad.

Fecha
2026-08-16
Ver el repositorio

Demostración pública en funcionamiento

Pública

Despliegue accesible de la consulta. Puede probarse con el número de colegiatura sintético 00001.

Alcance
Datos sintéticos. No consulta el padrón real ni emite verificaciones oficiales.
Abrir la demostración

Contrato OpenAPI de la API de consulta

Pública

Especificación de la API pública: formato de búsqueda aceptado, campos devueltos y límite de cinco resultados.

Consultar el contrato OpenAPI

Esquema JSON del snapshot del padrón

Pública

Contrato que define la proyección publicada y sus invariantes. Es la frontera formal entre lo que se expone y lo que permanece en el origen.

Ver el esquema del snapshot

Cadena DevSecOps en integración continua

Pública

Flujo que ejecuta validación de datos, lint, pruebas, build, auditoría del lockfile, Dependency Review y CodeQL en cada cambio hacia la rama principal.

Ver las ejecuciones de DevSecOps

Informe de equivalencia de los tres adaptadores

Pública

Salida generada que compara los snapshots producidos desde JSON, CSV y API/NDJSON, con número de registros y checksum de cada uno.

Fecha
2026-08-09
Ver el informe de equivalencia