Files
motor-de-encuestas/sprints/sprint-1/ETAPA_1C_PROMPT.md

82 lines
5.1 KiB
Markdown

# ETAPA 1C — Cierre de la fundación: REVOKE del GRANT peligroso + documentación
> Prompt versionado (Patrón B.1). Cierra la auditoría de la Etapa 1B con el único cambio bloqueante
> que encontró y documenta tres decisiones que el agente tomó por iniciativa. Claude Code lo ejecuta
> tras leer `CLAUDE.md`, `DATA_MODEL.md` y este prompt.
## 1. Objetivo
Quitar el `GRANT SELECT ON consent_records TO authenticated` (puerta apoyada-sin-llave: hoy inerte,
peligrosa si alguien suma una policy SELECT a futuro), **confirmar en ejecución que no rompe el flujo
de envío de la encuesta** (la FK `responses.consent_record_id`), y documentar en `DATA_MODEL.md` tres
decisiones tomadas en la 1B.
## 2. Contexto previo
La 1B aplicó las migraciones 001-006 a Supabase Cloud y la auditoría aprobó la fundación de datos
salvo este punto. La migración **006 ya está aplicada en Cloud****NO se edita** (rompería el
historial de migraciones). El cambio va en una migración nueva, 007.
## 3. Decisiones ya tomadas (no consultar de nuevo)
- El cambio es un `REVOKE`, en migración **nueva** 007. NO editar 001-006.
- El `GRANT INSERT ON consent_records TO anon, authenticated` **se mantiene** (el envío del formulario
lo necesita). Solo se revoca el SELECT.
- NO se agrega ninguna policy SELECT a `consent_records`. El analyst lee vía `service_role` (que
bypassa RLS y no necesita GRANTs).
- No se toca el resto del esquema, ni las policies, ni `service_role`.
## 4. Tareas
1. Crear la migración con `supabase migration new revoke_consent_select` y poner como contenido:
```sql
-- 007: Revoca el SELECT sobre consent_records a authenticated.
-- Auditoría 1B: GRANT inerte hoy (no hay policy SELECT) pero peligroso si a futuro alguien
-- agrega una policy SELECT para org_admin → expondría quién consintió qué, vector de
-- correlación con respuestas en encuesta anónima. El analyst lee vía service_role.
REVOKE SELECT ON public.consent_records FROM authenticated;
```
2. Aplicar a Cloud: `supabase db push` (usar `npx supabase ...` si el CLI no es global).
3. Correr las validaciones de la sección 6 contra la base real.
4. Documentar en `DATA_MODEL.md` las tres decisiones (texto exacto en la sección 5 de este prompt).
## 5. Texto EXACTO a agregar al final de `DATA_MODEL.md` (sección nueva)
```markdown
## Decisiones ratificadas en ejecución (Sprint 1)
- **`options` en preguntas `rating` (F3, G4):** se guarda como objeto
`{"min":1,"max":5,"min_label":"...","max_label":"..."}`, NO como array. El frontend (Sprint 2)
debe manejar dos formas de `options`: array para `single_choice`/`multiple_choice`, objeto para
`rating`.
- **`required = false` en todas las preguntas seeded:** la obligatoriedad real se define en Sprint 2
(validación del formulario). Nota: B1 estaba marcada obligatoria en el mockup; revisar al construir
el formulario.
- **Policies de `org_admin` presentes pero inertes en v1:** las policies RLS para `org_admin`
(acceso multi-tenant por empresa) existen en migración 003, pero v1 NO tiene login de cliente
("nosotros presentamos a cada empresa"). El acceso real lo hace el analyst vía `service_role`. El
camino `org_admin` queda reservado para un futuro de auto-servicio, no operado en v1.
```
## 6. Validaciones automatizadas mandatorias (contra la base Cloud)
La central es la #1 — confirma que revocar el SELECT NO rompe el envío:
- **FK intacta:** simulando rol `anon` (SET ROLE anon + claims, o vía anon key), `INSERT` en
`consent_records` → obtener su id → `INSERT` en `responses` referenciando ese `consent_record_id`
(con `survey_id` de una encuesta `status='live'` y `respondent_id` NULL) → **debe insertar sin
error**. Esto prueba que la verificación de FK no requiere SELECT sobre `consent_records`.
- **REVOKE efectivo:** como `authenticated`, `SELECT FROM consent_records` → ahora "permission
denied" (ya no "0 filas"). Confirma que el revoke aplicó.
- **Sin regresión:** re-correr las claves de la 1B → RLS sobre `responses`/`answers` = 0 filas para
org_admin; `agg_segment` n=3 → suprimido, n=5 → valor; inmutabilidad de `consent_records` (UPDATE/
DELETE → error) sigue vigente.
- Si CUALQUIERA falla: **NO declarar lista la etapa.** Reportar y esperar. En especial, si la #1
fallara (la FK SÍ necesitaba el SELECT), **detenerse y reportar** — sería el caso que invalida el
cambio.
## 7. Qué reportar
- **Verificado:** salida concreta de cada validación (el INSERT anónimo que efectivamente insertó, el
"permission denied" del SELECT como authenticated, y las 3 de no-regresión).
- **Asumido / Hallazgos / Decisiones por iniciativa** (clasificadas por nivel).
- **`git diff --name-only HEAD`:** debe contener solo la migración 007 nueva + `DATA_MODEL.md`.
## 8. Qué NO hacer
- NO editar las migraciones 001-006 (006 ya está en Cloud).
- NO agregar policy SELECT a `consent_records`.
- NO tocar `service_role`, ni las policies de org_admin, ni el resto del esquema.
- NO usar `respondent_id` ni exponer texto libre.
- Ante conflicto entre una restricción y "que aplique limpio": **detenerse y reportar**, no resolver
unilateralmente.