"""enable_rls_security_policies Revision ID: 85d25a191d06 Revises: 20260205_create_profiles_table Create Date: 2026-02-05 15:08:33.430692 """ from typing import Sequence, Union from alembic import op # revision identifiers, used by Alembic. revision: str = "85d25a191d06" down_revision: Union[str, Sequence[str], None] = "20260205_create_profiles_table" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Enable RLS security policies. Security measures: 1. Revoke anon role access to alembic_version (internal table) 2. Enable RLS on profiles table 3. Add defensive policies for profiles (deny all public access by default) Architecture: - Backend uses service_role connection (bypasses RLS) - RLS provides defense-in-depth security layer - Prevents accidental direct PostgREST access """ # 1. Revoke anon role access to alembic_version table op.execute("REVOKE ALL ON TABLE public.alembic_version FROM anon") op.execute("REVOKE ALL ON TABLE public.alembic_version FROM authenticated") # 2. Enable RLS on profiles table op.execute("ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY") # 3. Add defensive policies for profiles table # These policies deny all public access by default # Backend service_role connection bypasses these policies # Deny all SELECT operations for anon and authenticated roles op.execute( "CREATE POLICY profiles_deny_public_select ON public.profiles " "FOR SELECT TO anon, authenticated USING (false)" ) # Deny all INSERT operations for anon and authenticated roles op.execute( "CREATE POLICY profiles_deny_public_insert ON public.profiles " "FOR INSERT TO anon, authenticated WITH CHECK (false)" ) # Deny all UPDATE operations for anon and authenticated roles op.execute( "CREATE POLICY profiles_deny_public_update ON public.profiles " "FOR UPDATE TO anon, authenticated USING (false) WITH CHECK (false)" ) # Deny all DELETE operations for anon and authenticated roles op.execute( "CREATE POLICY profiles_deny_public_delete ON public.profiles " "FOR DELETE TO anon, authenticated USING (false)" ) def downgrade() -> None: """Rollback RLS security policies.""" # 1. Drop all policies on profiles table op.execute("DROP POLICY IF EXISTS profiles_deny_public_select ON public.profiles") op.execute("DROP POLICY IF EXISTS profiles_deny_public_insert ON public.profiles") op.execute("DROP POLICY IF EXISTS profiles_deny_public_update ON public.profiles") op.execute("DROP POLICY IF EXISTS profiles_deny_public_delete ON public.profiles") # 2. Disable RLS on profiles table op.execute("ALTER TABLE public.profiles DISABLE ROW LEVEL SECURITY") # 3. Re-grant default privileges to anon role on alembic_version # (reverting to Alembic's default behavior) op.execute("GRANT SELECT ON TABLE public.alembic_version TO anon") op.execute("GRANT SELECT ON TABLE public.alembic_version TO authenticated")