FeaturesTrustSecurityPricingCompareConnect your AIBlogStart Free
BlogAugust 4, 2026

Can your data room AI see what you cannot?

A permission filter can live in three places, and two of them are not controls. Here is how to tell which one a vendor has built, the query predicate we use, and what an adversarial caller receives.

Three places a filter can live

Every AI data room applies a permission filter somewhere. Vendors describe all three the same way, so the wording tells you nothing and the layer tells you everything.

  • Inside the retrieval queryenforced

    The permission check is a predicate in the WHERE clause. An unauthorised chunk is never selected, so there is no downstream code path that could return it.

  • After retrieval, in application codebypassable

    The rows were already read. Every new caller, every error branch, every log line and every cache is a place the unfiltered result can escape through.

  • As an instruction in the promptbypassable

    The restricted text is already in the context window. Asking a probabilistic system not to use it is a preference, not a boundary.

The same filter, three placements. Only the first one is a control.

Placement is half of the control. The other half is the identifier the predicate checks: it has to come from the server, derived from the session, and the function has to be unreachable by any caller who could supply a different one. Both halves have to hold.

How Sifrsys builds it

The subject is rag_vector_search, the function every chat answer retrieves through. Its permission logic is two predicates in one WHERE clause:

WHERE c.tenant_id = p_tenant_id
  AND d.deleted_at IS NULL
  AND d.status = 'ready'
  AND (d.ai_chat_enabled IS NOT FALSE)
  AND participant_can_access_document(p_participant_id, c.document_id)
-- similarity threshold, ordering and limit follow

participant_can_access_document resolves the participant's group defaults, walks up the folder tree for inherited folder permissions, then applies any document-level override, and returns true only at view level or above. The tenant predicate is separate and deliberate: it holds even if the permission resolver is wrong.

  1. Question
    Participant identity comes from the session, never the request body
  2. Embed
    Query vector only, no document content
  3. Retrieve
    Tenant and participant predicates inside the SQL
  4. Answer
    Model sees authorised chunks only
  5. Cite
    Page or cell range on every claim
A chat request. The permission boundary is at step three, before any document text exists in the process.

What each caller receives

Callers against the retrieval function, and what enforces each outcome.
CriterionWhat it receivesEnforced by
The room's own participantPassages from documents they may openPermission predicate in the query
A participant of another roomNothing from this roomPermission predicate in the query
A participant of another organisationNothing from this organisationTenant predicate in the query
A direct call with the public browser keyCall refusedExecute permission revoked for client roles
Callers against the retrieval function, and what enforces each outcome.

The last row is what makes the predicate trustworthy. Direct execute permission is revoked from every client-reachable role, so the only way to reach the function is through a server that derives the participant from the session.

One consequence worth naming. Because the fence is a predicate rather than a post-filter, an answer can only cite what the participant could already open, which is why every citation is checkable by the person who received it. That is covered in the citations piece.

Related: What a citation has to point at · Do watermarks survive screenshots · Pricing

Permission-fenced AI with cited answers is included in every paid tier rather than sold as an add-on. See the tiers.

FAQ

Questions about permission-fenced AI.

AI retrieval that returns only the documents the asking participant is already allowed to open. Sifrsys enforces this at the database level: the permission check is a predicate inside the retrieval query itself, so an unauthorised chunk is never selected, not selected and then hidden.
Because the rows were already read. Every path that forgets to apply the filter, every new caller, every error branch that returns the raw result, and every place the text is logged or cached becomes a way out. The filter is correct only where nothing else can be added downstream of it.
No. A system prompt that says to answer only from permitted documents is a request to a probabilistic system that has already been handed the text. If the restricted content is in the context window, the control has already failed, whatever the model does next.
Ask which layer the check runs in and ask to see it. A vendor whose filter is in the query can point at the predicate. Then ask what a caller who substitutes another participant's identifier receives, and what the retrieval function's execute grants are. If the answer is that the application never sends the wrong identifier, the control is the application, not the database.