Folio — Zero-Trust RAG
Policy-driven RAG where access is decided in code, never by the model. Each vector chunk carries its tenant and role ACL, so unauthorized documents never reach the LLM.
The problem
Teams want to ask questions across company documents, but naive RAG turns search into a data-leak path: if retrieval returns a document the person shouldn't see, the model will happily summarise it.
Prompt-level rules like “don't reveal restricted files” are not a security boundary. The access decision has to happen before the model ever sees context.
Architecture
The policy gate is the product boundary: tenant AND (owner OR role OR explicit user). It is enforced in the API and again as a Qdrant payload filter, before similarity search and before generation.
If the gate returns no authorized passages, the request stops there and Azure OpenAI is never called. Every answer ships with citations, source excerpts, and a security trace so a manager can see why a document was allowed or filtered.
How it was built
Administrators upload a document and assign roles or named people. Chunks inherit that policy when they are indexed, so every vector stores its tenant, owner, and role ACL as filterable payload.
FastAPI handles identity, revocable JWT sessions (roles are reloaded on every request), ingestion, and the audit log. Qdrant does the filtered search, Azure OpenAI provides embeddings and grounded answers, and a React workspace shows the answer next to an Access Map of what was allowed.
Filtered search holds at about 120ms p95. Browser tests cover permission, citation, and access journeys against an isolated store.
What’s next
- PostgreSQL and managed SSO in place of local SQLite accounts.
- Reranking and persisted chat history.
- Claim-level grounding checks. Today, citation checks prove references exist, not that every claim is supported.