fix: load app config on remaining retention-relevant routes

The messages routes (branch, artifact, post), share-link create/patch, and
the agent chat-abort route read req.config.interfaceConfig but never ran
configMiddleware, so req.config was undefined and retention was skipped.
Under ephemeral (and all) this let branched/edited/aborted messages and
shared links persist without isTemporary/expiredAt, outliving the chat.

Apply configMiddleware to those routes so retention is enforced
consistently. Add a getSharedLinkExpiration ephemeral test and keep route
test middleware mocks in sync.
This commit is contained in:
Marco Beretta 2026-06-17 16:04:37 +02:00
parent 536c7f1d20
commit adb17c83f8
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
4 changed files with 22 additions and 5 deletions

View file

@ -49,6 +49,7 @@ jest.mock('~/server/middleware/requireJwtAuth', () => (req, res, next) => next()
jest.mock('~/server/middleware', () => ({
requireJwtAuth: (req, res, next) => next(),
validateMessageReq: (req, res, next) => next(),
configMiddleware: (req, res, next) => next(),
}));
jest.mock('~/db/models', () => ({

View file

@ -220,7 +220,7 @@ router.get('/chat/status/:conversationId', async (req, res) => {
* @access Private
* @description Mounted before chatRouter to bypass buildEndpointOption middleware
*/
router.post('/chat/abort', async (req, res) => {
router.post('/chat/abort', configMiddleware, async (req, res) => {
logger.debug(`[AgentStream] ========== ABORT ENDPOINT HIT ==========`);
logger.debug(`[AgentStream] Method: ${req.method}, Path: ${req.path}`);
logger.debug(`[AgentStream] Body:`, req.body);

View file

@ -9,7 +9,7 @@ const {
traceIdForMessage,
} = require('@librechat/api');
const { findAllArtifacts, replaceArtifactContent } = require('~/server/services/Artifacts/update');
const { requireJwtAuth, validateMessageReq } = require('~/server/middleware');
const { requireJwtAuth, validateMessageReq, configMiddleware } = require('~/server/middleware');
const db = require('~/models');
const router = express.Router();
@ -108,7 +108,7 @@ router.get('/', async (req, res) => {
* @param {string} req.body.agentId - The agentId to filter content by
* @returns {TMessage} The newly created branch message
*/
router.post('/branch', async (req, res) => {
router.post('/branch', configMiddleware, async (req, res) => {
try {
const { messageId, agentId } = req.body;
const userId = req.user.id;
@ -189,7 +189,7 @@ router.post('/branch', async (req, res) => {
}
});
router.post('/artifact/:messageId', async (req, res) => {
router.post('/artifact/:messageId', configMiddleware, async (req, res) => {
try {
const { messageId } = req.params;
const { index, original, updated } = req.body;
@ -282,7 +282,7 @@ router.get('/:conversationId', validateMessageReq, async (req, res) => {
}
});
router.post('/:conversationId', validateMessageReq, async (req, res) => {
router.post('/:conversationId', validateMessageReq, configMiddleware, async (req, res) => {
try {
const message = { ...req.body, conversationId: req.params.conversationId };
const reqCtx = {