-- ========================================== -- 06: GRANT BYPASSRLS TO BACKEND USER -- ========================================== -- This script grants Row-Level Security bypass privilege -- Required for registration flow (tenant + user creation in same transaction) -- Runs as: postgres (superuser) \echo '🔓 Granting BYPASSRLS privilege...' -- ========================================== -- WHY BYPASSRLS IS NECESSARY -- ========================================== -- During registration, we create tenant and user in a single transaction: -- -- BEGIN; -- INSERT INTO tenants (...) VALUES (...); -- Creates tenant -- INSERT INTO users (tenant_id, ...) VALUES (...); -- References tenant -- COMMIT; -- -- PROBLEM WITHOUT BYPASSRLS: -- - PostgreSQL validates foreign key (users.tenant_id → tenants.id) -- - Foreign key check runs: SELECT 1 FROM tenants WHERE id = ? -- - RLS policy blocks this SELECT (no tenant context during registration) -- - Foreign key check fails: "violates foreign key constraint" -- - Transaction rolls back -- -- SOLUTION WITH BYPASSRLS: -- - Backend user can see ALL rows during registration -- - Foreign key check succeeds (tenant visible immediately) -- - Transaction commits successfully -- - Regular operations still protected by RLS (when app.current_tenant_id is set) -- ========================================== -- Grant BYPASSRLS to backend API user ALTER USER aurganize_backend_api WITH BYPASSRLS; \echo ' ✅ BYPASSRLS privilege granted to aurganize_backend_api' -- ========================================== -- VERIFY PRIVILEGE GRANTED -- ========================================== DO $$ DECLARE has_bypassrls BOOLEAN; user_privileges TEXT; BEGIN -- Check if BYPASSRLS was granted SELECT rolbypassrls INTO has_bypassrls FROM pg_roles WHERE rolname = 'aurganize_backend_api'; IF has_bypassrls THEN RAISE NOTICE ' ✅ Verification: BYPASSRLS is active'; ELSE RAISE WARNING ' ❌ Verification: BYPASSRLS not active!'; RAISE EXCEPTION 'Failed to grant BYPASSRLS privilege'; END IF; -- Build privilege summary SELECT CASE WHEN rolsuper THEN '🔴 SUPERUSER' WHEN rolbypassrls THEN '🟡 RLS BYPASS' ELSE '🟢 STANDARD' END INTO user_privileges FROM pg_roles WHERE rolname = 'aurganize_backend_api'; RAISE NOTICE ' 🔐 Privilege Level: %', user_privileges; END $$; -- ========================================== -- DISPLAY FINAL USER CONFIGURATION -- ========================================== \echo '' \echo '📋 Final user configuration:' SELECT rolname AS "Username", rolcanlogin AS "Can Login", rolsuper AS "Superuser", rolbypassrls AS "Bypass RLS", rolconnlimit AS "Conn Limit", CASE WHEN rolsuper THEN '🔴 Full Access' WHEN rolbypassrls THEN '🟡 RLS Bypass (for registration)' ELSE '🟢 Standard (RLS enforced)' END AS "Access Level" FROM pg_roles WHERE rolname = 'aurganize_backend_api'; -- ========================================== -- SECURITY NOTES -- ========================================== \echo '' \echo '==========================================' \echo '🔒 SECURITY NOTES' \echo '==========================================' \echo '' \echo '✅ SAFE USAGE:' \echo ' - Backend sets app.current_tenant_id for regular operations' \echo ' - RLS still protects all normal CRUD operations' \echo ' - Only registration flow runs without tenant context' \echo ' - Audit logs capture all operations' \echo '' \echo '⚠️ IMPORTANT:' \echo ' - BYPASSRLS only needed for registration endpoint' \echo ' - All other operations MUST set tenant context' \echo ' - Readonly user does NOT have BYPASSRLS' \echo '' \echo '✅ BYPASSRLS configuration complete!' \echo ''