Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 5045c30366c334b867cb852425f5cc48dcb1323b)
+++ src/services/ActivityPubService.js	(revision 78b6d8a72b391c1960a8488dc735fb03495bc209)
@@ -1073,7 +1073,10 @@
 }
 // Mark a timeline post as boosted so it shows in the Cirkel (mixed by date).
-let _markBoost, _boostedCount;
+let _markBoost, _unmarkBoost, _boostedCount;
 export function markBoosted(slug, noteId) {
   try { if (!_markBoost) _markBoost = db.prepare('UPDATE ap_timeline SET boosted = 1 WHERE slug = ? AND id = ?'); _markBoost.run(slug, noteId); } catch { /* ignore */ }
+}
+export function unmarkBoosted(slug, noteId) {
+  try { if (!_unmarkBoost) _unmarkBoost = db.prepare('UPDATE ap_timeline SET boosted = 0 WHERE slug = ? AND id = ?'); _unmarkBoost.run(slug, noteId); } catch { /* ignore */ }
 }
 export function boostedCount(slug) {
@@ -1226,20 +1229,32 @@
   const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, '');
   if (!base || !site || !site.slug || !targetNoteId) return { error: 'config' };
-  const type = kind === 'boost' ? 'Announce' : 'Like';
   const me = actorId(base, site.slug);
   const keys = getOrCreateKeys(site.slug);
-  const act = {
-    '@context': 'https://www.w3.org/ns/activitystreams',
-    id: `${me}#${type.toLowerCase()}-${Date.now()}-${rid()}`,
-    type, actor: me, object: targetNoteId,
-  };
-  if (type === 'Announce') { act.to = [PUBLIC]; act.cc = [`${me}/followers`]; }
+  // 'unboost' = Undo(Announce): retracts a boost so followers' servers remove the
+  // reblog (matched on actor+object — no record of the original Announce needed).
+  const fanout = (kind === 'boost' || kind === 'unboost'); // also goes to our followers
+  let act;
+  if (kind === 'unboost') {
+    act = {
+      '@context': 'https://www.w3.org/ns/activitystreams',
+      id: `${me}#undo-${Date.now()}-${rid()}`, type: 'Undo', actor: me,
+      to: [PUBLIC], cc: [`${me}/followers`],
+      object: { id: `${me}#announce-${Date.now()}-${rid()}`, type: 'Announce', actor: me, object: targetNoteId },
+    };
+  } else {
+    const type = kind === 'boost' ? 'Announce' : 'Like';
+    act = {
+      '@context': 'https://www.w3.org/ns/activitystreams',
+      id: `${me}#${type.toLowerCase()}-${Date.now()}-${rid()}`,
+      type, actor: me, object: targetNoteId,
+    };
+    if (type === 'Announce') { act.to = [PUBLIC]; act.cc = [`${me}/followers`]; }
+  }
   const inboxes = new Set();
   if (authorUri) { const a = await fetchActor(authorUri).catch(() => null); if (a) inboxes.add((a.endpoints && a.endpoints.sharedInbox) || a.inbox); }
-  // A boost is public → also deliver to our own followers so it shows for them.
-  if (type === 'Announce') { for (const f of fStmts().list.all(site.slug)) inboxes.add(f.shared_inbox || f.inbox); }
+  if (fanout) { for (const f of fStmts().list.all(site.slug)) inboxes.add(f.shared_inbox || f.inbox); }
   let delivered = 0;
   for (const inbox of [...inboxes].filter(Boolean)) { try { const st = await deliver(inbox, act, `${me}#main-key`, keys.private_pem); if (st >= 200 && st < 300) delivered++; } catch { /* best-effort */ } }
-  console.log('[AP]', type, site.slug, '→', targetNoteId, 'delivered', delivered);
+  console.log('[AP]', kind, site.slug, '→', targetNoteId, 'delivered', delivered);
   return { ok: true, delivered };
 }
@@ -1356,5 +1371,5 @@
   listOutbox, deliverOutboxDelete,
   webfingerResolve, followActor, resolveRemoteActor, unfollowActor, listFollowing, setAutoBoost, getTimeline, sendInteraction,
-  autoBoostCount, boostedCount, markBoosted, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, boostLatestN,
+  autoBoostCount, boostedCount, markBoosted, unmarkBoosted, getCirkelPosts, getCirkelMembers, autoMigrateCircles, selfHealTimeline, boostLatestN,
   getNotifications, listBlocks, isBlockedAny, blockTarget, unblock,
   deliverWithRetry, enqueueDelivery, processDeliveryQueue, startDeliveryWorker,
