Why RAG Access Revocation Is Not Immediate: In-Flight Requests, Caches, and Authorization Consistency

After an employee leaves a project, a RAG system can still return information through an old cache, a request that already passed authorization, or an answer being generated. This article separates revocation commits, authorization snapshots, and output release. Drawing on official Zanzibar, SpiceDB, and OpenFGA sources, it develops an event timeline, achievable revocation guarantees, and deterministic race tests that explain why another permission check is not the same as recalling data.

Correct authorization during retrieval does not mean authorization remains valid when the answer leaves the server. A RAG request spans identity resolution, retrieval, reranking, generation, and streaming, and access can be revoked between any two stages. This article examines consistency across those stages. Its protocols and examples are engineering design analysis, not measured experiments or claims that a particular product provides every guarantee described.

Give successful revocation a testable time boundary

Permission-Aware Enterprise RAG: From Retrieval to Verifiable Answers discusses binding identity, evidence, and access scope. The next question is more specific: when a user loses access during an answer, which event must prevent further use of the material? Without an explicit answer, an administrator can see a successful revocation while an engineer sees a successful permission check, and both records may be accurate.

Distinguish at least three guarantees. A commit guarantee means the authoritative permission store has accepted the change. A fresh-check guarantee means checks initiated after revocation, under the specified consistency conditions, can observe it. An output guarantee means controlled egress points admit no new content that depends on revoked material after revocation completes. Each requires different mechanisms; one green status cannot represent all three.

Define four observation points: t_commit is the authoritative revocation commit; t_check is the state point used by an authorization decision; t_model is the admission point where evidence passes the model-input gate; and t_out is the release point where an answer passes the user-output gate. Permission at t_check establishes legality in that state. If t_check < t_commit < t_out, the old decision does not automatically remain valid through output.

The observation boundary matters as well. Bytes already handed to the network may reach a phone after the server stops releasing data. Text already delivered to an external model cannot be recalled by cancelling a local request. No new server-side release after revocation completes is a guarantee that can be designed and tested. Every endpoint immediately forgetting all content when an administrator clicks revoke is not an achievable engineering commitment.

Reproduce a race inside an otherwise normal request

Consider a constructed scenario. Employee U belongs to project group G and may read quotation attachment D. Request Q completes retrieval and authorization, then pauses immediately before the model call. An administrator removes U from G, and the permission store confirms the commit. Q then resumes. If it reuses the earlier decision, the attachment still enters the model. This path does not require a cache failure: the relevant state changed after the check.

Move the pause to the point where the model has received all context but the user has not received an answer. Retrieving again does not erase the context already supplied to this model request. Removing citation links from the final response does not establish that it avoids repeating the attachment. To block this delivery, discard the unreleased answer, cancel generation, and, where appropriate, start a new request using currently authorized evidence.

A third case begins after the user has received part of a streamed response. The system can stop subsequent output but cannot retract the text already received. A later conversation turn may also resend revoked material as history. Track the evidence dependencies of answers and conversation summaries, and rebuild subsequent context. If the sources of a combined summary cannot be traced, a conservative response is to stop using that summary and regenerate it.

This is a time-of-check to time-of-use race. MITRE's CWE-367 describes a resource changing between a check and its use, invalidating the earlier decision.[1] Applying that distinction to RAG is the architectural reasoning developed here. Moving a check closer to use can reduce the window, but without coordination it does not demonstrate that the window has disappeared.

Consistency tokens bound reads; they do not coordinate output

Google's Zanzibar paper incorporates the causal ordering of permission and content changes, preventing an obsolete authorization state from incorrectly permitting access to later content.[2] For RAG, the useful principle is to associate the evidence's content revision with the state used for authorization, rather than simply labelling a request authorized. Individual products still need implementations appropriate to their APIs and storage configuration.

SpiceDB's at_least_as_fresh requires a check to use data no older than the supplied ZedToken. The token is opaque: let the service interpret it rather than sorting tokens as strings. Its fully_consistent mode chooses a snapshot at the start of the call; later writes are not included in that check.[3] A sufficiently fresh check therefore still cannot establish that no revocation occurs after the check finishes.

The storage backend matters too. SpiceDB's documentation explicitly identifies circumstances in which fully_consistent on CockroachDB does not guarantee observing a just-written relationship. It recommends combining the ZedToken returned by the write with at_least_as_fresh.[3] Validate the deployed backend and version rather than interpreting a parameter name as an immediate consistency guarantee across systems.

OpenFGA defines HIGHER_CONSISTENCY as bypassing query caches and reading the database directly. Its official explanation also notes that custom multiregion database adapters must account for underlying replication semantics.[4][5] This is not the same API as specifying a revision lower bound with a consistency token. With either mechanism, the request first needs trusted state that covers the relevant revocation. Repeatedly supplying an old token only establishes a lower bound at an old point.

Carry authorization dependencies into caches and model admission

A request should record its tenant, verified principal, evidence documents and revisions, authorization-model version, and relevant group or policy scopes. Keep content revisions separate from permission revisions: D's text may remain unchanged when U leaves G. Comparing document update times alone misses membership changes, while a user ID alone cannot reveal that the same user's access has narrowed.

Store an evidence-dependency manifest with each cached answer, and on a hit confirm that the current principal can access every dependency. An authorization epoch in the cache key must come from trusted state, not a browser parameter. Shared caches may reuse computation; they should not reuse another user's release decision. Invalidate old entries whose dependencies cannot be identified instead of keeping them because the answer happens not to name its source document.

