Skip to content

If persistence is not permission, where would you have drawn the line: cards only, or the entire turn? ​

TL;DR

  • A revocation has three points to reach, not two: search, the history replay, and the assembly of the next turn's context. Cards only and the entire turn are both replay lines. A narrow revocation does not reach what a stored thread already holds unless the assembly step checks it again.
  • For what a person sees, two records are defensible: keep the delivered words and withhold the derived evidence, counting a verbatim quote as evidence, or replay the turn exactly as it was shown. Either way, say that the permission behind the turn is no longer granted.
  • For what the model sees, compute the revoked state at every assembly against the permission as it is then, and never write it into the stored thread, so restoring the permission restores the result.
Position, by dateWhat a person sees on replayWhat the next turn receives
The article, 25 August 2026The answer text; source cards withheldNot addressed in the article
Stricter edge, named in the articleNothing: the whole turn is redactedNot addressed in the article
Looser edge, named in the articleEverything; the stored rows are treated as an immutable recordNot addressed in the article
Heinrich Neb, 25 August 2026The words, with a verbatim quote treated as a card, and a stamp instead of a silent replayNot addressed in the comment
The article's author, 8 October 2026The turn exactly as it was shown, cards includedThe document toggle governs what the next turn can do; a narrower revocation does not reach what is already in the thread

Published by Mnemoverse, a persistent-memory API for AI agents; its shared-memory rooms are one of the examples on this page.

After a revoked RAG answer, the argument starts with the transcript. Someone had permission. The copilot answered. The turn was stored with its source cards. A reload replayed the conversation. Then the permission moved. The visible fight is whether history should still show the cards, the words, or nothing. That fight is real. It is also incomplete.

Search can be clean. History can be clean. The document still returns. The question has two halves, and the article of 25 August 2026 addressed only the first: the replay line is about the record, what a person sees; the next-turn line is about the permission, what the model receives, and it has to be enforced where the next turn is built.

This page reads one public thread as a case study, Rodrigo Diego's dev.to article of 25 August 2026 and its comments through 9 October 2026 (two of them by this page's author), and quotes vendor documentation only for what it states.

Why is chat history a second read path into RAG data? ​

A second read path is any route other than search that returns data retrieved under a permission that may since have changed. Rodrigo Diego's article of 25 August 2026 describes a document-search copilot that stores, with every turn, the source cards it cited: which documents backed the answer, with names, versions and scores. After a refresh, the history endpoint restores the conversation and replays those sources, so "your history endpoint becomes a second read path into the same data your search guards so carefully."

The article's opening block quote:

Persistence is not permission. What a turn was allowed to show at write time proves nothing about what it may show at read time.

At write time the live path runs search, entitlement checks and a per-document view gate. At read time the history endpoint selects stored rows. Between write and read, weeks pass, and tenant admins flip two toggles: the copilot itself and the document-search capability that produces the cards. Hence the article's rule: "Entitlements drift between write and read. Re-check authorization at read time, in the service, not just at the gateway."

The article scoped that check on purpose: "The gate is entitlement-level, not document-level." A per-document check on every history page would mean a bulk authorization call per page read. The partial replay that results is a decision, not a failure: "graceful degradation is an authorization outcome, not an error state."

Cards only, the entire turn, or the record as shown: which replay line? ​

The article's closing paragraph names three lines and picks one:

When the document entitlement is revoked, I kept the words and withheld the evidence. A stricter shop would redact the whole turn; a looser one would replay everything and call the persisted rows an immutable record.

Its case for keeping the words: "the words were already delivered to this user once, and the toggle governs the document-search capability". Its own caveat: "The prose answer was generated from those documents and may paraphrase them."

By 8 October 2026 the author had moved:

Turns now replay exactly as they were shown, cards included, and the document toggle governs what the next turn can do rather than what the record shows.

Another reply that day gives the mechanism: "Since the post, a turn's result blocks are written once at turn end, exactly as streamed, and the transcript replays them as seen. The document toggle scopes doing; the record stays the record." That takes up the split proposed by the ANP2 Network account on 26 August 2026: "the toggle scopes doing, while reading what was done sits somewhere the tenant cannot flip." The account's other conclusion, "as written the posture here makes revocation retroactive over the record", was about the copilot switch, and there the author wrote: "Your retroactive-revocation point still applies one layer up."

"Copilot off still means no history reads at all (now a typed 403), with every row intact and no deletion event." On 25 August the article had answered that case with a uniform 404. The organization reads past activity through a separate path; the history endpoint is only the end user's view of it.

The article text, as read on 17 October 2026, describes the original design; the change is in the replies of 8 October.

Two conditions hold for every replay line. Keeping a record and letting someone read it are separate decisions: the 8 October design keeps every row and still admits no history read when the copilot is off. And a notice that the permission is gone explains the policy; it does not enforce it. None of the replay lines decides what the model receives next.

