# 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.