RLS boundaries

RLS filters rows for a given SQL statement. It does not replace network controls, gateway verification, or correct GRANT configuration.

What you will learn

  • GRANT vs policy order of operations
  • Failure modes: empty results vs errors
  • When Flux’s baseline v2 model does not enable RLS by default

The idea

Postgres evaluates privileges before RLS filters. If the role cannot SELECT the table, you see 42501, not “zero rows”.

On v2, the architecture spec notes RLS is not required initially for the baseline threat model—schema + role separation carries much of the isolation story. Adding RLS is an application choice with performance and complexity tradeoffs.

How it works

Typical checklist:

  1. GRANT appropriate table/schema privileges to the JWT role.
  2. ENABLE ROW LEVEL SECURITY.
  3. Add policies that reference stable claims (sub, org id, …).
  4. Test with real tokens, not only superuser sessions.

Example

A policy that compares uuid to a text claim silently returns no rows—type discipline matters. The full diagnostic flow for "empty array instead of error" lives in Troubleshooting; the diagnostic for 42501 (when the role cannot reach the table at all, before RLS is even consulted) is at Troubleshooting → 42501.

Next steps