-- ============================================================ -- Migration 006: GRANTs explícitos de tabla -- -- CONTEXTO: A partir de 2026-05-30, Supabase cambia el default de -- auto_expose_new_tables a false. Sin GRANTs explícitos, los roles -- anon/authenticated no pueden acceder a las tablas aunque haya -- políticas RLS. Las RLS policies son la capa de restricción por-fila; -- los GRANTs son la capa de acceso al objeto. Ambas son necesarias. -- -- Diseño de capas para responses/answers: -- Capa 1 (objeto): authenticated tiene SELECT → el role puede hacer queries -- Capa 2 (RLS): sin policy SELECT para org_admin → resultado = 0 filas -- Capa 3 (datos): para obtener datos reales, org_admin llama agg_segment, -- que aplica k_threshold internamente (SECURITY DEFINER) -- -- Esta layering cumple la intención del DATA_MODEL: "0 filas crudas", -- no "permission denied". El resultado es indistinguible para el caller -- (tabla vacía), pero la arquitectura es auditable y testeable con RLS. -- -- Principio mínimo de privilegios: -- anon → solo lo necesario para responder una encuesta -- authenticated → lo que necesita org_admin + respondentes autenticados -- service_role → bypasa RLS, no necesita GRANTs adicionales aquí -- ============================================================ -- Acceso al schema public GRANT USAGE ON SCHEMA public TO anon, authenticated; -- ============================================================ -- organizations -- authenticated (org_admin) lee solo su org (filtrado por RLS) -- ============================================================ GRANT SELECT ON public.organizations TO authenticated; -- ============================================================ -- consent_versions -- anon lee el texto de consentimiento para mostrarlo en el form -- ============================================================ GRANT SELECT ON public.consent_versions TO anon, authenticated; -- ============================================================ -- surveys -- anon: encuestas live (para renderizar el form) -- authenticated: sus encuestas en cualquier estado -- ============================================================ GRANT SELECT ON public.surveys TO anon, authenticated; -- ============================================================ -- questions -- anon: preguntas de encuestas live -- authenticated: preguntas de sus encuestas -- ============================================================ GRANT SELECT ON public.questions TO anon, authenticated; -- ============================================================ -- consent_records -- INSERT: al enviar el form -- SELECT: authenticated puede consultar (RLS filtra; analyst usa service_role) -- ============================================================ GRANT INSERT ON public.consent_records TO anon, authenticated; GRANT SELECT ON public.consent_records TO authenticated; -- ============================================================ -- responses -- INSERT: al enviar el form -- SELECT: authenticated puede hacer el query (RLS devuelve 0 filas para org_admin) -- El acceso con datos reales es solo via agg_segment (SECURITY DEFINER) -- ============================================================ GRANT INSERT ON public.responses TO anon, authenticated; GRANT SELECT ON public.responses TO authenticated; -- ============================================================ -- answers -- INSERT: al enviar el form -- SELECT: authenticated puede hacer el query (RLS devuelve 0 filas para org_admin) -- ============================================================ GRANT INSERT ON public.answers TO anon, authenticated; GRANT SELECT ON public.answers TO authenticated;