Epochs can be maintained at tenant, group, or resource scope, but the scope must cover inherited permissions. Tenant-wide epochs are simpler and invalidate more cached work. Fine-grained resource tracking can preserve more cache hits, but must follow parent directories, nested groups, and policy changes. An additional authorization path can also affect the final decision, so recompute effective access instead of assuming that deleting one relationship removes every route to permission.

Candidate selection, external reranking, and model admission each need checks at their own boundaries. An obsolete access list in a search index is not authoritative revocation state. If authorization is unavailable or the origin of a revision cannot be established, stop using the affected restricted evidence. The version manifests in RAG Incremental Updates and Deletion Consistency explain content-update integrity; binding a request to a content snapshot does not freeze the user's subsequent access rights.

Strict control of in-flight requests needs a completable revocation barrier

A requirement for no new release after revocation completes can be implemented with an application-level revocation barrier. The following is a conditional design, not a feature automatically provided by the authorization engines cited above. It assumes that relevant external calls and user output pass through controlled egress points, and that the revocation workflow can coordinate them. Controlling one retrieval service cannot establish an end-to-end guarantee.

First, durably record the revocation intent and suspend new releases within the affected scope. Second, commit the permission change and register its returned consistency information and a new controlled epoch in authoritative state. If the stores cannot be updated atomically, use a retryable state machine that remains in revocation pending and continues blocking on failure. Do not report full completion in the intermediate state where the permission store has changed but the egress layer has not.

Third, make serving nodes reject the old epoch, cancel affected in-flight requests, discard pending send buffers, and account for send operations already admitted. Epoch comparison and release at the egress point must have a defined ordering with revocation advancement, for example through a common coordinator that serializes the decisions. Do not compare an epoch and then place the body on an unchecked asynchronous queue. Do not acknowledge barrier completion while old operations remain unfinished or unfenced.

Finally, return revocation complete only after every egress point still permitted to serve that scope has entered the new state. An unreachable node must lose its ability to serve and synchronize its epoch before rejoining; otherwise, it may continue releasing output. This adds coordination, waiting, and possible false denials. The guarantee concerns release ordering at controlled egress points, not the arrival order of bytes already transmitted or deletion of copies already held by external services.

Bound streaming exposure and prevent retries from reusing old authority

Not every system warrants the cost of a strict barrier. An explicit bounded-revocation policy can periodically refresh authorization state, check the epoch before each output batch, and stop sending when connectivity is lost. Its bound must include synchronization, scheduling, and buffering delays. If any stage becomes unbounded under failure, the system can offer a target under normal conditions, not a guarantee that output always stops within a fixed number of seconds.

Buffering a complete answer and checking before delivery can reduce mid-stream revocation exposure, at the cost of higher time to first output. A single final check still leaves a check-to-send gap. Checking every output batch detects changes earlier, but smaller batches increase coordination overhead. Select a policy based on sensitivity and interaction requirements, and state that batches already released cannot be recalled.

When revocation triggers a retry, resolve the principal and current effective permissions again, rebuild the evidence set, and avoid continuing generation from the old context. Queued work carries the original principal and authorization dependencies and is checked again when dequeued. Do not silently rerun a failed task under a service account to make it succeed. If the remaining public material is sufficient, generate a new answer within that narrower scope; otherwise, explain the limitation without disclosing hidden document names.

Cancellation and data removal are separate operations. Cancelling generation reduces subsequent processing and output; clearing caches, logs, or provider-held data is a different workflow. Audit records need the revisions behind decisions and the release events, usually without copying the full sensitive document. Debugging a race should not become a reason to log credentials, raw tokens, or attachment contents without limits.

Test controlled event orders instead of repeatedly clicking and hoping

Build an independent fixture for U, G, and D using an isolated dummy attachment. Add controllable pause points after authorization, before model admission, and after the first output batch. The acceptance reviewer specifies event order and expected results before execution, avoiding random sleeps. Record evidence identifiers and epochs at external rerankers, model admission, and user egress so that no leak in the final answer can be distinguished from no material ever crossing the boundary.

Replay at least five counterexamples: authorize, revoke, then resume; hit an unexpired cache after membership is revoked; change only an ancestor-group relationship while the document's own permissions remain unchanged; attempt to resume old work after an egress node disconnects or restarts; and revoke after the first streaming batch. Keep a positive case where another valid authorization path still exists, preventing a system from achieving an apparent zero-violation score by rejecting everything.

Measure revocation-commit to barrier-completion time, new releases under an old epoch after completion, output batches released after cancellation, and false-denial rate for legitimate requests. For a bounded policy, also measure the interval between commit and the final old-authority release under each failure condition. Report sample counts, maxima, and incomplete revocations. Do not exclude incomplete operations and then present attractive percentiles only for successful ones.

Before launch, produce a complete evidence trail: who revoked which relationship in which scope, which authorization state covers the change, which in-flight requests were handled, and when each egress point stopped admitting output. Zero violations in testing is necessary evidence, not proof that future failure is impossible. A revocation status becomes a dependable business state only when its promise is limited to boundaries the system controls and failures remain visible.

References

  1. MITRE — CWE-367: Time-of-check Time-of-use Race Condition
  2. Pang et al. — Zanzibar: Google’s Consistent, Global Authorization System
  3. Authzed — SpiceDB Consistency
  4. OpenFGA — Query Consistency Modes
  5. OpenFGA — Query Consistency Options in OpenFGA
Back to insights
鲁ICP备2024109755号-2
Drag to move. Right-click, touch and hold, or press Shift+F10 to choose a corner.