feat: real-time Federation panel updates via WS events

Added federation_peers_changed (no-payload signal) broadcast from every
peer state mutation, and federation_approval_request_received when a new
approval request is queued. Client subscribes via onFederationPeersChanged
callback registry. FederationPanel and PendingApprovals debounce-refetch
on any event. sendToAdmins helper broadcasts only to admin users.
This commit is contained in:
Jannis Braun
2026-04-20 18:28:10 +02:00
parent 6afad97bd1
commit 3d8709d20a
7 changed files with 95 additions and 0 deletions
@@ -145,6 +145,8 @@ async function performHandshake(
.set({ status: 'awaiting_approval' })
.where(eq(schema.federationPeers.id, peerId))
.run();
const { connectionManager } = await import('../ws/handler.js');
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
return { status: 'pending', error: 'Awaiting admin approval on remote instance' };
}
@@ -154,6 +156,8 @@ async function performHandshake(
.set({ status: 'active', lastSeenAt: Date.now() })
.where(eq(schema.federationPeers.id, peerId))
.run();
const { connectionManager } = await import('../ws/handler.js');
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
return { status: 'active', peerId };
}
@@ -174,6 +178,8 @@ async function performHandshake(
.set({ status: 'rejected' })
.where(eq(schema.federationPeers.id, peerId))
.run();
const { connectionManager } = await import('../ws/handler.js');
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
return { status: 'rejected', error: errorMessage };
}
@@ -283,6 +283,7 @@ async function processOutboxTick(): Promise<void> {
})
.where(eq(schema.federationPeers.id, peerId))
.run();
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
} else {
console.warn(
`[federation-worker] Peer ${peerOrigin} returned HTTP ${response.status}`,
@@ -388,6 +389,8 @@ async function resolvePendingPeers(): Promise<void> {
switch (result.status) {
case 'active':
console.log(`[federation-worker] Auto-peered with ${peerOrigin} — entries will deliver next tick`);
// Notify admins of peer state change
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
break;
case 'rejected': {
@@ -417,6 +420,8 @@ async function resolvePendingPeers(): Promise<void> {
// Push federation_peer_rejected WS event to affected users
pushPeerRejectedEvent(peerOrigin, contextMap);
// Notify admins of peer state change
connectionManager.sendToAdmins({ type: 'federation_peers_changed' as const });
break;
}