From b71b4a9dbd057a5e482184fd32721969b5f3441d Mon Sep 17 00:00:00 2001 From: Ricardo Date: Thu, 2 Apr 2026 23:55:04 +0200 Subject: [PATCH] fix: exempt own posts from timeline retention cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cleanup was deleting own posts when remote posts pushed the total past the retention limit. Own posts are your content — they should never be deleted by retention. Now filters to only count and delete remote posts (author.url != profile.url). --- lib/timeline-cleanup.js | 31 ++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/timeline-cleanup.js b/lib/timeline-cleanup.js index 30335ff..cc88e7a 100644 --- a/lib/timeline-cleanup.js +++ b/lib/timeline-cleanup.js @@ -19,19 +19,32 @@ export async function cleanupTimeline(collections, retentionLimit) { return { removed: 0, interactionsRemoved: 0 }; } - const totalCount = await collections.ap_timeline.countDocuments(); - if (totalCount <= retentionLimit) { + // Get the local profile URL to exempt own posts from cleanup. + // Own posts are your content — they should never be deleted by retention. + const profile = collections.ap_profile + ? await collections.ap_profile.findOne({}) + : null; + const ownerUrl = profile?.url || null; + + // Only count remote posts toward retention limit + const remoteFilter = ownerUrl + ? { "author.url": { $ne: ownerUrl } } + : {}; + const remoteCount = await collections.ap_timeline.countDocuments(remoteFilter); + if (remoteCount <= retentionLimit) { return { removed: 0, interactionsRemoved: 0 }; } - // Use aggregation to get exact UIDs beyond the retention limit. - // This avoids race conditions: we delete by UID, not by date. + // Find remote items beyond the retention limit, sorted newest-first. + // Own posts are excluded from the aggregation pipeline entirely. + const pipeline = [ + ...(ownerUrl ? [{ $match: { "author.url": { $ne: ownerUrl } } }] : []), + { $sort: { published: -1 } }, + { $skip: retentionLimit }, + { $project: { uid: 1 } }, + ]; const toDelete = await collections.ap_timeline - .aggregate([ - { $sort: { published: -1 } }, - { $skip: retentionLimit }, - { $project: { uid: 1 } }, - ]) + .aggregate(pipeline) .toArray(); if (!toDelete.length) { diff --git a/package.json b/package.json index 5d7e57c..c19df88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rmdes/indiekit-endpoint-activitypub", - "version": "3.13.3", + "version": "3.13.4", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "keywords": [ "indiekit",