Mappings
How Quickback definitions compile to PostgreSQL Row Level Security policies for Supabase.
This page shows how each Quickback primitive maps to RLS policy SQL. The same firewall and access config used by the Hono target generates these policies — no Supabase-specific re-authoring required.
Schema → Tables
defineTable({ schema }) compiles to a Drizzle PostgreSQL schema and a CREATE TABLE statement. RLS is enabled on the table by default:
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;Firewall → FOR ALL USING
Firewall rules isolate data by tenant or owner. They become a single FOR ALL USING policy applied to every operation.
Org-scoped:
firewall: [
{ field: 'organizationId', equals: 'ctx.activeOrgId' },
]CREATE POLICY "projects_firewall" ON projects FOR ALL
USING (organization_id = public.get_active_org_id());User-scoped:
firewall: [
{ field: 'userId', equals: 'ctx.userId' },
]CREATE POLICY "preferences_firewall" ON preferences FOR ALL
USING (user_id = auth.uid());Access → FOR SELECT/INSERT/UPDATE/DELETE USING
Access rules layer role-based checks on top of the firewall. Each operation gets its own policy.
access: {
roles: ['admin', 'member'],
list: { roles: ['admin', 'member'] },
create: { roles: ['admin'] },
update: { roles: ['admin'] },
delete: { roles: ['admin'] },
}CREATE POLICY "projects_select" ON projects FOR SELECT
USING (
organization_id = public.get_active_org_id()
AND public.has_any_role(ARRAY['admin', 'member'])
);
CREATE POLICY "projects_insert" ON projects FOR INSERT
WITH CHECK (
organization_id = public.get_active_org_id()
AND public.has_any_role(ARRAY['admin'])
);Defense in depth — anon deny
Every generated table gets an explicit deny policy for the anon role:
CREATE POLICY "projects_deny_anon" ON projects FOR ALL
TO anon
USING (false);Unauthenticated requests are blocked at the database level even if a policy elsewhere is misconfigured.
Helper functions
Quickback emits a set of helper functions in 0100_create_rls_helpers.sql that the policies reference:
| Function | Purpose |
|---|---|
get_active_org_id() | Returns the user's active organization from user_sessions |
has_any_role(roles[]) | Checks if the user has any of the listed roles in the active org |
has_org_role(role) | Checks for a single specific role |
is_org_member() | Checks org membership |
get_user_role() | Returns the user's role in the active org |
These are used by the generated policies but you can also call them from views, triggers, or stored procedures.
What does not compile
defineActions(), views, masking, and runtime guards do not become RLS — see Limitations.