RAGEngineering Hub
Chapter 11 · concept 2 of 6 · show all
  1. 1What RAG is, and why
    1. 1.1Why models need outside knowledge, and what hallucination means
    2. 1.2What RAG is: anatomy of a request
    3. 1.3RAG vs fine tuning vs long context and prompt caching
    4. 1.4Use cases and the quality, latency and cost triangle
    5. Chapter overview
  2. 2Tokens, cost and your first RAG
    1. 2.1Tokens and context windows for RAG
    2. 2.2The RAG lifecycle and your first RAG in miniature
    3. Chapter overview
  3. 3Getting documents in
    1. 3.1Content sources and file formats
    2. 3.2Parsing, layout and OCR
    3. 3.3Tables, images and mixed content
    4. 3.4Cleaning, normalization and quality gates
    5. 3.5Metadata, document identity and versioning
    6. 3.6Updates, deletes, reindexing and ingestion pipelines
    7. Chapter overview
  4. 4Chunking
    1. 4.1Why we chunk, and the main chunking strategies
    2. 4.2Structure aware chunking and tables
    3. 4.3Chunk size, overlap and token based sizing
    4. 4.4Contextual chunking and late chunking
    5. 4.5Parent child and multi representation indexing
    6. 4.6Chunk metadata, provenance and the chunking debugging playbook
    7. Chapter overview
  5. 5Embeddings
    1. 5.1Embeddings and similarity from first principles
    2. 5.2What embeddings cannot do
    3. 5.3Choosing an embedding model: size, cost, language
    4. 5.4Embedding model migration and index rebuilds
    5. Chapter overview
  6. 6Vector stores and scores
    1. 6.1Vector databases, ANN indexes and choosing a store
    2. 6.2Score calibration and thresholds
    3. 6.3Late interaction and multivector retrieval
    4. Chapter overview
  7. 7Finding the right chunks
    1. 7.1Query understanding, rewriting and expansion
    2. 7.2Dense retrieval and keyword search with BM25
    3. 7.3Hybrid retrieval and rank fusion
    4. 7.4topK, no good match, and metadata filtering
    5. 7.5Routing, diversity, deduplication and caching
    6. 7.6Reranking: two stage, cross encoder and LLM rerankers
    7. Chapter overview
  8. 8When retrieval fails
    1. 8.1Retrieval failure analysis playbook
    2. Chapter overview
  9. 9Building the answer
    1. 9.1Context selection, packing and citations
    2. 9.2Grounding prompts and abstention
    3. 9.3Lost in the middle and context management
    4. 9.4Conflicts, staleness and freshness rules
    5. 9.5Hallucination checks and answer verification
    6. 9.6Conversational RAG, answer UX and RAG APIs
    7. Chapter overview
  10. 10Measuring
    1. 10.1Why measure, and what to measure
    2. 10.2Building a golden dataset
    3. 10.3Retrieval metrics: precision, recall, MRR, nDCG
    4. 10.4Faithfulness and answer correctness
    5. 10.5LLM as judge, and judging the judge
    6. 10.6Offline and online evals, regression tests and slices
    7. Chapter overview
  11. 11Safety and operations
    1. 11.1Prompt injection and poisoned documents
    2. 11.2Access control, privacy and governance
    3. 11.3Index lifecycle operations
    4. 11.4Observability and tracing
    5. 11.5Latency, cost, caching and model routing
    6. 11.6Reliability, degraded modes and launch readiness
    7. Chapter overview
  12. 12Scale and advanced RAG
    1. 12.1Scaling, multi tenancy and enterprise architecture
    2. 12.2Choosing an architecture: naive, advanced, agentic, graph
    3. 12.3Agentic RAG and RAG as an MCP tool
    4. 12.4GraphRAG, structured data and multimodal RAG
    5. Chapter overview

Access control, privacy and governance

Users must only get answers from documents they may read. Filter by role before ranking, never in the prompt. Without a filter, our restricted runbook reached a customer's top 3; with one, it cannot.

A real question

A customer asks a question whose answer is in an internal runbook. What should happen?

The runbook should never reach the model for that customer. Store who may read each document on every chunk, filter by the user's real roles before ranking, and log what was shown to whom.

The problem

Why this matters

Tell the model in the prompt not to reveal internal documents.
The belief

Tell the model in the prompt not to reveal internal documents.

What really happens

Once restricted text is in the prompt, it has already left the access boundary. A prompt instruction can be ignored or overridden by injection. Without a filter, our NOC-only runbook reached the top 3 for a customer's question.

Why not the simpler way

RAG often starts as a demo over public documents, then grows into internal ones: HR policies, incident runbooks, customer records. Search does not know who is asking. Without access control in retrieval, the assistant becomes the easiest way to read documents you were never meant to see.

The idea

The idea in plain words

