fix: return the converted conversation after forced project retention

assignConversationToProject captured the findOneAndUpdate result before running
the forced-retention conversion, so under ephemeral mode the returned object was
a stale pre-conversion snapshot. The client writes that object straight into the
active conversation and the React Query cache, so an assigned/removed permanent
chat was cached as non-temporary with no expiredAt until a later refetch.

Run the retention conversion before capturing the updated document so the
findOneAndUpdate result carries the isTemporary/expiredAt fields alongside the
chatProjectId change. A no-op outside forced retention.
This commit is contained in:
Marco Beretta 2026-07-04 16:07:33 +02:00
parent cbd0ca2f0f
commit fb095b9241
No known key found for this signature in database
GPG key ID: D918033D8E74CC11
2 changed files with 15 additions and 3 deletions

View file

@ -313,13 +313,17 @@ describe('ChatProject methods', () => {
]);
await SharedLink.create({ conversationId: 'convo-1', user, shareId: uuidv4() });
await methods.assignConversationToProject(
const result = await methods.assignConversationToProject(
user,
'convo-1',
project._id!.toString(),
ephemeralConfig,
);
expect(result?.conversation.isTemporary).toBe(true);
expect(result?.conversation.expiredAt).toBeInstanceOf(Date);
expect(result?.conversation.chatProjectId).toBe(project._id!.toString());
const conversation = await Conversation.findOne({
user,
conversationId: 'convo-1',

View file

@ -486,6 +486,16 @@ export function createChatProjectMethods(mongoose: typeof import('mongoose')): C
}
const previousProjectId = conversation.chatProjectId ?? null;
/**
* Convert the touched conversation to the forced (ephemeral) window before capturing the
* updated document. The caller returns this object straight to the client, which writes it
* into the active conversation and the React Query cache, so it must already carry the
* isTemporary/expiredAt fields rather than a stale pre-conversion snapshot. A no-op outside
* forced retention.
*/
await forceConversationRetention(user, conversationId, interfaceConfig);
const update =
normalizedProjectId == null
? { $unset: { chatProjectId: '' } }
@ -500,8 +510,6 @@ export function createChatProjectMethods(mongoose: typeof import('mongoose')): C
return null;
}
await forceConversationRetention(user, conversationId, interfaceConfig);
const projectIds = new Set(
[previousProjectId, normalizedProjectId].filter((id): id is string => Boolean(id)),
);