Skip to content

⏳ feat: Add Ephemeral Retention Mode for Forced Temporary Chats - #13811

Merged
berry-13 merged 20 commits into
canaryfrom
admin/retention-mode
Sep 30, 2026
Merged

berry-13 merged 20 commits into
canaryfrom
admin/retention-mode

Conversation

@berry-13

@berry-13 berry-13 commented Jun 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #10052. LibreChat can expire chats a user marks temporary, and retentionMode: "all" can put a deadline on everything while leaving it visible, but an operator who needs every conversation to behave like a temporary chat has no way to say so: the toggle is the user's, and anything they leave off is stored permanently.

This adds retentionMode: "ephemeral". While it is active every newly saved chat is forced temporary: it is hidden from history and search, it carries the temporary-chat expiration, and the Temporary Chat toggle is locked on with an administrator-enforced label rather than disappearing. The four routes that write a message without going through the retention-aware conversation save (the text edit, the artifact edit, feedback, and the parallel-response branch) re-stamp the conversation holding that message, so a write inside a chat that predates the setting can never leave the message expiring while the chat around it stays permanent and visible.

Enabling the mode converts records as they are written; it is not a migration. Chats nobody touches again stay as they are, and the default temporary mode and the existing all mode are unchanged. Docs: LibreChat-AI/docs#611

How it works

The decisions live in packages/api and the CJS callers only wire them up. applyForcedRetention returns immediately unless the mode is ephemeral, re-stamps the message when the caller has not already saved it, and writes the conversation with noUpsert; neither write upserts, so a row deleted while the edit was in flight stays deleted instead of returning as a skeleton. resolveImportRetentionFields and resolveImportTagCounts decide what an imported, forked or duplicated record is stored with and whether its bookmark tags are counted. A fork or duplicate passes its source's classification, so under all a copy of a chat the user marked temporary stays temporary, as it did before this change.

packages/api/src/conversations/retention.ts   # when a bypassing write re-stamps, and what imports store
packages/data-schemas/src/methods/            # saveConvo and saveMessage stamp isTemporary + expiredAt
api/server/routes/messages.js                 # the four bypassing routes call the helper
api/server/utils/import/importBatchBuilder.js # passes its config and stores the resolved fields

saveConvo and saveMessage gained one branch each: a caller-supplied deadline is honored and the row is still marked temporary, otherwise the temporary-chat expiration is computed. saveMessage also gained the noUpsert option saveConvo already had.

Two places treated all-data retention as the literal "all" and so skipped the new mode: the resumable agent job's metadata, which now records a paused ephemeral turn as temporary with its original deadline so resume and abort restore it as such, and the client's shared history-cache insert, which now refuses a temporary conversation exactly as the SSE upsert path already did, so a forced-temporary fork or duplicate never appears in the sidebar. Every other literal comparison was inspected and is correct as all-only.

The Temporary Chat permission is overlaid where the control renders rather than written into stored role permissions, so enabling and later disabling the mode leaves an operator's configured value untouched.

Type of change

  • Feature

Testing

Tested environments/configuration:

  • Config: interface.retentionMode: "ephemeral" with temporaryChatRetention: 1, plus a control run with the setting absent
  • Browser: Chromium desktop light, desktop dark, and mobile emulation
  • Database: MongoDB, per-run database against the mock harness
  • Provider: in-process mock model

Automated tests:

  • Six end-to-end scenarios in e2e/specs/mock/scenarios/ephemeral-retention.spec.ts, each run on desktop light, desktop dark and mobile against a live server and MongoDB: a new chat is saved temporary and stays out of history; the toggle is locked on, stays keyboard reachable and ignores a click; editing a message converts the chat holding it; branching a response converts the chat holding it; a duplicated chat is temporary and adds no bookmark count; and, with the setting absent, a chat is still saved permanently and still appears in history.
  • packages/api/src/conversations/retention.spec.ts covers the three helpers: the ephemeral gate, the non-upserting writes, the optional message re-stamp, no write at all under temporary, all or an absent mode, and the import fields and tag counts including the fallback deadline.
  • packages/data-schemas/src/methods/message.spec.ts proves noUpsert against a real in-memory MongoDB: a deleted message is not recreated, an existing one is still re-stamped.
  • Route wiring for all four bypassing routes in api/server/routes/__tests__/messages-retention.spec.js and messages-update.spec.js; the stored-permission behavior in packages/api/src/app/permissions.spec.ts; the history-cache guard in client/src/utils/convos.spec.ts.
  • Full workspace suites run locally: api 259 suites / 5554 tests, client 231 suites / 4115 tests for the touched areas, plus packages/api, packages/data-schemas and packages/data-provider. ESLint, Prettier, import sorting and tsc --noEmit are clean for every changed file.

Screenshots / recordings

