Reference architecture · Updated 23 September 2026

Secure internal knowledge assistant.

Retrieval over a document estate that already has an access model. The hard part is not the model. It is proving that nobody can read what they could not read before.

This is a design document, not a client project. Every figure below is either a scenario parameter or a design target. None of them is a measured result. When we publish a measurement, we will say what we ran and you will be able to re-run it.

The scenario this is designed for

Organisation400 to 800 people, professional services or manufacturing
Corpus10,000 to 20,000 live documents
SourcesSharePoint, Google Drive, a ticketing system
Access modelAlready exists, group-based, and is not up for renegotiation
UsersEveryone, with what they see differing per person

What actually decides feasibility

Three constraints. None of them is the choice of model, and none is the choice of vector database, which is where most proposals spend their first page.

01 — Can permissions be resolved at query time?

If group membership can only be read in a nightly export, then every answer is up to a day stale on access rights. Someone who left a project on Monday can be quoted its documents on Tuesday. This single question decides whether the project can be deployed beyond a pilot group, and it has to be answered in week one, not at integration.

02 — Do documents carry an owner?

Retrieval surfaces the most semantically similar passage, not the most correct one. Where two documents contradict each other, the system needs a rule to prefer one. Without an owner or a review date, that rule does not exist and the assistant will confidently serve the outdated version.

03 — Is there a question set?

Without a list of real questions with known correct answers, there is no way to say whether the system improved or regressed. Public benchmarks do not transfer: they measure performance on someone else's corpus. Building this set is the first deliverable, before any retrieval code.

The architecture

Query path

A question is embedded and matched against the index. Candidate passages are then filtered against the asking user's live group membership, resolved at query time rather than from a cached export. Only permitted passages are assembled into context. The model answers from that context only, and every claim carries its source. If no permitted passage supports an answer, the system says so instead of generating one.

The filter sits after retrieval and before context assembly. Filtering at ingestion instead would require re-indexing every time somebody changes team.
Why the filter is not applied at ingestion. Indexing one copy per permission group looks simpler and fails on the first reorganisation: permissions change far more often than documents do. Filtering at query time costs a little latency per request and removes an entire class of stale-access incident.

How we would know it works

The protocol below is what we would run. The numbers are targets set before building, so that the result can disappoint us rather than be redefined afterwards.

What we measureHowTarget
Unsupported claimsManual review of answers against cited passagesunder 5%
Permission leakageReplay the question set as users of differing accesszero, and it is a release blocker
Retrieval recallQuestion set with known source documentsagreed with the client before build
Refusal rateShare of questions answered "not found in your documents"tracked, not minimised
Actual usageWeekly active askers against headcount in scopethe one that decides success

Refusal rate is deliberately not minimised. A system pushed to always answer will answer from nothing, and the first confident wrong answer in front of a client costs more than a hundred honest refusals.

What we would refuse to build

  • An assistant over a corpus nobody owns. It will serve the outdated version faster than a colleague would.
  • A version that bypasses the access model "just for the pilot". Pilots become production, and the exception is never removed.
  • Anything without the question set built first. There would be no way to tell improvement from regression.
  • An answer path with no refusal branch.

Cost structure

We are not publishing per-token prices here. They change without notice, and a figure quoted from memory is worse than no figure. What is stable is the shape of the bill, and it is rarely where people expect.

  • One-off: initial embedding of the corpus. Real, and smaller than most people fear.
  • Recurring, per query: embedding the question, then generation. Driven by how much context you assemble, not by corpus size.
  • Recurring, fixed: the vector store and the permission resolution calls.
  • The one people forget: re-embedding when documents change. On a live estate this is not an edge case, it is a weekly job.
Book a free review The service behind this