prompt 4G
This commit is contained in:
121
sprints/sprint-4/ETAPA_4G_PROMPT.md
Normal file
121
sprints/sprint-4/ETAPA_4G_PROMPT.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# ETAPA 4G — Submit con instance_id + validación de integridad server-side
|
||||||
|
|
||||||
|
## 1. Objetivo
|
||||||
|
Escribir el submit de v3: persiste las respuestas (incluyendo instancias) y VALIDA la
|
||||||
|
integridad en el servidor contra el esquema antes de insertar. La validación server-side
|
||||||
|
es REQUISITO NO NEGOCIABLE (BRIEF decisión 15). El cliente no es confiable; datos de salud.
|
||||||
|
|
||||||
|
## 2. Contexto previo
|
||||||
|
- El submit de v2 (`app/actions/submit-survey.ts`) NO está conectado y está desactualizado:
|
||||||
|
- `WITH CHECK (true)` en RLS de answers → acepta cualquier insert (sin validación real).
|
||||||
|
- payload plano `Record<code,value>` — sin noción de `instance_id`.
|
||||||
|
- códigos qi_* apuntan a A1/A4/A5 (v2), no existen en v3 (son 2.1/2.4/2.5).
|
||||||
|
- 3 INSERTs sueltos sin transacción → si answers falla, responses/consent quedan huérfanos.
|
||||||
|
- El motor `lib/form-engine.ts` es PURO → se puede correr SERVER-SIDE para validar.
|
||||||
|
NO reescribir la lógica de flujo: reusar el motor.
|
||||||
|
- `answers.instance_id` existe (4A), constraint UNIQUE(response_id, question_id, instance_id).
|
||||||
|
- El estado del wizard ya tiene claves `code:instanceId` (4C/4D).
|
||||||
|
- Se usa anon key respetando RLS (regla 9 de CLAUDE.md) — NUNCA service_role.
|
||||||
|
|
||||||
|
## 3. DECISIONES YA TOMADAS — no consultar de nuevo
|
||||||
|
- Validación de integridad SERVER-SIDE, no negociable.
|
||||||
|
- Reusar `lib/form-engine.ts` en el servidor para validar coherencia de flujo — no duplicar lógica.
|
||||||
|
- El submit rechaza el envío ENTERO si algo no valida — no inserta datos parciales ni inyectados.
|
||||||
|
- El payload del cliente pasa a ser consciente de instancia: `{code, instanceId, value}[]`
|
||||||
|
(o equivalente que preserve la clave compuesta).
|
||||||
|
- Transaccionalidad: las inserciones (consent_records → responses → answers) deben ser atómicas.
|
||||||
|
Evaluar función RPC transaccional (SECURITY DEFINER con validaciones) vs. inserts en el
|
||||||
|
Server Action. Proponé el enfoque más robusto dado que anon no puede hacer múltiples
|
||||||
|
inserts atómicos fácilmente — una RPC transaccional es probablemente lo correcto.
|
||||||
|
- Códigos qi_* actualizados a v3 (2.1 zona, 2.4 edad, 2.5 sector — verificar contra el seed).
|
||||||
|
|
||||||
|
## 4. Validaciones server-side mandatorias
|
||||||
|
Por cada submit recibido, el servidor valida CONTRA EL ESQUEMA de la DB (no contra el cliente):
|
||||||
|
1. **Survey válido y activo:** el `survey_id` existe y está en estado que admite respuestas.
|
||||||
|
2. **Preguntas legítimas:** cada `code` recibido existe y pertenece a ESE survey.
|
||||||
|
3. **Valores válidos:** cada valor es una opción válida de su pregunta (para single/multiple_choice),
|
||||||
|
respeta `max_select`, tipo correcto.
|
||||||
|
4. **Visibilidad coherente:** usando el motor (`resolveScreens`/`resolveVisibility`) con las
|
||||||
|
respuestas recibidas, cada respuesta enviada corresponde a una pregunta que DEBÍA estar
|
||||||
|
visible. Rechazar respuestas a preguntas que el flujo nunca debió mostrar (ej. responder
|
||||||
|
3.2 cuando 3.1='No' las oculta).
|
||||||
|
5. **Instancias legítimas:** cada `instance_id` (familiar_N) corresponde a una instancia
|
||||||
|
realmente generada por su `instance_generator` (4.1) según la respuesta real recibida para 4.1.
|
||||||
|
Rechazar instancias inventadas.
|
||||||
|
6. **Consentimiento requerido presente:** el consentimiento operativo (requerido) está.
|
||||||
|
7. **Requeridas presentes:** las preguntas required visibles tienen respuesta.
|
||||||
|
|
||||||
|
Si CUALQUIERA falla: rechazar el submit completo, no insertar nada, devolver error claro.
|
||||||
|
|
||||||
|
## 5. Tareas
|
||||||
|
### 5.1 Definir el contrato del payload v3
|
||||||
|
Shape consciente de instancia. El wizard ya tiene `state.answers` con claves `code:instanceId`.
|
||||||
|
Definir el payload que el cliente envía y el validador consume.
|
||||||
|
|
||||||
|
### 5.2 Validador server-side (reusando el motor)
|
||||||
|
Módulo/función que recibe el payload + carga el esquema desde la DB + corre las 7 validaciones
|
||||||
|
del punto 4, reusando `lib/form-engine.ts`. Puro y testeable donde se pueda.
|
||||||
|
|
||||||
|
### 5.3 Persistencia transaccional
|
||||||
|
Implementar la inserción atómica (consent_records → responses → answers con instance_id).
|
||||||
|
Proponer e implementar RPC transaccional o mecanismo equivalente. Si una RPC SECURITY DEFINER
|
||||||
|
es el camino, documentar por qué y qué valida internamente.
|
||||||
|
|
||||||
|
### 5.4 Conectar el wizard al submit
|
||||||
|
El botón "Enviar (próximamente)" pasa a enviar de verdad. Manejar estados éxito/error
|
||||||
|
(los stage que 4D dejó sin implementar). Mensajes de error accionables, nunca trace crudo.
|
||||||
|
|
||||||
|
### 5.5 Tests
|
||||||
|
- Validación: submit con respuesta a pregunta oculta → rechazado.
|
||||||
|
- Validación: valor fuera de opciones → rechazado.
|
||||||
|
- Validación: instancia inventada → rechazada.
|
||||||
|
- Validación: sin consentimiento requerido → rechazado.
|
||||||
|
- Happy path: submit completo válido (con instancias) → persiste correctamente con instance_id.
|
||||||
|
- Atomicidad: fallo a mitad → no quedan datos parciales.
|
||||||
|
|
||||||
|
## 6. Entregables (DoD)
|
||||||
|
- [ ] Validación server-side completa (7 validaciones) reusando el motor.
|
||||||
|
- [ ] Submit rechaza envío entero si algo no valida; sin datos parciales.
|
||||||
|
- [ ] Persistencia transaccional (sin huérfanos ante fallo).
|
||||||
|
- [ ] instance_id persistido correctamente por instancia.
|
||||||
|
- [ ] Códigos qi_* actualizados a v3.
|
||||||
|
- [ ] Wizard conectado al submit, estados éxito/error funcionando.
|
||||||
|
- [ ] Tests de las validaciones + happy path + atomicidad.
|
||||||
|
- [ ] anon key, nunca service_role (salvo dentro de RPC SECURITY DEFINER justificada).
|
||||||
|
- [ ] **Validación del director** antes de aplicar a producción.
|
||||||
|
|
||||||
|
## 7. Qué reportar
|
||||||
|
```
|
||||||
|
Verificado:
|
||||||
|
- Validación server-side: 7/7 implementadas, reusando lib/form-engine.ts ✓
|
||||||
|
- Casos rechazados probados: pregunta oculta, valor inválido, instancia falsa, sin consentimiento
|
||||||
|
- Persistencia transaccional vía [RPC / mecanismo] ✓ — atomicidad probada
|
||||||
|
- instance_id persistido: [ejemplo real de filas answers con familiar_1/familiar_2]
|
||||||
|
- Códigos qi_* actualizados a v3 ✓
|
||||||
|
- Wizard conectado, estados éxito/error ✓
|
||||||
|
- Tests: N/N
|
||||||
|
Asumido / decisiones:
|
||||||
|
- [enfoque transaccional y por qué]
|
||||||
|
Hallazgos:
|
||||||
|
- [lo que aparezca]
|
||||||
|
```
|
||||||
|
Reporte con datos concretos (C.4): mostrá filas reales de answers con instance_id tras un
|
||||||
|
submit de prueba con 2 familiares.
|
||||||
|
|
||||||
|
## 8. Qué NO hacer
|
||||||
|
- ❌ No confiar en validación de cliente para integridad (es UX, no seguridad).
|
||||||
|
- ❌ No duplicar la lógica de flujo — reusar el motor server-side.
|
||||||
|
- ❌ No insertar datos parciales si la validación falla.
|
||||||
|
- ❌ No usar service_role fuera de una RPC SECURITY DEFINER justificada y documentada.
|
||||||
|
- ❌ No aplicar a producción sin validación del director.
|
||||||
|
- ❌ No tocar v2.1.0-stable, el seed, ni el motor (salvo para CONSUMIRLO en validación).
|
||||||
|
|
||||||
|
## 9. Versionado
|
||||||
|
```
|
||||||
|
feat(submit): submit v3 con validación de integridad server-side [4G]
|
||||||
|
|
||||||
|
Validación server-side (no negociable) reusando el motor: rechaza respuestas
|
||||||
|
a preguntas ocultas, valores inválidos, instancias falsas, sin consentimiento.
|
||||||
|
Persistencia transaccional con instance_id por instancia. Conecta el wizard.
|
||||||
|
Cierra la falla de WITH CHECK(true): el cliente ya no es fuente de verdad.
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user