intermediate · 25 minute study
Predict the rows a policy will reveal
One permissive policy added for convenience can widen access despite several careful policies elsewhere. Learn to evaluate the complete policy set.
Useful preparation · 1 prerequisite
Use this as a map, not a lock. If these ideas are familiar, continue.
- Identity is not authority — A signed-in user can still be the wrong user, in the wrong company, with the wrong permission. A public key and a privileged key must never be treated as interchangeable fixes.
First, build a mental model
For an ordinary SELECT, an RLS condition behaves like an enforced row filter. Within the relevant command group, permissive policies can open rows; restrictive policies can narrow that opening.
- Enabled RLS with no applicable permissive policy is default deny. A SELECT may succeed while returning no rows; this is different from lacking a SELECT grant.
- Applicable permissive policies combine with OR; restrictive policies combine with AND. At least one permissive must pass, and every applicable restrictive must pass.
- ALL policies participate in the selected command group. Policy role matching also matters: a PUBLIC policy applies to all roles; an authenticated policy does not apply to anon.
- USING sees the existing row. Only true passes; false or NULL filters it out. Membership lookups inside real policies also need deliberate access control and performance.
-- PostgreSQL / Supabase example; not SQLite syntax.
ALTER TABLE public.notes ENABLE ROW LEVEL SECURITY;
GRANT SELECT ON public.notes TO authenticated;
CREATE POLICY member_read ON public.notes
FOR SELECT TO authenticated
USING (company_id IN (
SELECT company_id FROM public.memberships
WHERE user_id = (SELECT auth.uid())
));- Grant
The role may issue SELECT on notes. That does not yet admit a row.
- Membership
A note qualifies only if its company is in the verified actor's trusted membership set.
- Composition
An additional permissive USING(true) could widen the group. A restrictive tenant fence would still have to pass.
Production thinking
Take this beyond the example.
Inventory effective policies, commands, roles, table grants and later migrations. Test direct reads for allowed, foreign and anonymous actors. A screenshot of a filtered list is not tenant-isolation proof.
Your evidence
unseen is a local learning signal, not a credential or proof of production competence.
Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.
Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.
Next lesson · Check the row before and after a change →