Stills are not attached. The only visible change is the Temporary Chat control in the header, and its enforced state is asserted by an automated scenario rather than shown: the-temporary-toggle-is-locked-on-under-ephemeral-retention runs on desktop light, desktop dark and mobile and checks that the control is pressed, carries the administrator-enforced label, stays reachable by keyboard, and still reads as pressed after a click. The button keeps its place, size and icon; what changes is the pressed state, the label, the not-allowed cursor, and that the keyboard shortcut no longer toggles it. Say the word if you would rather have a before-and-after pair and I will capture one.

Risk / compatibility

No migration and no schema change: the new mode is one more value of an existing enum, and records are converted as they are written. Deployments on temporary or all take no new write and no new read on any path. The conversation re-stamp adds at most one saveConvo per message edit, artifact edit or branch, and only while ephemeral is active. MongoDB TTL deletion remains asynchronous, and the PR does not promise graph-wide deadline capping or retroactive bookmark-count reconciliation.

Checklist

@berry-13
berry-13 marked this pull request as draft June 17, 2026 13:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f6757b041

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/utils/import/importBatchBuilder.js Outdated
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2de5b1f164

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/routes/convos.js
@berry-13
berry-13 marked this pull request as ready for review June 17, 2026 23:43

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5481e9a498

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/conversation.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

https://github.com/danny-avila/LibreChat/blob/aae969b970f20ecc95d6985a4f6f75b93531d1dc/api/server/routes/convos.js#L222
P2 Badge Pass retention config when pinning conversations

