Skip to main content
Version: 1.0.0
Last Updated: 2026-01-11
Status: Active

Overview

This guide explains the automated RLS (Row Level Security) validation integrated into our CI/CD pipeline. These checks prevent security regressions and ensure all database changes follow multi-tenant isolation best practices.

Quick Reference

Local Commands

What Gets Checked


CI/CD Pipeline

Pipeline Stages

Workflow Jobs

  1. migration-lint - Runs on every PR that modifies supabase/migrations/*.sql
  2. rls-policy-validation - Runs after migrations are applied (push to main or internal PRs)

Environment Variables Required


Pre-Commit Hook

The pre-commit hook automatically lints staged migration files:

Bypassing (Emergency Only)

⚠️ Warning: Bypassing pre-commit hooks will still fail CI. Only use for emergencies.

Common Failures & Fixes

Error: CREATE TABLE without RLS

Failure:
Fix:

Error: UPDATE policy without WITH CHECK

Failure:
Fix:

Error: Direct pf_user_roles query (Recursion Risk)

Failure:
Fix:

Error: Missing search_path on SECURITY DEFINER

Failure:
Fix:

Excluding Tables from Validation

Some tables intentionally have fewer than 4 policies:

Audit/Log Tables (Append-Only)

  • Only SELECT + INSERT policies (no UPDATE/DELETE)
  • Examples: pf_audit_logs, hr_payroll_audit_log, fw_approval_history

Version Tables (Immutable)

  • Only SELECT + INSERT policies
  • Examples: fw_form_versions, pf_document_versions

System Tables (Deny-All)

  • Only service_role access
  • Examples: pf_integration_credentials
To add a table to the exclusion list, update scripts/validate-rls-policies.ts:

Troubleshooting

”Missing environment variables”

Ensure these are set:

“RPC function does not exist”

The validation script relies on helper functions. Run the migration that adds them:

CI passes but local fails

Local and CI may have different database states. Ensure:
  1. You’ve applied all migrations locally
  2. Your local Supabase matches the CI environment

Adding New Validation Rules

  1. Add rule definition in scripts/lint-rls-migration.ts:
  2. Add detection logic in lintFile() function
  3. Add documentation in this guide
  4. Test with existing migrations to avoid false positives

Reports

CI generates a JSON report at reports/rls-validation.json:
Reports are retained as CI artifacts for 30 days.

See Also