Sovereign RAG on Your Own Repository: Letting the Search Engine Enforce Permissions
Enterprise AI has a permission problem. Point a RAG assistant at a document repository and it will happily quote a contract the user was never allowed to open. The usual fix is to ship everything to a hyperscaler and trust an application-layer filter. For a hospital, a ministry or a court, neither half of that is acceptable.
Fifteen years of open source search inside a large content platform, and where it landed: a stack that runs on your own infrastructure, where the search engine itself decides who may read what.
Three eras, three permission models. Alfresco started on a patched Apache Solr fork with custom Lucene scorer classes and a separate ACL document type joined by hand at query time, so every Solr upgrade meant editing search-engine code. Moving to Elasticsearch and then OpenSearch replaced all of it with a standard client and a denormalised reader/denied filter. Today OpenSearch Document-Level Security pushes enforcement below the application entirely: one role, a terms lookup query, and no query the application can write will leak a document.
We then apply that to working retrieval-augmented generation over existing repositories. Live demo: two users, one question, two different answers, embeddings and language model running locally, nothing leaving the building.
You will leave with three patterns that transfer to any content source: enforce authorization in the storage layer, keep retrieval hybrid rather than vector-only, and make ingestion idempotent so batch and live sync can run together.
Who this is for
Anyone who has been asked to "add AI to our documents" and then realized the documents have access rules, and that those rules are the hard part. Public sector IT, ECM developers, search and platform engineers. No Alfresco knowledge assumed.
The arc
2010, embedded Lucene and a patched Solr. Alfresco shipped a fork of Apache Solr 6.6.5 (patch level 11), with custom Lucene Query, Weight and Scorer classes, a custom authority cache, and a custom auth plugin. Permissions were a second document type in the same index: a bitset of matching ACL records, then a manual join onto every content document. Indexing was cron-scheduled REST polling. The consequences were exactly what you would expect: eventual consistency, and a source-code change for every engine upgrade.
2021, event-driven and standard clients. Polling became a durable ActiveMQ subscription fanning out to metadata, content and path queues. Permissions became denormalized: every document carries reader and denied authority arrays, and the filter is a plain boolean terms clause built by a client. Custom code inside the engine: none. The trade-off is honest and worth showing: an ACL change now means rewriting documents.
Today, let the engine do it. OpenSearch Document-Level Security with a terms lookup query resolves the authenticated user against an ACL index at query time. One role definition scales to any number of users. The application query adds no ACL filter at all, because there is nothing left for it to forget. Packaged as an Agent Skill contributed upstream to the OpenSearch project, with a runnable demo against a secured cluster.
The payoff: permission-aware RAG. Ingest chunks, vectors, metadata and ACLs into one layer. Retrieve with hybrid search, vector plus BM25 fused by reciprocal rank fusion, with the permission filter on both legs. Ground a locally hosted model on only the chunks this caller may read. Embeddings and inference run on your own GPU, so content, queries and prompts stay inside your perimeter.
Live demo
The same question asked by two users with different permissions, returning two different answers and two different citation sets, then a permission change in the repository reconciled within seconds. Everything on one machine: no external API key, no content leaving the room.
Three things to take home
- Authorization belongs in the storage layer, not the application. Storage-layer enforcement is a materially better answer to GDPR data minimisation than a filter in application code that a future refactor can drop.
- Hybrid retrieval beats vector-only on real repository content, where exact identifiers, acronyms and paths still matter.
- Two-phase idempotent ingestion, metadata synchronously and embeddings asynchronously lets batch and live sync run at the same time safely.
Open source
The reference implementation is Apache 2.0 at github.com/aborroy/content-lake-app (plus deployment, UI and Nuxeo repositories). The permission-aware search skill is being contributed upstream to the OpenSearch project (https://github.com/aborroy/opensearch-agent-skills/tree/feat/permission-aware-search). The underlying platform is scheduled for open-source release at the end of September 2026; this session is the first conference walkthrough after that release, so attendees can clone it the same day.
Angel Borroy is Developer Evangelist at Hyland, working on Alfresco and Nuxeo, where he has spent the last several years on the search and AI side of open source enterprise content management: the migration from a patched Apache Solr fork to Elasticsearch and OpenSearch, permission-aware retrieval, and on-premises RAG.
He is a Docker Captain and a member of the Alfresco Order of the Bee, and has spoken at
OpenSearchCon, FOSDEM, DockerCon, the Linux Foundation EMEA Open Source Summit and
OpenExpo Europe.
Based in Zaragoza, Spain.
