Row Level Security (RLS) Standard Contract
Status: Canonical
Last Updated: 2026-02-06
Owner: Engineering
Purpose
This document defines the mandatory Row Level Security (RLS) standards for CAIRL.
It establishes:
- How access to Postgres data is enforced
- Which tables MUST have RLS enabled
- How RLS interacts with roles, compliance, and abuse prevention
- When (and only when) elevated access is permitted
This document defines system-wide invariants. All database schemas, migrations, and queries MUST comply.
Scope
This contract applies to:
- All Supabase Postgres tables
- All user-owned and compliance-regulated data
- All server-side database access
- All migrations and schema changes
No feature, spec, or flow may bypass or weaken these rules.
Core RLS Principles (Invariants)
- RLS is the primary enforcement layer for data access.
- RLS MUST be enabled on all user-owned tables.
- Server-side checks supplement RLS; they do not replace it.
- Least privilege is mandatory.
- Ambiguity defaults to denial.
- Compliance requirements override convenience.
Table Classification for RLS
Every Postgres table MUST be classified into one of the following categories.
User-Owned Tables
Tables containing data owned by a specific user.
Examples:
- Messages
- Uploaded documents
- Profiles
- Preferences
- Mailboxes
Rules:
- RLS MUST be enabled
- Access MUST be restricted to the owning user
- Ownership MUST be explicit (e.g., a user_id column)
Compliance-Regulated Tables
Tables containing data subject to HIPAA, billing, or audit retention.
Examples:
- HIPAA documents
- Biometric verification records
- Audit logs
- Billing events
Rules:
- RLS MUST be enabled
- Access MUST be restricted to authorized roles
- All access MUST be logged
- Retention rules apply regardless of account state
System-Owned Tables
Tables required for platform operation and enforcement.
Examples:
- Allowlists
- Suppression lists
- Abuse reports
- Partner configuration
Rules:
- RLS SHOULD be enabled where feasible
- Access MUST be restricted to admin roles
- Client access is prohibited unless explicitly documented
Derived / Ephemeral Tables
Tables used for caching or temporary state.
Examples:
- Temporary aggregations
- Job queues
- Session helpers
Rules:
- RLS MAY be enabled
- Tables MUST NOT be treated as source of truth
- Data MUST be discardable
Mandatory RLS Requirements
The following rules are non-negotiable:
- All user-owned and compliance-regulated tables MUST have RLS enabled.
- RLS policies MUST reference the authenticated user identifier.
- Client-side database access MUST NEVER use service-role credentials.
- Service-role credentials MUST be server-only and explicitly scoped.
- Any table without RLS MUST be documented and approved.
Auth Context and Identity Mapping
RLS policies MUST rely on Supabase-provided authentication context.
Standard invariant pattern:
- Ownership columns (e.g., user_id) MUST equal auth.uid().
No alternative identity mapping is permitted without documentation and approval.
Role-Based Access in RLS
RLS MAY incorporate role checks when required.
Rules:
- Role checks MUST be explicit.
- Admin access MUST be narrowly scoped.
- Admin access MUST NOT imply unrestricted access.
Admin access MUST still respect compliance boundaries and retention rules.
HIPAA and Audit-Specific RLS Rules
For HIPAA-regulated tables:
- Read access MUST be limited to:
- The owning user
- Explicitly authorized admin or support roles
- Write access MUST be minimized
- Every access MUST be logged
RLS MUST NOT allow:
- Bulk reads across users
- Unscoped admin access
- Anonymous access
Interaction with Abuse and Rate Limits
RLS MUST NOT be used to implement rate limiting or abuse logic.
Rules:
- RLS enforces who can access which rows
- Abuse logic enforces how often actions may occur
- Both layers MUST exist independently
Abuse enforcement MUST NOT rely on bypassing RLS.
Server-Side Elevated Access
Use of elevated database access (service-role credentials) is permitted ONLY:
- In server-side contexts
- For explicitly documented administrative or system operations
- With minimum required scope
Rules:
- Elevated access MUST NOT be used for normal user flows
- All elevated access MUST be logged
- Scope MUST be reviewed periodically
Migrations and Schema Changes
All migrations MUST:
- Enable RLS on new user-owned or regulated tables
- Define RLS policies before data is exposed
- Document table classification
- Include rollback considerations
A table without RLS is considered insecure by default.
Testing and Verification
The following MUST be verified:
- Users cannot access other users’ data
- Admin access is limited and scoped
- RLS policies behave correctly for edge cases
- Compliance-regulated tables enforce access controls
Automated tests SHOULD include RLS validation where feasible.
Failure and Misconfiguration Handling
If RLS is misconfigured or fails:
- Access MUST fail closed
- Data MUST NOT be exposed
- Errors MUST be logged
- Deployment MUST be blocked until corrected
Non-Negotiable Rules
- RLS is mandatory.
- No client bypass exists.
- Least privilege is enforced.
- Compliance data access is logged.
- Convenience does not override security.
References
- docs/governance/doc-authority.new.md
- docs/contracts/authz-and-roles.new.md
- docs/contracts/data-retention.new.md
- docs/contracts/rate-limits-and-abuse.new.md
- Supabase Row Level Security documentation
End of Document