Skip to content

Ola 3 · 3.1 (de Neid, hecha por el carril de Sebas): evento_caso + RegistroService - #20

Open
heysebitas wants to merge 2 commits into
feat/o5-5.9-llaves-apifrom
feat/o3-3.1-evento-caso
Open

heysebitas wants to merge 2 commits into
feat/o5-5.9-llaves-apifrom
feat/o3-3.1-evento-caso

Conversation

@heysebitas

Copy link
Copy Markdown
Collaborator

Tarea 3.1 — es del carril de Neid. La escribí desde el mío porque bloqueaba cuatro tareas mías (3.2, 3.10, 4.1, 4.5) y la ola 3 no podía empezar sin ella. Va sobre #16.

@neylinsomne: revísala como tuya. Si el diseño no te convence, cámbialo — lo que importaba era desbloquear, no fijar la forma. Todo lo que quedó fuera está escrito abajo y en docs/tareas/neid.md.

El problema

De los 22 eventos del sistema, 3 se guardaban: 6 vivían en memoria y 13 no existían o se descartaban. Los dos momentos más vendibles del producto eran invisibles:

  • rerouteado"el hospital dijo que no y el sistema siguió solo", el mejor momento del demo, no quedaba registrado en ninguna parte.
  • override_crue — una decisión con potestad legal, guardada en el localStorage del navegador de quien la tomó.

Qué trae

  • RegistroService.registrar() es el único punto de escritura. Una sola firma, un solo sitio donde arreglar idempotencia, actor y orden — y es lo que hace posible el test de cobertura de eventos de 5.12. La tentación de dejar que cada servicio inserte directo es justo la que convierte un registro de auditoría en eventos con formas distintas para lo mismo.
  • No lanza nunca. Si la base está caída se pierde el evento y se grita en el log, pero el traslado sigue: un paciente no se queda sin hospital porque no se pudo escribir su línea de tiempo.
  • Idempotencia por (caso, tipo, clave) — el paramédico toca "ya llegué" dos veces con mala señal y eso es UNA llegada.
  • corregir() escribe una fila nueva con corrige_a. El original se queda: un UPDATE habría borrado el error, que es justo lo que un auditor necesita ver.
  • Migración 0006 con el trigger append-only (calcado del de 0002), el índice único parcial de idempotencia, corrige_a y RLS.
  • GET /casos/:id/eventos y los dos almacenes (memoria y Postgres) detrás de una interfaz, con la degradación declarada de siempre.

⚠️ El DDL del bloque D1 listaba 21 tipos: se le habían quedado fuera demora_detectada, tramite_firmado e intento_cruzado, que sí están en la tabla de §11.2. La migración usa la unión de las dos listas (24 entradas para los 22 eventos, porque dos filas de la tabla llevan dos eventos cada una).

Lo que NO quedó hecho, y por qué

  • Depende de 1.2, que sigue sin existir. El paso 5 —"evento_caso en la misma transacción que el cambio de estado"— no se puede cumplir mientras el estado sea un Map. La firma para hacerlo está anotada en registro.service.ts.
  • GET /casos/:id/eventos no filtra por organización: caso todavía no tiene dueño. Llega con 1.2 + las policies de 1.6. No expongan esa ruta fuera del equipo mientras tanto.
  • actor_id sin FK a actor(id) — esa tabla es de 1.1 (Zaid) y sin ella la migración no corre sola. Queda text para admitir los ids sintéticos que ya existen (legado:operador, llave:<uuid>).
  • SedeEstado y CapacidadDeclarada (los otros dos tipos que 3.1 debía mergear) no están: son de 3.3, de Zaid.
  • La migración no se probó contra un Postgres real — no hay base en el entorno. El SQL está revisado a mano; córrelo antes de confiar.

Hecho cuando

  • Un UPDATE sobre evento_caso lanza excepción
  • El mismo evento con la misma clave dos veces → una fila
  • Una corrección se lee como corrección, no borra el original
  • Los tipos están mergeados antes que el resto de la ola — parcial, ver arriba

9 tests nuevos · tsc y lint limpios.

⚠️ Numeración de migraciones: con esta quedan tomadas 0004 (#12), 0005 (#15) y 0006. La de identidad de Zaid (1.1) es la 0007.

⚠️ Tarea del carril de NEID, escrita desde el carril de Sebas porque
bloqueaba 3.2, 3.10, 4.1 y 4.5, y la ola 3 no podia empezar sin ella.
Neid: revisala como tuya y cambia lo que no te convenza.

De los 22 eventos del sistema, 3 se guardaban: 6 vivian en memoria y 13 no
existian o se descartaban. El re-ruteo automatico —el mejor momento del
producto— no quedaba registrado, y el override del CRUE, que es una decision
con potestad legal, vivia en el localStorage del navegador.

  - `RegistroService.registrar()` es el UNICO punto de escritura. Una sola
    firma, un solo sitio donde arreglar idempotencia, actor y orden — y es lo
    que hace posible el test de cobertura de eventos de 5.12.
  - **No lanza nunca.** Si la base esta caida se pierde el evento y se grita
    en el log, pero el traslado sigue: un paciente no se queda sin hospital
    porque no se pudo escribir su linea de tiempo.
  - Idempotencia por (caso, tipo, clave): el paramedico toca "ya llegue" dos
    veces con mala señal y eso es UNA llegada.
  - `corregir()` escribe una fila nueva con `corrige_a`. El original se queda:
    un UPDATE habria borrado el error, que es justo lo que un auditor
    necesita ver.
  - Migracion 0006 con el trigger append-only (calcado del de 0002), el
    indice unico parcial de idempotencia, `corrige_a` y RLS.
  - `GET /casos/:id/eventos` y los dos almacenes (memoria y Postgres) detras
    de una interfaz, con la misma degradacion declarada del resto del repo.

Lo que queda fuera y esta escrito en docs/tareas/neid.md: el evento en la
misma transaccion que el cambio de estado (necesita 1.2), el filtro por
organizacion de la lectura (1.2 + 1.6), la FK a `actor` (1.1) y correr la
migracion contra un Postgres real.
heysebitas added a commit that referenced this pull request Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant