Skip to content
~/miran

02/Security · PostgreSQL · RLS·4 min read

Tenant Isolation for AI Systems Belongs Below the Prompt Layer

Prompts are not a security boundary. Multi-tenant AI needs organisation and workspace isolation enforced in application code and the database.

the prompt is not a wall

Multi-tenant AI products tempt a dangerous shortcut: put tenant rules in the system prompt and hope the model complies. That approach collapses under adversarial input, retrieval poisoning, confused deputies, and ordinary bugs. A model that “usually” respects a written rule is not an authorization system.

Isolation belongs below the prompt layer — in authentication, membership, request context, query planning, and database policy. The model should operate inside a workspace that has already been constrained by deterministic controls.

AtlasCore’s design centre is that knowledge, retrieval, and answering inherit the same tenancy boundary. The LLM is a component inside that boundary, not the mechanism that creates it.

This distinction also changes how incidents are investigated. If a leak happens, you want to ask which policy, role, or context failed — not whether the model “forgot” a paragraph of instructions. Security reviews get sharper when the boundary is code and SQL policy rather than prose.

organisations, workspaces, and fail-closed context

A practical tenancy model separates organisations from workspaces. Organisations own membership and administrative surfaces. Workspaces scope knowledge, retrieval, and day-to-day AI workflows. Switching workspace context should be an explicit product action, not something inferred from free-text instructions.

Fail-closed workspace context means operations do not proceed with a guessed or ambient tenant. If membership or workspace selection cannot be validated, the request stops. That is stricter than “best effort filtering” in application code after a broad query already ran.

Live membership revalidation matters because sessions outlive role changes. An invitation revocation, team change, or workspace removal should not leave stale authorization assumptions hanging around until a token expires on its own schedule.

postgresql rls and force rls

Application checks are necessary and still insufficient alone. A missed filter in one endpoint can leak rows. PostgreSQL Row-Level Security pushes isolation into the database so queries execute under policies bound to the tenant context of the connection.

FORCE RLS matters because it prevents privileged table owners and bypass paths from casually skipping policies. Isolation becomes a property of the data plane rather than a convention in the happiest code path.

A restricted runtime database role complements that model. The application should not connect with a superuser-equivalent role that can disable controls. Least privilege at the DB role level reduces the blast radius of bugs and compromised credentials.

retrieval must inherit the same boundary

RAG introduces a second leak surface. Embeddings and full-text indexes are still rows. Hybrid retrieval that ignores tenant filters can surface another organisation’s documents into an evidence packet, after which a “grounded” answer becomes a grounded leak.

The correct invariant is simple to state and expensive to get wrong: every retrieval path — lexical, vector, fused ranking — must execute under the same workspace authorization boundary as ordinary CRUD. Ranking quality never excuses cross-tenant visibility.

Defence in depth stacks these controls: authenticate the principal, authorize membership, set fail-closed workspace context, enforce RLS with FORCE RLS, restrict the runtime role, and only then let retrieval and generation run. Prompts can describe policy. They cannot enforce it.

what this looks like in product terms

For operators, the visible result is boring in a good way. Workspace selectors change context. Sources and documents stay inside that context. Ask AI answers only from evidence that survived the same controls. Audit logs record security-relevant actions without needing the model to confess.

None of that requires claiming large-scale production deployment. It requires treating isolation as engineering work that survives prompt edits, provider swaps, and UI iterations.

If a multi-tenant AI system’s primary tenant boundary is a paragraph in a system prompt, it does not have a tenant boundary. It has a wish.

Engineering teams feel this most clearly when they add a second workspace. Suddenly every list endpoint, embedding query, and answer request has to prove which context it belongs to. If that proof is only a sentence in a prompt template, the second workspace is already a security incident waiting for traffic.

Related: AtlasCore case study