docs(adr): registrar ADR-005 esquema declarativo + deuda Fase 2 en backlog
This commit is contained in:
@@ -77,11 +77,15 @@ Principios estructurales (de ADR-001):
|
||||
- **Umbral de k-anonimato** obligatorio en toda visualización compartida (nunca mostrar celda con
|
||||
n < umbral).
|
||||
|
||||
## 6. ADRs iniciales
|
||||
## 6. ADRs
|
||||
|
||||
Ver `docs/adr/` para los archivos completos.
|
||||
|
||||
- **ADR-001** — Modelo de privacidad y gobierno de datos *(el corazón del producto)*.
|
||||
- **ADR-002** — Stack tecnológico y residencia de datos.
|
||||
- **ADR-003** — Consentimiento granular versionado e inmutable.
|
||||
- **ADR-004** — Capa de identidad y autenticación (SSO Keycloak para staff; sin login para respondentes).
|
||||
- **ADR-005** — Esquema declarativo de formularios y estrategia de dos fases (Sprint 4). La lógica del flujo vive en datos (JSONB), interpretada por un motor backend; el frontend wizard es un renderer sin reglas de negocio. Motor genérico diferido a Fase 2.
|
||||
|
||||
## 7. Riesgos
|
||||
|
||||
|
||||
11
BACKLOG.md
11
BACKLOG.md
@@ -58,6 +58,17 @@
|
||||
|
||||
---
|
||||
|
||||
### [BACKLOG-002] Fase 2 — Motor genérico de formularios
|
||||
- **Estado:** Diferido post-deadline
|
||||
- **Contexto:** En Sprint 4 se construye un intérprete del esquema declarativo específico
|
||||
para el formulario de cuidadores (ADR-005, Fase 1). Una vez entregado ese caso, el
|
||||
intérprete se extrae a un motor universal que interprete cualquier esquema definido en
|
||||
`questions.conditional_rules` + campos de instanciación, sin hardcodear ningún formulario.
|
||||
El formulario de cuidadores se vuelve el primer caso de prueba del motor sin reescribir
|
||||
el contrato de datos.
|
||||
- **Dependencia:** Fase 1 completada (Sprint 4 — wizard funcional).
|
||||
- **Ver:** ADR-005 (`docs/adr/ADR-005-esquema-declarativo-formularios.md`).
|
||||
|
||||
- Dashboard / reportes (Sprint 3)
|
||||
- Formulario de consentimiento + persistencia de respuestas (Etapa 2B)
|
||||
- Builder visual de encuestas (post-validación del caso fijo)
|
||||
|
||||
102
docs/adr/ADR-005-esquema-declarativo-formularios.md
Normal file
102
docs/adr/ADR-005-esquema-declarativo-formularios.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# ADR-005 — Esquema declarativo de formularios y estrategia de dos fases
|
||||
|
||||
> Para agregar a `ARCHITECTURE.md` (o `docs/adr/`). Estado: **Aceptada**.
|
||||
> Fecha: 2026-06-20 · Sprint 4 · Versión objetivo 3.0.0
|
||||
|
||||
---
|
||||
|
||||
## Contexto
|
||||
|
||||
El producto es un **motor de formularios/flujos de encuesta**. La aplicación
|
||||
actual (encuesta "Mapeo de Cuidadores") es su primer caso de uso real, pero la
|
||||
arquitectura debe servir al producto, no solo a este formulario.
|
||||
|
||||
El rediseño a wizard v3 introduce lógica de flujo significativamente más compleja
|
||||
que v2: recorridos ramificados (cuidador completo / solo niño / sin vínculo),
|
||||
mini-wizard de instancias de vínculo familiar (preguntas que se repiten N veces,
|
||||
una por familiar), y saltos condicionales de sección.
|
||||
|
||||
Existe una restricción de negocio: dos clientes inminentes en 10-20 días requieren
|
||||
la encuesta funcionando para validación.
|
||||
|
||||
El esquema actual de `questions` ya posee una base declarativa:
|
||||
- `conditional_rules` JSONB con operadores `eq` / `eq_any` y acción `show`
|
||||
- Auto-target implícito (la regla afecta a la pregunta que la porta)
|
||||
- Tipos de pregunta extensibles vía CHECK constraint
|
||||
|
||||
## Problema
|
||||
|
||||
¿Dónde reside la lógica del flujo del formulario? Tres anti-patrones a evitar:
|
||||
1. **Lógica en el presentador** (frontend con reglas hardcodeadas) — impide
|
||||
reutilización, genera bugs de sincronización de estado, no escala al producto.
|
||||
2. **Lógica dispersa en columnas sueltas** de la base — deuda técnica; no soporta
|
||||
evolución a flujos más complejos sin migrar el esquema entero.
|
||||
3. **Sobre-ingeniería prematura** — construir un motor genérico universal para
|
||||
casos hipotéticos antes de conocerlos, retrasando el deadline real.
|
||||
|
||||
## Decisión
|
||||
|
||||
**La lógica del flujo vive en una capa de definición declarativa (datos),
|
||||
interpretada por un motor en el backend, y renderizada por un frontend sin reglas
|
||||
de negocio.**
|
||||
|
||||
Se adopta una **estrategia de dos fases**:
|
||||
|
||||
### Fase 1 (Sprint 4 — para el deadline)
|
||||
- El formulario de cuidadores se define como **esquema declarativo persistido**,
|
||||
extendiendo el `conditional_rules` JSONB existente y agregando campos
|
||||
declarativos de instanciación a `questions`.
|
||||
- Se construye un motor de resolución de flujo **para este formulario** (interpreta
|
||||
el esquema; calcula qué pantalla sigue desde esquema + estado).
|
||||
- El frontend wizard es un **renderer** del esquema, sin reglas de negocio.
|
||||
- NO se construye el intérprete genérico universal todavía.
|
||||
|
||||
### Fase 2 (sprints posteriores — post-deadline, registrada en BACKLOG)
|
||||
- Se extrae el intérprete a un **motor genérico de formularios**.
|
||||
- El formulario de cuidadores, ya definido como esquema, se vuelve el primer caso
|
||||
de prueba del motor — sin reescribir el contrato.
|
||||
|
||||
### Diseño técnico del esquema (Fase 1)
|
||||
Se extiende `questions` en lugar de crear una tabla de definición separada:
|
||||
- `conditional_rules` extendido con nuevos operadores (`not_in`, acción `hide`)
|
||||
para expresar saltos como "Ninguno → salta a sección final".
|
||||
- Nuevos campos declarativos para instanciación:
|
||||
- `instance_generator` — marca la pregunta que genera instancias (ej. 4.1)
|
||||
- `instance_of` — código del generador del que depende una pregunta (ej. 4.2 → "4.1")
|
||||
- Representación de secciones con nombre y descripción (el "porqué").
|
||||
|
||||
## Alternativas consideradas
|
||||
|
||||
1. **Lógica en el frontend (rechazada):** rápida para este formulario, pero viola
|
||||
el principio de producto, no escala, y reproduce los bugs de sincronización ya
|
||||
vistos en el mockup.
|
||||
2. **Columnas sueltas tipo `is_instanced` (rechazada):** resuelve hoy, genera deuda;
|
||||
no soporta flujos más complejos sin migración de esquema.
|
||||
3. **Motor genérico universal ahora (rechazada):** arquitectónicamente deseable como
|
||||
fin, pero sobre-ingeniería antes del deadline y con un solo caso de uso conocido
|
||||
(diseñar en el vacío). Se difiere a Fase 2 cuando haya más casos que informen el
|
||||
diseño abstracto.
|
||||
4. **Tabla de definición de flujo separada (diferida):** posible mejor forma para el
|
||||
motor genérico, pero para un solo formulario es sobre-ingeniería. Se reevalúa en
|
||||
Fase 2.
|
||||
|
||||
## Consecuencias
|
||||
|
||||
**Positivas:**
|
||||
- Entrega la encuesta en plazo sin generar retrabajo estructural.
|
||||
- La lógica en datos habilita guardado parcial, reanudación, validación consistente
|
||||
y progreso preciso — mejor UX, fuente única de verdad del estado.
|
||||
- La Fase 2 es generalización del intérprete, no reescritura del contrato.
|
||||
- El esquema declarativo es versionable y auditable.
|
||||
|
||||
**Negativas / deuda intencional:**
|
||||
- Fase 1 es más trabajo que parchear el formulario actual.
|
||||
- El motor de Fase 1 es específico a este formulario (no genérico) — deuda
|
||||
registrada en BACKLOG, asumida conscientemente, no oculta.
|
||||
- Extender `conditional_rules` puede requerir reevaluación cuando lleguen flujos
|
||||
con lógica que el vocabulario actual de operadores no exprese.
|
||||
|
||||
## Cumplimiento (cómo se verifica)
|
||||
- Revisión de código: el frontend wizard NO contiene reglas de flujo del negocio.
|
||||
- El flujo es reproducible desde el esquema persistido.
|
||||
- La deuda de Fase 2 figura en `BACKLOG.md`.
|
||||
Reference in New Issue
Block a user