Saltar al contenido
DispensAI

ATN-005

Bloqueo por receta vencida

Garantizar que ninguna dispensación se entregue con base en una receta médica cuya vigencia haya expirado, y que el socio y la organización dispongan de información accionable para regularizar la situación.

1. Objetivo

Impedir que el sistema registre una dispensación cuando la receta médica del socio está vencida, y asegurar que tanto el socio como la organización tengan información suficiente para actuar.

Este protocolo es la contraparte operativa de [[wiki/entities/dispensai/protocolos/ADM-004]] (renovación de receta). ADM-004 cubre el proceso de ingreso y validación de documentación nueva. ATN-005 cubre lo que ocurre cuando ese documento ya no es válido en el momento de intentar una dispensación.

2. Alcance

Cubre el control de vigencia de receta en el momento de creación de una dispensación, la información que el sistema muestra al socio, y el registro del evento de bloqueo.

No cubre:

  • El proceso de renovación de receta una vez detectado el vencimiento — eso es [[wiki/entities/dispensai/protocolos/ADM-004]].
  • El primer ingreso de la receta — eso es ADM-003.
  • La validación de identidad del socio en el momento de la dispensación — eso es otro control.
  • El caso en que la receta aún no tiene fecha de vencimiento configurada — ese estado (requiresConfiguration) requiere atención administrativa diferente al vencimiento.

3. Definiciones

Receta vencida. Receta cuya prescription_expiration_date registrada en extracted_documents es anterior a la fecha y hora actual al momento de la solicitud de dispensación.

Receta sin configurar. Receta cuya prescription_expiration_date es NULL. El sistema la trata como requiresConfiguration: true, distinto de isExpired: true. Ambos estados bloquean la dispensación, pero el camino de regularización es diferente.

Bloqueo. La interrupción del proceso de creación de dispensación antes de que se ejecute ninguna mutación sobre la tabla dispensations.

Preventivo. Estado en que la receta tiene 30 días o menos de vigencia restante. El sistema lo detecta y puede advertir al socio sin bloquearlo aún.

4. Roles y responsables

RolResponsabilidad
SistemaVerificar vigencia antes de crear la dispensación; rechazar y registrar el evento si está vencida
SocioRegularizar su documentación según lo que le indica el sistema
Admin / soporteDetectar socios bloqueados y apoyar el proceso de renovación
Responsable de documentaciónVerificar que la receta nueva cumple los requisitos antes de configurarla en el sistema

5. Disparador de inicio

Un administrador o el sistema intenta crear una dispensación para un socio cuya receta médica está vencida o sin fecha de vencimiento configurada.

6. Requisitos previos

  • La receta médica del socio está registrada en extracted_documents.
  • El sistema tiene acceso a prescription_expiration_date del documento más reciente configurado.

7. Entradas

  • Solicitud de creación de dispensación con el user_id del socio.
  • Registro del documento médico del socio en extracted_documents.

8. Procedimiento paso a paso

  1. Verificación de vigencia. Antes de ejecutar ninguna mutación, el sistema consulta checkPrescriptionStatus(userId) y compara prescription_expiration_date con la fecha actual.
  2. Bloqueo por vencimiento. Si isExpired === true (fecha pasada) o la receta está sin configurar, el sistema retorna un error y no crea ningún registro en dispensations.
  3. Información al operador. El sistema devuelve un mensaje de error que indica el motivo del bloqueo. El dashboard del socio muestra DocumentStatus con razón "expired" o "missing_expiration_date".
  4. Registro del evento. El sistema invoca logISOSystemEvent("prescription_expired", ...). Hoy esa llamada no deja ningún registro: la tabla destino no existe y el plano ISO está apagado en todos los tenants (ver brecha 3 de la §17). El paso se conserva porque el código lo ejecuta, pero no produce evidencia verificable.
  5. Orientación al socio. El dashboard del socio muestra el estado del documento. El socio puede iniciar el proceso de renovación conforme a [[wiki/entities/dispensai/protocolos/ADM-004]].
  6. Seguimiento por admin. El equipo administrativo revisa los socios con receta vencida y coordina la renovación.

9. Puntos de control

#ControlDónde se ejecutaCarácter
C1Guard isExpired antes de crear dispensación (path principal)app/actions/dispensations.ts:183Duro — el servidor no crea la dispensación
C2Guard isExpired antes de crear dispensación (path alternativo)app/actions/dispensations.ts:927Duro — mismo control en segundo path
C3Guard por BLOCKED_ROUTES (vía de administración)app/actions/dispensations.ts:175Duro — independiente del guard de vigencia
C4Estado DocumentStatus visible en dashboard del sociolib/document-status-checker.tsInformativo
C5Llamada a logISOSystemEvent("prescription_expired", ...)lib/prescription-checker.tsSin efecto hoy — no deja registro (ver §17, brecha 3)