Access control decides which chunks a user may retrieve, based on the permissions of their source documents. Privacy covers personal data in documents and in logs: minimise, protect, delete on request. Governance is knowing what is indexed, who owns it, how long it is kept, and being able to show that.

A library with a reading room for staff: the catalogue only shows staff books to people with a staff card, it does not ask visitors to promise not to read them.

How it works

Step by step

  1. Copy the document's access list (allowed_roles, groups, tenant) to each of its chunks at ingestion, and update it when the document's permissions change.
    1

    Roles on every chunk

    Copy the document's access list (allowed_roles, groups, tenant) to each of its chunks at ingestion, and update it when the document's permissions change.

  2. Take the user's roles from the authenticated session, never from the question. Filter before ranking, in the index query.
    2

    Filter by the session

    Take the user's roles from the authenticated session, never from the question. Filter before ranking, in the index query.

  3. Log which chunks each user received. Keep logs only as long as needed. Delete a person's data, and its chunks, on request.
    3

    Log, retain, delete

    Log which chunks each user received. Keep logs only as long as needed. Delete a person's data, and its chunks, on request.

In detail

Document-level ACLs copied to chunks: allowed_roles, groups, tenant_id. Multi-tenant systems also separate indexes or namespaces per tenant (RAG-51).

Query-time filter. The filter is part of the search call, built from the session. Pre-filtering is exact; check ANN recall with narrow filters (RAG-22).

Sync. Permission changes in the source must reach the index quickly. Store a permissions hash per document and re-sync when it changes.

Privacy. Detect and mask personal data at ingestion where the use case allows. Logs of questions and answers are personal data too: retention limits and deletion apply.

The code

Try it in Python

def allowed(chunk_meta: dict, session_roles: set[str]) -> bool:
    roles = set(chunk_meta.get("allowed_roles") or [])
    return not roles or bool(roles & session_roles)      # empty list = public

def search_for(session, question, index):
    roles = session.verified_roles                        # from the login, never from the question
    pool = [c for c in index.chunks if allowed(c.meta, roles)]
    results = hybrid_search(question, pool)
    audit_log(session.user_id, question, [c.id for c in results])
    return results

See it

What we measured

Measured · restricted chunks in the top 3, hybrid search

Polder corpus, 34 recursive 512 token chunks. One document, the NOC escalation runbook, has allowed_roles [noc_engineer]. 62 questions: 47 answerable plus 15 unanswerable.

No access filter: questions with the runbook in the top 32 of 62
Of these, asked as a customer (g-39)1 (a leak)
Role filter before ranking0 for customers
Golden items testing roles3 (restricted)

Measured 2026-11-04 with corpus/scripts/measure-parts-4-7.mts. With the filter applied before ranking, restricted chunks cannot be returned to users without the role, by construction.

Try it on a real example

“When must a fibre outage be escalated to the duty manager?”

Asked by
1.NOC escalation runbook (internal)“A fibre outage affecting more than 500 connections…”✓

Allowed: the runbook lists noc_engineer. Answer: escalate within 15 minutes when more than 500 connections are affected.

Choosing

Use it when, avoid it when

Use it when
  • ACLs on every chunk, filtered before ranking
  • Role pairs in the golden set
  • Audit logs with retention limits
Avoid it when
  • Prompt instructions as access control
  • Roles taken from user input
  • Caches shared across roles

What it costs · Metadata at ingestion, a filter per query, and a sync job for permission changes.

In production

Test access with golden items per role: the same question asked by roles that may and may not see the answer, as in our g-38 and g-39 pair. Run these on every index rebuild. Audit regularly: which documents are indexed, who can see them, who owns them. Treat a cache keyed without the user's roles as a leak waiting to happen (RAG-30).

Watch out

Common mistakes

  • The model will keep secrets if asked. Text in the prompt is already exposed.
  • Filtering after ranking is fine. Restricted chunks may already be in the context or the cache.
  • Internal tools do not need access control. Internal users have different rights too.

Check yourself

Remember this

Remember these

  • Store access lists on every chunk and keep them in sync with the source.
  • Filter by the session's roles before ranking.
  • Without a filter our restricted runbook reached a customer's top 3.
  • Log, limit retention, and support deletion of personal data.

Say it in an interview

  1. 01Access control lives in retrieval: ACLs on every chunk, filtered before ranking.
  2. 02Roles come from the authenticated session, never from the question.
  3. 03Without a filter my NOC-only runbook reached a customer's top 3; with it, it cannot.
  4. 04I test with role pairs: the same question for a role that may and one that may not see it.
  5. 05Question and answer logs are personal data, with retention and deletion rules.

Quick quiz

Three questions

Question 1

Q1

Where must access control happen in RAG?

Question 2

Q2

Without an access filter, what happened with the restricted runbook?

Question 3

Q3 · from RAG-29

When should metadata filters run?

Saved on this device. No account needed.