An employee asks a question and gets a sourced answer that respects their document access.
An employee asks about a procedure, price list, or decision in everyday language. The system searches only the documents that person may open and returns an answer with the source identifier. Document owners remain in control of access.
What we measured
The reference implementation uses 600 synthetic documents and five fictional accounts. It checks that answers and sources stay within the asker's permissions. It contains no client content or identities.
- Access-control test
- What we measured
- Permission checks and prepared cases
- Company knowledge with access controls
- Verified
- synthetic corpus
Problem, solution, and result
The problem
Knowledge is scattered across documents, inboxes, and the memory of a few experienced colleagues. Employees repeat the same questions, while ordinary search neither understands the request nor respects document access.
How it works
The employee's identity and groups travel to the database with the question. The database returns only documents inside that person's scope, and the system writes a sourced answer from them. Unauthorized material remains outside the entire process.
750 question-card pairs, zero out-of-scope releases
The reference implementation uses 600 synthetic documents and five fictional accounts. It checks that answers and sources stay within the asker's permissions. It contains no client content or identities.
For whom
This system fits companies where employees repeatedly ask for information already stored in documents and some of that material is restricted to specific teams.
Identity → scope → an answer with a source
- 01The asker's scope travels into the database with the question
- 02Answer and citation come only from documents that person may open
- 03Conflicting sources and requests for wider access go back to a human
- Business type
- Mid-sized and large organizations with a private knowledge base and role-based access
- Input
- A logged-in employee's question and the groups on their session, over a catalog of 600 documents
- Boundary
- An answer is assembled only from documents the asker's card opens, and the refusal reads the same whether a closed document exists or not
- Cost
- PLN 0 in external API fees for the recorded run; 3 answers prepared locally, 521 ms median.
- Security
- A document outside the user’s permissions never enters search or the answer. A refusal does not reveal whether the document exists.
- Speed
- We measure answer time in a pilot using the client’s documents and permissions.
- Trace
- The history shows the question, applied access scope, sources used, and answer status.
- Similar system build
- from €6,000 net (approx. $6,500) · 4–10 weeks
The access boundary
A restricted document stays out of the answer
An answer uses only documents the employee may open. If the available sources contradict each other, the system sends the question for clarification instead of choosing the more convenient sentence. A question outside the employee's access ends in a refusal that can be taken to the document owner. The demonstrator reads the catalog but cannot add notes or approve anything into shared memory. The optional local model drafts only from material that has already passed the access check.
- Boundary
- An answer is assembled only from documents the asker's card opens, and the refusal reads the same whether a closed document exists or not
- Cost
- PLN 0 in external API fees for the recorded run; 3 answers prepared locally, 521 ms median.
- Security
- A document outside the user’s permissions never enters search or the answer. A refusal does not reveal whether the document exists.
- Speed
- We measure answer time in a pilot using the client’s documents and permissions.
Questions phrased in different words remain harder
The demonstration sometimes misses a relevant document when a question uses different wording. In that situation it refuses to answer. A pilot must test the client’s vocabulary, identity source, permission changes, and session security.
Estimated impact
Calculate the impact at your volume
This estimate uses the stated volume. Enter your own numbers to assess the possible impact in your company. The result is confirmed only during a pilot.
Today
Current assumption: 250 h/month (25 min/query)
With the system
After scenario: 70 h/month (7 min/query)
Time or cost saved
Modelled outcome: 135-215 h/month, 180 h base case
- Volume
- Modelled scenario: 600 queries/month
- Formula
- 600 x (25 - 7) min / 60 = 180 h/month
- Calculation status
- medium
Data in the screenshots. The names, amounts, and documents shown in the screenshots are synthetic. Client data remains private. Measurements describe the demonstrator and are kept separate from production outcomes.
Working surfaces
Document owners still decide who has access, and a human settles contradictory sources.
A project manager asks for the current mobilization rate and gets 4,450 PLN net with the identifier CEN-2026, although two price lists sit inside their scope. The answer uses the version still in force; the older list remains in the catalog with its replacement date. The same question from a new starter ends in a one-sentence refusal because pricing is outside their scope. When available sources conflict, the system refuses to choose one version and routes the issue for clarification. Without scope, it returns the same non-revealing refusal. The security team can inspect why the model cannot see excluded material: the query with its group predicate and the database row policy. Search-time savings must be measured on your catalog, questions and volumes.
Three screens: the query desk, two cards side by side, the check.
Query desk
The question, the answer, and the identifier of the document it came from; one click opens the exact passage.
Two cards side by side
The same question under two reader cards: a release with its identifier next to a refusal without one.
The check
The aggregate trial of 24 signature-free paraphrases, including 45 question-card pairs with access to the sought document, shows both coverage and the ranker's boundary.
System screens
See how the system works in practice
These desktop and mobile screenshots come from the running application. They show the process and the points where a person makes the decision.
- Screens
- 9
- px
- 1440 · 390
- 021440×1100
The same HR unit under two scopes: a release from HR-PLAC-07 beside a refusal without a signature or returned documents. - 031440×1100
A signed OIDC session framed on a phone: CEN-2026, the exact source, and zero fragments loaded before the scope check.
Open the remaining screen archive (6)
- 041440×1100
The current version - 051440×1100
Conflicting sources - 061440×1100
Direct opening outside scope - 071440×1100
A query with a signed card - 081440×1100
Scope and citation matrix - 091440×1100
RLS and the audit trail
Technology stack
The guarantee lives in SQL, because that is the one place an auditor can read it.
This process needs no orchestration framework and no separate vector store: the whole request is one SELECT with a group-overlap condition, and the safeguard is a row policy in the same database that holds the documents. A separate vector service would move the access lists away from the place that enforces them and force two copies of permissions to stay in step. So an auditor reads migrations and a policy rather than a slide, and maintenance comes down to one database, one API service and an identity source. Bielik enters only after the material has been filtered, and it runs on the client's own machine when the data may not leave.
- PostgreSQL 17 with pgvector 0.8.1
- holds the 600 documents, the vectors, the access lists, the notes and the audit chain, and enforces scope with a row policy
- FastAPI 0.116.1 and psycopg
- one layer: the hybrid query with its group predicate, and the deterministic answer policy with its relevance threshold
- Dex 2.43.1
- signs the OIDC identity, so groups arrive with the session as signed claims
- Next.js 16.2.12 and React 19.2.8
- the query desk, the document register, the two-card comparison and the run check screen
- Bielik 4.5B v3.0 Instruct (MLX 8-bit)
- optional drafting on a local machine, only over already filtered passages and with no write tools
The client takes the code, the migrations with the access lists, the prompts, the evaluation data and the documentation. The reference implementation runs as four Docker Compose services on generated test data and touches no client documents, identities or credentials.
Technical details and measurements
The working loop
Who is asking first. What they may see second. The answer after that.
That order is the design. Scope is settled before the first line of text is read, so a document outside the asker's permissions has no stage at which it could shape the answer, the citation or the refusal.
A logged-in employee's question
The session: who they are and what they may open
Scoped search → the database checks the scope again
An answer with the document identifier
Conflict or no accessible source → one sentence of refusal
The question, the scope and the answer in the hash chain
System architecture
A group predicate in the query, a row policy in the database, the model last.
Two independent scope layers around one hybrid query, a deterministic answer policy in code, and optional drafting on a model that sees only filtered passages.
- 01
Identity
The session carries the login together with its groups.
Dex signs the OIDC identity and the session carries groups as signed claims. The asker's scope is known before the system reaches for the first document.
- 02
Scope
The group predicate is part of the query.
Lexical and dense search run in a single SQL query with an explicit group-overlap condition. A document outside the scope never appears among the candidates, so it can shape neither the ranking nor the wording.
- 03
Row
The database binds the application with a row policy.
The czytelnia role is created nosuperuser nobypassrls with read-only rights on documents, so forced row-level security binds it. We verify this separately: a predicate-free query under the shared scope returns 99 of 600 documents.
- 04
Answer
A cited document or a controlled status.
The answer policy is deterministic and extractive. A question without an identifier must clear a relevance rule: a full-text match, or dense similarity of at least 0.22 with at least two shared tokens. Contradictory sources end in a status for clarification, and no accessible source ends in one sentence of refusal.
Why we do not filter citations after the answer is written
Stripping forbidden citations from a finished answer fails as a control: the document has already shaped the wording, and the refusal itself can still betray that something exists. The one piece above the minimum here is the second enforcement layer in the database, and it pays for itself: one row policy and one role that cannot bypass it, in exchange for showing scope in SQL rather than on a slide. Components without an enforceable control stay out of the system.
- Scope is settled before the first line of text is read
- The same refusal whether the closed document exists or not
- An instruction hidden in a document does not widen scope
- Question, scope, passages used and answer all enter the hash chain
Want to assess a similar process in your company?
- A 30-minute call with the engineer who would lead the work.
- A review of the processes that cost you the most time and money.
- A written summary of what to automate first and the likely cost range.
Times are shown in your own time zone. We work with clients across time zones.
The scan is free and creates no obligation. If automation is unlikely to pay off, the written recommendation will say so.