C1 y C2 son controles duros verificados en código. C3 es un control duro separado. C4 es un control de visibilidad. C5 se conserva como paso del código, pero hoy no produce evidencia: no tratarlo como registro auditable.

10. Criterios de decisión

Estado de la recetaResultado
isExpired: true (fecha pasada)Bloqueo. Sin dispensación. Sin registro del evento (§17, brecha 3)
requiresConfiguration: true (fecha NULL)Bloqueo. Sin dispensación. Se requiere configurar la fecha
≤ 30 días de vigencia (preventive)Sin bloqueo. Aviso en dashboard. Sin registro del evento (§17, brecha 3)
Vigente y configuradaDispensación procede normalmente

11. Excepciones y escalamiento

  • Receta sin fecha configurada: El administrador debe revisar el documento, extraer la fecha de vencimiento e ingresar el dato al sistema. Hasta que no se configure, el sistema no puede distinguir vigente de vencido y bloquea preventivamente.
  • Error en la lectura del documento: Si extracted_documents no tiene registro para el socio, checkPrescriptionStatus retorna requiresConfiguration: true. El bloqueo opera igual.
  • Receta vencida urgente: Si la situación clínica del socio requiere dispensación urgente, la organización puede coordinar la renovación acelerada. El sistema no tiene mecanismo de sobrepaso (bypass) habilitado por defecto.

12. Registros generados

RegistroContenidoTabla
Estado de documento del socioRazón "expired" o "missing_expiration_date"Calculado en tiempo real; no persiste como fila separada

Este protocolo no genera hoy ningún registro persistente propio. El bloqueo opera, pero no deja rastro verificable en el sistema: la evidencia del evento de bloqueo se declaraba sobre iso_system_events, tabla que ya no existe. Ver §17, brecha 3. La evidencia de que el control se ejecutó es humana (reporte del socio, revisión del panel), no del sistema.

13. Indicadores

IndicadorFórmulaMetaFuente
Tasa de dispensaciones bloqueadas por receta vencidaDispensaciones bloqueadas ÷ intentos de dispensaciónMonitorear tendencia; no es una métrica que deba ser 0 siempreNo calculable hoy — no hay registro del bloqueo (§17, brecha 3)
Socios con receta vencida activaCOUNT socios con isExpired: true sin dispensación en 30 días0 sin seguimiento activoextracted_documents
Tiempo de regularizaciónFecha de nueva receta configurada − fecha del primer bloqueo≤ 7 días hábilesextracted_documents para la fecha de la receta nueva; la fecha del primer bloqueo no está registrada (§17, brecha 3)

14. Riesgos y controles

RiesgoControlTipo
Dispensación entregada sin receta vigenteGuards C1 y C2 en server action (código)Preventivo duro
Bloqueo sin rastro auditableNingún control compensatorio en el sistema; los guards C1/C2 siguen operando pero no dejan registroBrecha (§17, brecha 3)
Socio bloqueado sin orientaciónDashboard muestra estado y razón; protocolo ADM-004 para renovaciónInformativo
Admin sin visibilidad de socios vencidosNo hay alerta automática — ver §17Brecha

15. Normativa y referencias

NormaReferenciaQué cubre en este protocolo
ISO 9001:2015§8.5.1Control de producción y provisión del servicio; la receta vigente es un requisito documentado para la dispensación
ISO 9001:2015§8.7Control de salidas no conformes; una dispensación sin receta vigente es una salida no conforme
Ley 20.000Art. 8Uso exclusivamente terapéutico; la receta médica vigente es el instrumento que acredita la condición médica del socio
ISO 27001:2022A.8.15Logging de eventos; el bloqueo por receta vencida debería quedar registrado. Cobertura abierta: hoy no se registra (§17, brecha 3)

16. Anexos y formularios vinculados

  • [[wiki/entities/dispensai/protocolos/ADM-004]] — Renovación de receta médica (contraparte).
  • [[wiki/entities/dispensai/protocolos/ADM-003]] — Primer ingreso de documentación.

17. Implementación en el sistema

El bloqueo principal está implementado y confirmado en dos puntos independientes del código. El registro del evento no existe. La visibilidad del administrador es una brecha.

