--- name: supabase-rls-policy-generator description: This skill should be used when the user requests to generate, create, or add Row-Level Security (RLS) policies for Supabase databases in multi-tenant or role-based applications. It generates comprehensive RLS policies using auth.uid(), auth.jwt() claims, and role-based access patterns. Trigger terms include RLS, row level security, supabase security, generate policies, auth policies, multi-tenant security, role-based access, database security policies, supabase permissions, tenant isolation. --- # Supabase RLS Policy Generator To generate comprehensive Row-Level Security policies for Supabase databases, follow these steps systematically. ## Step 1: Analyze Current Schema Before generating policies: 1. Ask user for the database schema file path or table names 2. Read the schema to understand table structures, foreign keys, and relationships 3. Identify tables that need RLS protection 4. Determine the security model: multi-tenant, role-based, or hybrid ## Step 2: Identify Security Requirements Determine access patterns by asking: - Is this a multi-tenant application? (tenant_id isolation) - What roles exist in the system? (admin, user, viewer, etc.) - Are there public vs private resources? - Do users need to share resources across accounts? - Are there hierarchical permissions? (organization > team > user) Consult `references/rls-patterns.md` for common security patterns. ## Step 3: Generate RLS Policies For each table requiring protection, generate policies following this structure: ### Enable RLS ```sql ALTER TABLE table_name ENABLE ROW LEVEL SECURITY; ``` ### Policy Types to Generate **SELECT Policies** - Control read access: - User can view their own records - User can view records in their tenant - Role-based viewing (admins see all) - Public records accessible to all authenticated users **INSERT Policies** - Control creation: - User can create records with their own user_id - User can create records in their tenant - Role-based creation restrictions **UPDATE Policies** - Control modifications: - User can update their own records - Admins can update all records - Tenant-scoped updates **DELETE Policies** - Control deletion: - User can delete their own records - Admin-only deletion - Tenant-scoped deletion ### Policy Templates Use templates from `assets/policy-templates.sql`: **Basic User Ownership**: ```sql CREATE POLICY "Users can view own records" ON table_name FOR SELECT USING (auth.uid() = user_id); ``` **Multi-Tenant Isolation**: ```sql CREATE POLICY "Tenant isolation" ON table_name FOR ALL USING ( tenant_id IN ( SELECT tenant_id FROM user_tenants WHERE user_id = auth.uid() ) ); ``` **Role-Based Access**: ```sql CREATE POLICY "Admins have full access" ON table_name FOR ALL USING ( auth.jwt() ->> 'role' = 'admin' ); ``` **JWT Claims**: ```sql CREATE POLICY "Organization access" ON table_name FOR SELECT USING ( organization_id = (auth.jwt() -> 'app_metadata' ->> 'organization_id')::uuid ); ``` ## Step 4: Generate Helper Functions Create PostgreSQL functions to support complex policies: ```sql -- Function to check user role CREATE OR REPLACE FUNCTION auth.user_has_role(required_role TEXT) RETURNS BOOLEAN AS $$ BEGIN RETURN (auth.jwt() ->> 'role') = required_role; END; $$ LANGUAGE plpgsql SECURITY DEFINER; -- Function to check tenant membership CREATE OR REPLACE FUNCTION auth.user_in_tenant(target_tenant_id UUID) RETURNS BOOLEAN AS $$ BEGIN RETURN EXISTS ( SELECT 1 FROM user_tenants WHERE user_id = auth.uid() AND tenant_id = target_tenant_id ); END; $$ LANGUAGE plpgsql SECURITY DEFINER; ``` ## Step 5: Generate Testing Queries Create test queries to verify policies work correctly: ```sql -- Test as authenticated user SET request.jwt.claim.sub = 'user-uuid'; SELECT * FROM table_name; -- Should see only accessible records -- Test as admin SET request.jwt.claim.role = 'admin'; SELECT * FROM table_name; -- Should see all records -- Test as different tenant SET request.jwt.claim.sub = 'other-user-uuid'; SELECT * FROM table_name; -- Should see different tenant's records ``` ## Step 6: Create Migration File Generate a migration file with proper structure: ```sql -- Migration: Add RLS policies -- Created: [timestamp] -- Enable RLS on tables ALTER TABLE users ENABLE ROW LEVEL SECURITY; ALTER TABLE items ENABLE ROW LEVEL SECURITY; -- Drop existing policies if any DROP POLICY IF EXISTS "policy_name" ON table_name; -- Create new policies [Generated policies here] -- Create helper functions [Generated functions here] -- Grant necessary permissions GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO authenticated; GRANT SELECT ON table_name TO anon; -- If public read needed ``` ## Step 7: Document Generated Policies Create documentation explaining: - What each policy does - Which users/roles have what access - Any special cases or exceptions - How to test the policies - Common troubleshooting tips Use template from `assets/policy-documentation-template.md`. ## Implementation Guidelines ### Security Best Practices - Always enable RLS on tables with user data - Use auth.uid() for user-owned records - Use JWT claims for role-based access - Prefer SECURITY DEFINER functions for complex logic - Test policies with different user roles - Use USING clause for read access, WITH CHECK for write validation ### Performance Considerations - Add indexes on columns used in policies (user_id, tenant_id, role) - Keep policy logic simple for better performance - Use helper functions for reusable complex logic - Avoid subqueries in policies when possible ### Common Patterns Consult `references/rls-patterns.md` for detailed examples of: - Multi-tenant isolation - Role-based access control (RBAC) - Attribute-based access control (ABAC) - Hierarchical permissions - Public/private resource splitting - Shared resource access ## Output Format Generate files in the following structure: ``` migrations/ [timestamp]_add_rls_policies.sql docs/ rls-policies.md (documentation) tests/ rls_tests.sql (test queries) ``` ## Verification Checklist Before completing: - [ ] RLS enabled on all sensitive tables - [ ] Policies cover all operations (SELECT, INSERT, UPDATE, DELETE) - [ ] Policies tested with different user roles - [ ] Indexes added for policy columns - [ ] Helper functions created for complex logic - [ ] Documentation generated - [ ] Test queries provided - [ ] No policies accidentally grant excessive access ## Consulting References Throughout generation: - Consult `references/rls-patterns.md` for security patterns - Consult `references/supabase-auth.md` for auth.uid() and JWT structure - Use templates from `assets/policy-templates.sql` ## Completion When finished: 1. Display the generated migration file 2. Summarize the policies created 3. Provide testing instructions 4. Offer to generate additional policies or modify existing ones