A RAG system that retrieves brilliantly and leaks across tenants is a breach with good UX. This playbook designs the isolation architecture: document-level authorization, index-per-tenant versus metadata filters, the PII-in-embeddings problem, and the poisoning surface — as a reviewable design artifact.
Tier: Advanced · Hands-on time: ~40 minutes
The canon takes this seriously: Azure's baseline chat reference architecture is explicitly network-isolated, and DPDP practitioner analysis is blunt that prompts, embeddings, and model outputs are all personal-data surfaces in their own right. The security track owns attack depth; the architect owns what this playbook produces — the isolation model, drawn and justified, before the first document is ingested. Retrofitting tenancy into a live index is the expensive version of this afternoon.
Map every place data rests or flows. Source documents, chunks, embeddings, vector index, retrieval cache, prompts, outputs, traces. For each: which tenant's data, which users may see it, and which regulation touches it. This map is the substrate for every later decision.
Choose the tenant isolation model deliberately. The fork: index-per-tenant (hard blast-radius boundary, per-tenant deletion is index deletion, but cost and ops multiply with tenant count) versus shared index with metadata filters (efficient, scales to thousands of tenants, but every query is one missing filter clause away from cross-tenant leakage). Hybrids are legitimate — dedicated indexes for regulated or premium tenants, pooled for the rest. Write down which contractual promise ("your data is never co-mingled") the choice must honor.
Design document-level authorization as a retrieval-time property. Source ACLs must survive into retrieval: carry permission metadata on every chunk, resolve the caller's entitlements at query time, and filter before the LLM ever sees context. Decide the staleness contract too — when a user loses access to a document, how long until retrieval reflects it?
Red-team the design before review does. Vikram runs this on a BFSI knowledge copilot before it reaches his ARB:
Act as an adversarial reviewer of this RAG tenancy design (attached:
isolation model, filter scheme, ACL sync approach).
Attack it specifically on:
1. Cross-tenant leakage: enumerate every query path where a missing or
wrong metadata filter returns another tenant's chunks.
2. ACL drift: what happens between a source-permission revocation and
index sync? Who can see what during the gap?
3. Embedding exposure: which fields end up inside embedding vectors,
and what would deletion of one data principal's data actually require?
4. Poisoning: which ingestion paths accept content that could carry
injected instructions into future prompts?
For each finding: severity, concrete scenario, and the design change
that closes it. Do not soften findings. Flag anything you cannot
assess from the attached material as UNKNOWN.
Decide the PII-in-embeddings stance. Embeddings derived from personal data are personal-data surfaces. Options: redact PII before embedding (redaction gateway in the ingestion path), embed but scope deletion to chunk-plus-vector, or keep PII-bearing content out of RAG entirely. Whatever you choose, deletion must be executable: a named path from "data principal requests erasure" to vectors actually gone.
Bound the poisoning surface. List every ingestion source that accepts third-party or user-supplied content; those documents can carry adversarial instructions into prompts. Design the mitigations you can draw: source allowlists, content quarantine on ingest, and clear provenance metadata so a poisoned answer can be traced to its chunk.
Ship the artifact. One diagram (data flows with trust boundaries), the isolation ADR (model chosen, rejected alternative's best argument, revisit trigger at tenant-count or regulation change), and the authorization design table (surface × control × staleness contract).
Per MSA discipline, the isolation design itself may be client-confidential — build it in client-approved tooling or describe the architecture abstractly (tenant classes, not client names) to external assistants. Use synthetic tenants and schema-faithful fake documents for all leakage testing; real tenant data never enters test indexes. Where contracts require, place the whole pipeline in client tenancy — Bedrock or Azure OpenAI inside the client subscription with private endpoints — and for the strictest data classes run embedding and retrieval locally (Ollama + pgvector) so vectors never leave the boundary.
Tenancy is decided at design time and proven with a hostile query — index-per-tenant buys blast radius, metadata filters buy scale, and either way embeddings are personal data with a deletion path you have actually executed.