Skip to main content

D10 — RLS role provisioning & grants (code-verified)

Architecture decision record, relocated verbatim from the retired single-file docs/tenancy/ decision log. Status, thematic clusters, and how to record a new ADR: the decision log index.

  • tenants:rls creates the RLS login role via CREATE USER … LOGIN PASSWORD (Postgres defaults it to NOBYPASSRLS ✓) and applies ENABLE + FORCE ROW LEVEL SECURITY ($forceRls = true). FORCE means the table owner is also subject to RLS, so the central role must have BYPASSRLS to see all tenants (local stables is a superuser ⇒ fine; staging/prod set it explicitly in stables-core-infra).
  • grantPermissions re-runs on every tenants:rls call and GRANTs on all current tables, so the rule "run tenants:rls after every migration" also keeps grants current for new tables. Therefore tenants:rls is added to docker/dev-start-app.sh right after migrate, and the deploy pipeline runs migrate --force && tenants:rls.
  • Hardening (tracked): the package GRANTs ALL (incl. TRUNCATE, which bypasses RLS and could wipe every tenant's rows) on existing tables to the RLS role. The app never issues TRUNCATE in tenant context, but for least-privilege we override the schema manager to grant only SELECT, INSERT, UPDATE, DELETE (+ sequence usage). See §3.

← Decision log index