ElementoUbicaciónEstado
Guard principal de vigencia (path 1)app/actions/dispensations.ts:183CONFIRMADO
Guard principal de vigencia (path 2)app/actions/dispensations.ts:927CONFIRMADO
Guard por BLOCKED_ROUTESapp/actions/dispensations.ts:175CONFIRMADO
checkPrescriptionStatus() — distingue isExpired vs requiresConfigurationlib/prescription-checker.tsCONFIRMADO
DocumentStatus visible en dashboard del sociolib/document-status-checker.tsCONFIRMADO
Tipos prescription_expired y prescription_expiring en el enum ISOlib/iso-event-logger.ts:89-90CONFIRMADO (el tipo existe; el destino no)
Registro persistente del evento de bloqueo—INEXISTENTE (brecha 3)

Brechas conocidas:

  1. La emisión del evento no falla ruidosamente. La llamada a logISOSystemEvent("prescription_expired", ...) se ejecuta dentro de un bloque try/catch que captura la excepción sin relanzarla. El bloqueo de la dispensación igual se ejecuta — C1 y C2 no dependen del evento — pero la ausencia de registro nunca se manifiesta como error. Esto es lo que hizo que la brecha 3 pasara inadvertida.

  2. Sin notificación al administrador cuando una receta vence. El sistema bloquea en silencio desde la perspectiva del equipo. El administrador descubre que un socio está bloqueado solo si: (a) el socio lo contacta, (b) el administrador revisa el panel de documentos del socio de forma proactiva. No existe cola, alerta ni vista filtrada de socios con receta vencida sin dispensación reciente. Esta es una brecha operativa con consecuencia directa: un socio puede permanecer bloqueado indefinidamente sin que la organización lo sepa.

  3. La tabla iso_system_events no existe y el plano ISO está apagado. Este protocolo declaraba iso_system_events como registro de evidencia. Esa tabla fue eliminada por la migración dispensai/supabase/migrations/20260515000000_iso_standby.sql:121 (DROP TABLE IF EXISTS public.iso_system_events CASCADE) y vuelve a eliminarse en 20260629000000_cross_tenant_dispensation_fix_canonical.sql:76. Ninguna migración posterior la recrea. El plano ISO se trasladó al Worker dispensai/backends/workers/iso (D1), detrás de la bandera ISO_ENABLED, que está en false en los seis tenants con .env local. Con la bandera apagada, logISOSystemEvent es un no-op silencioso — así lo documenta dispensai/lib/iso-event-logger.ts:8. Consecuencia operativa: el control de bloqueo por receta vencida existe como procedimiento y se ejecuta en código, pero no deja rastro verificable en el sistema. No se puede acreditar ante un tercero cuántas veces operó, ni cuándo. La evidencia disponible es humana, no del sistema.

Lo que ejecuta la organización fuera del sistema: la comunicación al socio de que su receta vencida necesita renovación se hace por canales externos (llamada, correo). El sistema muestra el estado en el dashboard del socio, pero no envía notificación proactiva. La coordinación de la renovación entre el socio y el equipo médico también ocurre fuera del sistema.

18. Historial de versiones

VersiónFechaCambioAutor
1.02026-08-28Versión inicial. Redactada desde la corrida de evidencia 2026-08-28-ATN. Dos brechas declaradas: evento best-effort y ausencia de notificación al admin.Sistema / admin
1.12026-08-29Cierre de INFERIDO: guards en dispensations.ts:183 y :927 confirmados en código. Tipos prescription_expired y prescription_expiring confirmados en lib/iso-event-logger.ts:89-90. Todo §17 ya estaba CONFIRMADO o PARCIAL — sin cambio a brechas.Sistema / admin
1.22026-08-29Corrección de evidencia inexistente: iso_system_events sale del frontmatter (registro_evidencia, implementacion.tablas) y eventos_iso queda vacío. Nueva brecha 3 con la migración que eliminó la tabla y el estado de ISO_ENABLED. §8, §9, §10, §12, §13, §14 y §15 corregidos para no afirmar un registro que no ocurre. Brechas 2 → 3.Sistema / admin

Documentos asociados

  • receta médica vigente
  • extracted_documents

Registros y evidencia

  • audit_logs

Indicadores

  • 0 dispensaciones entregadas con receta vencida
  • % de socios con receta vencida notificados o atendidos dentro del plazo

Normativa y referencias

  • ISO 9001:2015 §8.5.1
  • ISO 9001:2015 §8.7
  • Ley 20.000 Art. 8
  • ISO 27001:2022 A.8.15

Dónde deja rastro en el sistema

Rutas
  • /dashboard
  • /admin/dispensaciones
Tablas
  • extracted_documents
  • dispensations