fix: enforce tag retention before the rename commits

PUT /api/tags/:tag renamed the tag first and ran the forced-retention cascade
with the new tag afterwards. A cascade failure returned 500 with the rename
already committed, and a retried PUT /:oldTag hit the 404 path because the old
tag no longer exists, so the tagged conversations' messages, shares, and files
could never be backfilled.

Run the cascade with the old tag before the rename, mirroring the DELETE route:
the old tag selects the same conversations the renamed tag will carry,
enforcing on a nonexistent tag is a no-op, and a failed rename now retries
cleanly with retention already applied.
This commit is contained in:
Marco Beretta 2026-07-05 03:11:46 +02:00
parent cc4533d554
commit 80ae204cbe
No known key found for this signature in database
GPG key ID: D918033D8E74CC11

View file

@ -96,10 +96,16 @@ router.post('/', configMiddleware, async (req, res) => {
router.put('/:tag', configMiddleware, async (req, res) => {
try {
const decodedTag = decodeURIComponent(req.params.tag);
/**
* Enforce retention with the old tag before the rename commits. The rename rewrites the
* conversations' tag entries, so a cascade failure afterwards would 500 while a retried
* PUT /:oldTag hits the 404 path (the old tag no longer exists) and the affected chats
* never convert. The old tag selects the same conversations the renamed tag will carry,
* and enforcing on a nonexistent tag is a no-op, so a failed rename retries cleanly.
*/
await enforceForcedRetentionForTag(req, decodedTag, 'PUT /api/tags/:tag');
const tag = await updateConversationTag(req.user.id, decodedTag, req.body);
if (tag) {
const renamedTag = typeof req.body?.tag === 'string' ? req.body.tag : decodedTag;
await enforceForcedRetentionForTag(req, renamedTag, 'PUT /api/tags/:tag');
res.status(200).json(tag);
} else {
res.status(404).json({ error: 'Tag not found' });