From 71445c5f27fbda8dabb25b6c784b43964940f341 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:45:02 +0200 Subject: [PATCH] feat(server): wire onPeerDeactivated at admin revoke/reset sites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Admin-revoke endpoint (DELETE /api/federation/peers/:id): fires onPeerDeactivated(id, 'admin_revoked') after the status write to 'revoked', evicting any in-flight federated calls for the now-revoked peer. Admin-reset endpoint (POST /api/federation/peers/:id/reset): hook SKIPPED. The reset endpoint is guarded to only run when status is already 'needs_attention' (active peers are rejected at the boundary with a 400). Because the peer was already deactivated before reset is called, onPeerDeactivated was already fired at the active→needs_attention transition. The reset deletes the row entirely rather than writing a new status; it does not represent a transition OUT OF active, so wiring it here would be a semantic error — double-evicting an already-deactivated peer. --- packages/server/src/routes/federation.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/src/routes/federation.ts b/packages/server/src/routes/federation.ts index a321e38a..6ded4e4f 100644 --- a/packages/server/src/routes/federation.ts +++ b/packages/server/src/routes/federation.ts @@ -18,7 +18,7 @@ import { sanitizeUser } from '../utils/sanitize.js'; import { deleteAttachmentFiles, deleteUploadFile } from '../utils/fileCleanup.js'; import { tombstoneUser, collectDeletionBroadcastTargets, collectProfileBroadcastTargetIds } from '../utils/userDeletion.js'; import { computeFederatedId, getDmParticipants, sendCallRelay } from '../utils/federationOutbox.js'; -import { onPeerActivated } from '../utils/federationPeerActivation.js'; +import { onPeerActivated, onPeerDeactivated } from '../utils/federationPeerActivation.js'; import { getDmMessageWithUser } from './dm.js'; import type { FederationRelayRequest, FederationRelayResponse, FederationRelayEvent, FederationRelayAttachment, FederationSyncRequest, FederationSyncResponse, DmMessageWithUser, DmChannel, FederationRelayProfileSnapshot, FederationIdentityDeleteS2SRequest, FederationProfileUpdatePayload, ServerEvent } from '@backspace/shared'; @@ -883,6 +883,10 @@ export async function federationRoutes(app: FastifyInstance): Promise { .where(eq(schema.federationPeers.id, id)) .run(); + onPeerDeactivated(id, 'admin_revoked').catch(err => + console.error('[federation] onPeerDeactivated from admin revoke failed:', err), + ); + // Delete all outbox entries for this peer db.delete(schema.federationOutbox) .where(eq(schema.federationOutbox.peerId, id))