Access-Controlled Enterprise RAG
By Sourav Banerjee · Last updated 5 Oct 2026 · Report an issue
Read the worked design: Enterprise Knowledge Assistant
7 min read
Pushing permissions into retrieval makes every answer safe, but a check that is only cheap and approximate can never be the final word on who sees what.
Multi-source RAG is easy; giving three people three different correct answers to the same question is the hard part. Design around access control from the first minute, and pace the round with the six-step whiteboard clock.
Objectives:
- frame the round so access control shapes the retrieval path, not the other way round;
- choose between post-filtering, partitioned indexes and pre-filtering, and justify combining two;
- explain the two-layer filter and post-check and why the LLM is never the enforcement point;
- build hybrid retrieval with fusion and reranking, ordered after enforcement;
- gate releases on a zero-leak security suite and fail closed on authorisation.
Frame the Round Around Different Correct Answers
The prompt is "Architect a RAG-based system that pulls from multiple enterprise data sources with access control." Say one sentence in the first two minutes. Anyone can build multi-source RAG. What makes it hard is that a Tier-1 agent, a Tier-3 engineer and an account manager must get different correct answers to the same question. So access control is not a feature added at the end; it decides the shape of the retrieval path.
That sentence names the real difficulty and signals experience. It also sets up every later decision. Then ask the questions that change the design. Who are the users, and do they all see the same data? The answer is always no. What are the sources, and who owns permissions in each? What is the sensitivity range, and are there regulatory constraints such as residency, PII, right-to-erasure or audit retention?
Ask about scale, latency budget, whether the assistant can act, and what a wrong answer costs. Read-only halves the guardrail surface. Then scope out loud: read-only Q&A over six sources, role- and attribute-based access, multi-tenant, under 3 seconds. Write actions and real-time streaming ingestion are descoped.
Anchor on One Question and Five Personas
Anchor the design on a concrete customer. Meridian Cloud is a B2B SaaS observability company. Its sources are a public help centre, internal runbooks and tickets, confidential post-mortems, confidential contracts and pricing, and restricted security advisories. One question drives everything: "Why did Vertex Financial lose data in March, and do they get service credits?"
| Who asks | Correct answer |
|---|---|
| Tier-1 agent | Platform backlog; credits go to the account manager |
| Tier-3 engineer | The engineering root cause; the account is credit-eligible |
| Account manager | The contractual credit tiers, but not the root cause |
| External contractor | Nothing |
| Another tenant | Nothing at all |
Draw this table early. It is the requirement, and everything after it is justified against it.
Write the nouns next: tenant, principal, group, compartment, document, chunk, ACL, query, run, trace and citation. Then narrate one request in words before drawing. The Tier-3 engineer asks. Identity and attributes resolve from the IdP and compile into a filter. Search runs over only the permitted slice, dense and keyword fused. The policy is re-checked on what came back, the results are reranked to six, and sufficiency is checked. The answer is generated with citations, and every citation is verified as real, permitted and grounded.
Draw Two Flows and Make the Order Structural
Draw ingestion and the query path, and label every arrow. Ingestion runs connectors, normalises to a common schema, validates ACLs, chunks by structure, embeds and indexes into a per-tenant collection.
connectors ──> normalise ──> VALIDATE ACLs ──> chunk ──> embed ──> index (per-tenant)
translate each REFUSE anything
source's perms with no usable ACL
to our ABAC (a latent leak)
The connector's real job is translating each source system's permission model into ours. Getting that translation wrong is the number one cause of enterprise RAG leaks. A document with no usable permissions is refused, not defaulted to "internal" in hope.
AUTHORIZE ─> PLAN ─> RETRIEVE ─> ENFORCE ─> RERANK ─> GRADE ─> GENERATE ─> VERIFY
identity, multi- filtered authoritative 20 -> 6 insufficient:
compile hop? search re-check + refuse + escalate
filter redaction
Authorise runs first, and enforce runs before the model sees anything. That ordering is the security property of the whole system. So encode it in the graph's edges, not in a code convention someone can forget.
Choose Pre-Filtering Inside a Tenant Partition
Announce where the risk is: access control and retrieval quality. The vector database choice is close to irrelevant by comparison. Then name three access-control patterns before choosing.
| Pattern | How it works | Verdict |
|---|---|---|
| Post-filter | Retrieve everything, drop what the user cannot see | Wrong: a top-6 shrinks to a top-2, crowded out by unseen material, and result counts leak |
| Partitioned indexes | One index per tenant or group | Strongest isolation and simple, but expensive and awkward with overlapping groups |
| Pre-filter | Push the permission check into the search query | Unauthorised chunks are never scored, ranked or returned |
Use partitioning and pre-filtering together: partition by tenant, pre-filter within it. That is defence in depth. If the metadata filter is ever wrong, the blast radius stops at the tenant boundary.
Use attribute-based access, not role-based. Principals carry tenant, groups, clearance, region, compartments and an external flag. Resources carry tenant, allowed groups, sensitivity, region, need-to-know, validity dates and a PII flag. A policy with deny-overrides compares them and returns allow plus obligations, such as redacting PII and auditing access.
| # | Rule | Denies when |
|---|---|---|
| 1 | Tenant isolation | Different tenant; nothing crosses, ever |
| 2 | Clearance | The document outranks the principal |
| 3 | Data residency | A region-locked document, principal elsewhere |
| 4 | Embargo | Before publication or after expiry |
| 5 | Need-to-know | Principal not in the compartment |
| 6 | External | Contractors cannot read commercial sources |
| 7 | Default deny | Nothing granted access |
Why attributes? "EU engineers on the vulnerability-response team may read restricted advisories, but only after the embargo lifts" is one rule in ABAC. In RBAC it is a combinatorial explosion of roles.