diff --git a/packages/data-schemas/src/methods/message.spec.ts b/packages/data-schemas/src/methods/message.spec.ts index bc642693f7..f54d625ac6 100644 --- a/packages/data-schemas/src/methods/message.spec.ts +++ b/packages/data-schemas/src/methods/message.spec.ts @@ -1128,6 +1128,42 @@ describe('Message Operations', () => { } }); + it('preserves an edited message expiring sooner than its parent under forced retention', async () => { + const conversationId = uuidv4(); + const editedMessageId = uuidv4(); + const messageDeadline = new Date(Date.now() + 60 * 60 * 1000); + const parentDeadline = new Date(Date.now() + 12 * 60 * 60 * 1000); + await Conversation().create({ + conversationId, + user: 'user123', + endpoint: 'openAI', + title: 'Carried-over chat', + isTemporary: false, + expiredAt: parentDeadline, + }); + await Message.create({ + messageId: editedMessageId, + conversationId, + user: 'user123', + text: 'edited', + isTemporary: false, + expiredAt: messageDeadline, + }); + + await applyForcedRetention( + { + userId: 'user123', + interfaceConfig: { temporaryChatRetention: 24, retentionMode: RetentionMode.EPHEMERAL }, + }, + { conversationId, messageId: editedMessageId }, + { context: 'edit', capExpiryToConversation: true }, + ); + + const message = await Message.findOne({ messageId: editedMessageId, user: 'user123' }).lean(); + expect(message?.isTemporary).toBe(true); + expect(message?.expiredAt?.getTime()).toBe(messageDeadline.getTime()); + }); + it('converts a permanent conversation and its messages without a messageId (tag write)', async () => { const conversationId = uuidv4(); await Conversation().create({ diff --git a/packages/data-schemas/src/methods/message.ts b/packages/data-schemas/src/methods/message.ts index 176d3ab503..c666b818cc 100644 --- a/packages/data-schemas/src/methods/message.ts +++ b/packages/data-schemas/src/methods/message.ts @@ -422,10 +422,14 @@ export function createMessageMethods(mongoose: typeof import('mongoose')): Messa } if (typeof messageId === 'string' && messageId.length > 0) { - await Message.updateOne( - { messageId, user: userId }, - { $set: { isTemporary: true, expiredAt: forcedExpiredAt } }, - ); + await Message.updateOne({ messageId, user: userId }, [ + { + $set: { + isTemporary: true, + expiredAt: { $min: [{ $ifNull: ['$expiredAt', forcedExpiredAt] }, forcedExpiredAt] }, + }, + }, + ]); } await cascadeForcedConversationRetention( Conversation,