Where does a revoked document get back into the next turn? ​

Context assembly is the step that builds the prompt for the next model call from the stored thread, the new message and any tool results.

Raised in the thread by this page's author on 30 August 2026: the checks on search and on the history read leave out what gets assembled into the prompt for the next turn. A document hidden after it sat inside an earlier exchange comes back, without touching either check, when that exchange returns as context. So the redaction decision has to run again at context assembly for every continuation. The open question was whether the next turn is rebuilt from the stored thread or re-derived from retrieval.

An illustration, not any team's system:

text
turn 1   search runs under the user's permission and returns document D
         the answer quotes D; the tool result and the answer go into the thread
revoke   an admin removes view permission on D (a narrow revocation)
replay   the history endpoint re-checks the permission and applies its replay line
turn 2   context assembly loads the thread, tool result and answer included
         unless assembly checks D again, the model receives D again

On 8 October 2026 Rodrigo Diego answered:

Rebuilt from the stored thread, not re-derived from retrieval, so it's a genuine third gate and not a stricter second one.

He described what the thread holds: "The next turn's context is assembled from a checkpointed thread that holds tool results retrieved under the old entitlement." And how far each revocation reaches: "Revoking the copilot entirely closes it, because no turn is admitted at all. A narrower revocation, like the document capability or view permission on a single document, doesn't reach what's already in the thread."

PointWhat it readsRevoking one capability or one documentRevoking the whole copilot
SearchThe documents, liveThe live path checks entitlements and per-document view permission (article, 25 August)No turn is admitted (8 October)
History replayStored turns and their cardsDocument capability: cards withheld (25 August). One document: not re-checked on replay, the gate is entitlement-level (25 August). Either: the turn as shown (8 October)No history reads at all, every row intact (8 October)
Next-turn assemblyThe checkpointed thread, tool results includedDoes not reach what is already in the thread (8 October)No turn is admitted (8 October)

He named where a check would go: "The assembly step already rewrites history on every model call (guardrail scoping, tool-call repair, version stamps on document-bearing results), so that's where re-authorization would live." That is a location, not a shipping report. The precedent is in the same design: a turn cut short gets an explicit message in place of the missing tool result, "so the model sees the gap rather than a shorter conversation. A revoked result deserves the same treatment." Rewriting early turns at assembly also touches the stable prefix contract of prompt caches, a separate problem in the same step.

Delivered speech and derived artifacts: what counts as evidence? ​

Delivered speech is answer text that was already shown to this reader.

A derived artifact is anything that exists because a retrieval ran under a permission: source cards, document names, versions, scores, and text that reproduces a document verbatim.

Heinrich Neb refined the article's line on 25 August 2026: the boundary is not text against cards but delivered speech against derived artifacts.

text that VERBATIM quotes a document is a card wearing prose.

For text that mixes both, his rule: "Where provenance is segmentable, redaction should follow it per segment; where it isn't (paraphrase), keeping the words is defensible because they were already delivered". On 8 October 2026 the author called delivered speech against derived artifact "the line I should have drawn", and wrote in the same reply that "a revoked capability now governs the next turn, not the record".

That settles what a person sees, not what the model receives, because the answer text changes role. Raised by this page's author on 9 October 2026: shown back to the user, the answer is record, and the argument that it was already delivered still holds. Fed back to the model, it is material for the next turn, which is what the rule says the revocation should reach.

The cut-short precedent stops at the tool result, while the turn's own answer stays in the window. If that answer quoted the result, the model can restate a claim it once grounded with nothing left to check it against. If version stamps sit only on the tool result, the assembly step can find the revoked evidence but not the prose built on it. Whether the author's stamps reach the assistant message is unanswered as of 17 October 2026.

Why compute the revoked marker at assembly instead of writing it to the thread? ​

Because the two facts age differently. This page's author, in the same exchange on 9 October 2026: "This did not complete" is a fact about that turn and stays true forever, while "this was revoked" is a fact about the current entitlement and stops being true the moment the permission comes back. So the revoked placeholder has to be computed at each assembly against the entitlement as it is then, and never written into the checkpoint.

Written back, the placeholder has already destroyed the result by the time a revocation is undone, and every later turn is built from the thread as of the last revocation. Computed per call, there is nothing to undo: the next assembly reads the restored permission and includes the result again. Treat the stored thread as the record and the assembled context as a permission-filtered view of it. A sketch, not an API:

text
for result in thread.tool_results:
    if not entitled_now(result):
        yield unavailable_placeholder(result)   # computed per call, never written back
    else:
        yield result

The sketch covers tool results only; the quoted-answer case above needs provenance on the answer text as well.