When interface.retentionMode: "ephemeral" is enabled and a user pins or unpins an older non-temporary conversation, this route still calls saveConvo with only userId, unlike the archive/update routes above. Since saveConvo only forces isTemporary/expiredAt when it receives interfaceConfig, the pin write preserves the conversation as permanent and visible, bypassing the forced-temporary policy. Add configMiddleware here and pass req.config.interfaceConfig into saveConvo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@berry-13
berry-13 changed the base branch from main to dev June 18, 2026 08:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b4b36de6f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/files/retention.ts
Comment thread packages/data-schemas/src/methods/message.ts Outdated
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: f63be383c8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@berry-13
berry-13 force-pushed the admin/retention-mode branch from f63be38 to 596c5b4 Compare June 20, 2026 23:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 596c5b4118

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/conversation.ts Outdated
Comment thread packages/data-schemas/src/methods/message.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b170f5ff3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 144ad1e5b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f91cbfeb66

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1cb50554df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3378917bdf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/routes/agents/index.js Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5dfae72636

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated
Comment thread packages/data-schemas/src/methods/message.ts Outdated
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18119a74ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/utils/retention.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e798bc5919

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/message.ts Outdated
Comment thread api/server/routes/messages.js Outdated
@berry-13
berry-13 force-pushed the admin/retention-mode branch from e798bc5 to 94642c8 Compare June 22, 2026 21:55

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 94642c8cd2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/conversation.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f1bfb90c4e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/components/Chat/TemporaryChat.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 920814a3d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-provider/src/config.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4aa8ae7ab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread api/server/services/Threads/manage.js Outdated
@berry-13
berry-13 force-pushed the admin/retention-mode branch from c4aa8ae to b960221 Compare June 23, 2026 14:42
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1950beceaa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!savedResponseMessage) {
throw new Error('Re-pause response progress could not be persisted');
}
await applyForcedRetention(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stamp forced retention before empty re-pauses return

Fresh evidence beyond the earlier resume fix is that this stamp is reached only after persistRePauseProgress returns early when the resumed segment has no content or attachments. If a pre-policy permanent job is resumed after ephemeral is enabled and immediately pauses again without emitting output, only the job metadata becomes temporary; the conversation remains permanently visible and, if the new approval expires or is abandoned, no later finalization converts it. Stamp the parent before the empty-progress return, adding the message ID only when a message was actually saved.

AGENTS.md reference: AGENTS.md:L42-L44

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 2bd0faf: the resume controller now stamps the parent through applyForcedRetention right after persisting the forced job metadata and before client initialization, so a pre-policy chat converts even when the resumed segment re-pauses with no output or is later abandoned; the saved response is still stamped after its save. resume.spec.js adds the empty re-pause case (fails without the fix) and asserts stamp ordering; full spec 153/153.

Comment thread packages/data-schemas/src/methods/conversation.ts
Adds RetentionMode.EPHEMERAL, which forces every newly saved chat
temporary: hidden from history and search, given the temporary-chat
expiration, and with the toggle locked on.

Forces isTemporary and applies the temporary expiration in the normal
conversation and message save methods, routes Assistants/Threads
messages through the normal message save, applies the all-data
retention policy to file uploads and shared links, and stamps imports,
forks, and duplicates. Locks the frontend toggle and keyboard shortcut
behind an administrator-enforced badge.

The default temporary mode and the existing all mode are unchanged.
Input and output messages were saved with the raw request, so under
ephemeral retention they missed the forced-temporary classification the
conversation received. Route both through getConversationWriteContext
and announce the stored reply as saved.
A resumed response was saved with a fresh forced-temporary window while
the re-stamp kept the conversation's earlier deadline, so a chat that
paused again could leave its response stored after the conversation
expired. Stamp the saved response with the parent's deadline.
stampForcedRetention released a converted chat's bookmark counts but
kept its tags, so deleting that chat before TTL removal decremented the
same tags again and reduced counts owned by other visible chats. Clear
the tags in the conditional conversion update that releases them.
An ephemeral import, fork or duplicate skipped its tag count increment
but kept the source tags, so deleting the copy before TTL removal
decremented counts owned by other visible chats. Store the same tags the
import counts, which is none for a forced-temporary copy.
@berry-13
berry-13 force-pushed the admin/retention-mode branch from 2bd0faf to e9f9321 Compare September 30, 2026 14:14
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review the current PR head 6604d70. State the exact reviewed commit and ignore findings that apply only to earlier heads.

Purpose supplied by the requester: Canary rebase with conflict resolution in resume.js and chatV1/chatV2, plus 3 fixes since reviewed head 1950bec: forced-retention resume submission state, startup-config gate on resume, concurrent stamp deadline reuse

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 6604d70fad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@berry-13
berry-13 merged commit 02a70e9 into canary Sep 30, 2026
54 of 56 checks passed
@berry-13
berry-13 deleted the admin/retention-mode branch September 30, 2026 16:57
jeannotdamoiseaux pushed a commit to jeannotdamoiseaux/LibreChat that referenced this pull request Oct 1, 2026
…eChat-AI#13811)

* feat: add ephemeral retention mode for forced temporary chats

Adds RetentionMode.EPHEMERAL, which forces every newly saved chat
temporary: hidden from history and search, given the temporary-chat
expiration, and with the toggle locked on.

Forces isTemporary and applies the temporary expiration in the normal
conversation and message save methods, routes Assistants/Threads
messages through the normal message save, applies the all-data
retention policy to file uploads and shared links, and stamps imports,
forks, and duplicates. Locks the frontend toggle and keyboard shortcut
behind an administrator-enforced badge.

The default temporary mode and the existing all mode are unchanged.

* fix: enforce ephemeral retention when resuming paused chats

* fix: preserve forced retention across pauses and assistant turns

* test: Use Real Module IDs for Installed Package Mocks

* test: Wait for Resumed Retention Persistence

* test: Control Mongo Index Setup in OpenID Fixture

* test: Close Mobile Drawer Before Retention Resume Scenario

* fix: Store Responses API Messages Under the Retention Write Context

Input and output messages were saved with the raw request, so under
ephemeral retention they missed the forced-temporary classification the
conversation received. Route both through getConversationWriteContext
and announce the stored reply as saved.

* fix: Align Resumed Responses With the Parent Retention Deadline

A resumed response was saved with a fresh forced-temporary window while
the re-stamp kept the conversation's earlier deadline, so a chat that
paused again could leave its response stored after the conversation
expired. Stamp the saved response with the parent's deadline.

* fix: Clear Released Bookmark Tags When Forcing a Chat Temporary

stampForcedRetention released a converted chat's bookmark counts but
kept its tags, so deleting that chat before TTL removal decremented the
same tags again and reduced counts owned by other visible chats. Clear
the tags in the conditional conversion update that releases them.

* fix: Store No Bookmark Tags on Forced-Temporary Imports

An ephemeral import, fork or duplicate skipped its tag count increment
but kept the source tags, so deleting the copy before TTL removal
decremented counts owned by other visible chats. Store the same tags the
import counts, which is none for a forced-temporary copy.

* test: Provide the Forced-Temporary Retention Helper to the Header Stacking Mock

* test: Reuse One Admin Login per Worker in Ephemeral Retention Scenarios

* fix: Keep Legacy Temporary Chats Temporary When Forking Under All-Data Retention

* fix: Convert a Resumed Chat Under Ephemeral Retention Before It Can Re-Pause Empty

* fix: Treat a Reloaded Pre-Policy Run as Temporary Once Retention Is Forced

* fix: Stamp Messages with the Deadline a Concurrent Retention Stamp Stored

* fix: Wait for the Startup Config Before Rebuilding a Resumed Submission

* test: Wait for the Resumed Response Row in the Ephemeral Resume Scenario

* test: Provide the Real Command Executor Stamp to the Callbacks Mock

(cherry picked from commit 02a70e9)

Original-PR: LibreChat-AI#13811
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhancement]: Temporary Chat always on

3 participants