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)

  1. RLS is the primary enforcement layer for data access.
  2. RLS MUST be enabled on all user-owned tables.
  3. Server-side checks supplement RLS; they do not replace it.
  4. Least privilege is mandatory.
  5. Ambiguity defaults to denial.
  6. 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:

  1. Enable RLS on new user-owned or regulated tables
  2. Define RLS policies before data is exposed
  3. Document table classification
  4. 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