Documentation built for context management, not for permissions, shows the same shape. LangGraph: "Checkpointers persist a thread’s graph state as checkpoints." LangChain's transient context is "What the LLM sees for a single call. You can modify messages, tools, or prompts without changing what’s saved in state." Summarization works the other way, "permanently replacing old messages with a summary that’s saved for all future turns." A revoked marker belongs on the transient side. Anthropic's context editing splits the same way on the server: "When activated, the API automatically clears the oldest tool results in chronological order. The API replaces each cleared result with placeholder text indicating to Claude that it was removed." And: "Context editing is applied server-side before the prompt reaches Claude. Your client application maintains the full, unmodified conversation history." This page borrows only that shape: a change made when the prompt is assembled, without writing to what is stored.

What should a replayed turn say when the permission behind it is gone? ​

Silence is a third product decision, and the thread argued against it. Heinrich Neb, on 25 August 2026:

I'd stamp the replayed turn with "generated under an entitlement no longer granted" rather than silently replaying it.

And: "Provenance footnote instead of redaction: the record stays honest without becoming a leak." Rodrigo Diego, on 8 October 2026, after the move to replay as shown: "If the record replays as seen, the honest version tells the reader the capability behind it is no longer granted, and the replay response carries no field for that today."

Kartik N V J K, on 26 August 2026, had already stored what such a notice needs: "I started snapshotting the doc IDs and the entitlement version onto each turn so a replay can diff against current access, not just re-render."

The stamp is a display concern. The snapshot is a diff input. This page recommends that a replayed turn keep what the record holds and carry a status computed at read time against the reader's current permission, in the replay response itself, so that every client can show it. The notice is a recommendation, not a reported implementation. Whether a record still has authority is a different revoke, covered in Memory API Response Shape: Nowhere to Put a Disagreement.

Does gating the response keep revoked data out of the service? ​

Only if the policy concerns the response alone. The article's second gate withheld the cards with one expression in the response builder. Raised by the ANP2 Network account and confirmed by the author on 8 October 2026:

The revoked payload was selected, normalized and held in memory, and only serialization was gated, so a traceback, a payload-capturing span or a debug dump would all have seen it.

Keeping cards out of a response and out of the request's data path are different properties. A response assertion establishes the former. It does not establish the latter. The author agreed with the alternative: "Driving the column list from the entitlement (already loaded by then), with a not-selected negative control, is the right shape". Then: "It became moot for the reason in your second paragraph." Replay as shown had removed the reason to withhold.

The first gate had the stronger property, and a test for it: "The test pins this: when the toggle is off, the session and turn queries are never even awaited." A test that proves the protected read never ran says more than a test of the response shape. A clean serialized response proves neither that the read never ran nor that the field was never selected.

Can a cache in front of the history endpoint replay what was revoked? ​

A check in the service protects the requests that reach the service. Vinh Nguyen, on 26 August 2026, pointed out that a cached serialized history response can bypass it: "If the endpoint is cacheable, the cache key has to include tenant plus entitlement version, or revocation must purge it". His test: "A negative test that warms the cache before revocation and replays after would cover the read path the mocked database test cannot see."

The author agreed on 8 October 2026: without an explicit cache header on the history routes, "nothing caches this" is "an assumption about whatever sits in front of the service, not a property of the service." His remedy: "Cache-Control: no-store on the history routes is the cheap fix that makes the guarantee local, and your warm-then-revoke-then-replay test is the one that proves it end to end."

So choose an explicit policy (no-store, a key that changes with the permission, or a purge on revocation) and test through the route the reader uses. Caches that answer after a delete are covered in Agent Memory Deletion: What Survives a Delete.

How do assistants, frameworks and memory APIs document this? ​

Some of the documented positions, for example, each in its own words as read on 15 to 17 October 2026.

Microsoft Copilot. The page Data, Privacy, and Security for Microsoft Copilot states: "Microsoft Copilot only surfaces organizational data to which individual users have at least view permissions." And: "Semantic Index honors the user identity-based access boundary so that the grounding process only accesses content that the current user is authorized to access." On stored history: "The stored data includes the user's prompt and Copilot's response, including citations to any information used to ground Copilot's response." And: "Your users can delete their Copilot activity history, which includes their prompts and the responses Copilot returns". Stored history there carries citations too, which is the surface this page is about.

LangChain, LangGraph and Anthropic. Quoted in the section on the revoked marker; those pages describe context management, not permissions.

Mnemoverse. In shared-memory rooms (beta), "an expired or revoked grant stops working on the very next request." The rooms reference states the boundary: "Revocation is immediate and forward-only. A revoked member loses access from that moment on. There is no retroactive un-sharing: whatever the member already read, it keeps, and atoms it wrote remain in the room." The security page puts it as "future access stops, but content a member already read or wrote is not recalled." Access can come back: "Re-inviting a revoked member restores access." And: "Treat a room's contents as shared with everyone who has ever been an active member." This is one example of the record-stays-the-record position at the level of a memory API. The next turn is assembled in the client that reads from the API, so the third point still needs its own check there.

