Multi-Tenant & RLS
Local Lead Legend enforces tenant isolation at two layers: the application query layer and the database (Postgres Row-Level Security). This is defense in depth — and the isolation boundary once multiple agencies share the same database.
Layer 1 — application query scoping
Section titled “Layer 1 — application query scoping”Every request resolves an acting org (see Subaccounts & X-Org-Id),
and every query is scoped to that org. A route that forgets org_id is the number-one bug class
in Local Lead Legend, so org scoping is checked first in review.
Membership is validated against crm.org_members: a caller who is not a member of the requested
org gets 403, and the API never leaks whether the org exists.
Layer 2 — database Row-Level Security (RLS)
Section titled “Layer 2 — database Row-Level Security (RLS)”At the database level, RLS is enabled and forced on the crm base tables that carry an
org_id, with an org_isolation policy on each. The acting org is bound to the database session
on every request via a per-request setting (a Postgres GUC, app.current_org_id), and the policy
scopes every query to the acting org and its direct children (honoring the parent_org_id
hierarchy). The application connects as a non-superuser role that cannot bypass RLS.
This means that even if an application-layer query forgot to scope by org_id, the database
would still return only the acting org’s rows. RLS is fail-closed.
Bootstrap
Section titled “Bootstrap”Resolving the acting org itself has to query membership before the org GUC can be set (a chicken-and-egg problem), and a brand-new user’s first request provisions their owner membership. Those steps run under a sanctioned system bypass for resolution and owner-provisioning only, then the request immediately switches to the org-scoped policy for the rest of the handler. The bypass never leaks past resolution.
Cross-org paths
Section titled “Cross-org paths”Legitimately cross-org paths — provider webhooks that carry no X-Org-Id, and some
operator/settings reads — take the sanctioned system bypass deliberately, and resolve the org
internally. Everything else is org-scoped.
Why it matters for white-label
Section titled “Why it matters for white-label”DB-level isolation is the binding gate for letting multiple agencies share one database safely. With RLS forced and the app on a non-bypass role, a child-only token is blocked from the agency org at the database itself — not just by application code.