Which tests prove the permission line holds? ​

Five tests, one per decision.

  1. Not awaited. With the copilot entitlement off, request history and assert that the session and turn queries never ran, not only that the response is empty. The article's own test of its first gate (25 August 2026). A 403 (8 October 2026) or a 404 (25 August 2026) after the query has run is a different test.
  2. Not selected. Where a policy forbids reading a field once access is revoked, assert that the field was never selected, not nulled in the response. Proposed in the thread; the author called it the right shape, then moot for his design (8 October).
  3. Warm, revoke, replay. Warm any cache in front of the history route, revoke, replay through the same route, and assert the current replay policy. Proposed by Vinh Nguyen (26 August 2026); the author called it the test that proves the fix end to end.
  4. Revoke, continue. Revoke one document's permission or the document capability after an exchange that used it, and continue. Assert that the assembled input carries an explicit marker in place of the tool result and of any quotation of it in the answer. This page's inference from the exchange of 8 and 9 October 2026.
  5. Restore, continue. Restore the permission and continue. Inspect the stored thread itself, not the model output, and assert that it still holds the original result with no placeholder written into it; then assert that the next assembly includes the result again. This page's inference from the same exchange.

A passing replay test does not establish the continuation result; a passing continuation test does not establish that restoration works.

What this page does not claim ​

No performance or latency figure for anyone; the author of the original design did not measure one. Positions are dated, because the article of 25 August 2026 and the replies of 8 October 2026 differ. Product documentation is quoted for what it states as read on 15 to 17 October 2026; where a page says nothing about revocation, this page says nothing either, and it tests no product. Apart from the first test, which the article describes as its own, the tests are proposals, not a description of any team's suite.

Common questions ​

If persistence is not permission, where would you have drawn the line: cards only, or the entire turn? ​

Neither line closes the gap on its own, because a revocation has three points to reach: search, the history replay, and the assembly of the next turn's context. For what a person sees, keep the delivered words and withhold the derived evidence, counting a verbatim quote as evidence, or replay the turn exactly as it was shown, with a note that the permission behind it is no longer granted. For what the model sees, compute the revoked state at every assembly and never write it into the stored thread.

When entitlements go finer-grained on old sessions, do you version the withheld cards or just drop them silently? ​

Do not drop them silently. Kartik N V J K, who asked this in the thread on 26 August 2026, described snapshotting the document IDs and the entitlement version onto each turn "so a replay can diff against current access, not just re-render." A replay can then mark a card as withheld instead of returning a shorter turn that looks complete.

Should chat history be filtered at write time or re-checked at read time? ​

Re-checked at read time, at every point that reads it: the replay endpoint and the assembly of the next turn. A filter at write time decides once, and permissions drift between write and read. If the policy forbids reading a field, enforce that before the field is selected, not only when the response is built.

Does revoking access remove a document from the next turn's context? ​

Not by itself, when the next turn is rebuilt from a stored thread. In the design Rodrigo Diego described on 8 October 2026, revoking the whole copilot admits no turn at all, but a narrower revocation, such as view permission on a single document, does not reach tool results already in the thread. The re-check belongs in context assembly, and it has to cover answer text that quotes the result.

Can a cache in front of the history endpoint replay what was revoked? ​

Yes, if the response is cacheable and the cache key does not change with the permission. Vinh Nguyen put the rule in the thread on 26 August 2026: the key has to include tenant plus entitlement version, or revocation must purge it. On 8 October 2026 Rodrigo Diego called Cache-Control: no-store on the history routes the cheap fix; a warm, revoke, replay test proves it end to end.

What should a replayed turn show when the permission behind it is gone? ​

What the record holds, with a visible note that it was generated under a permission no longer granted. Heinrich Neb proposed stamping the replayed turn with "generated under an entitlement no longer granted" rather than replaying it silently. On 8 October 2026 Rodrigo Diego, the article's author, agreed, and wrote that his replay response carried no field for it that day. The note is a recommendation, not a reported implementation.

Sources ​

The thread on dev.to ​

Read on 15 to 17 October 2026 through the dev.to API, the comment pages and r.jina.ai.

Vendor documentation ​

Read on 15 to 17 October 2026.

Mnemoverse ​

Read on 15 to 17 October 2026.

Edward Izgorodin · Mnemoverse · 2026-10-16

Mnemoverse is a persistent-memory API for AI agents. Free key: console.mnemoverse.com · Plans and limits · Docs: Getting Started