fix: multiple federation peering bugs

1. queueOutboxEvent no longer creates pending peer placeholders when
   autoAcceptPeering is disabled — prevents bypassing the admin's
   peering control

2. Approval endpoint checks for 202 before response.ok — when the
   remote also has autoAcceptPeering off, sets peer to awaiting_approval
   instead of incorrectly activating it

3. awaiting_approval status added to Federation panel UI — status label,
   colors, filter options so these peers are visible and manageable
This commit is contained in:
Jannis Braun
2026-04-20 17:54:00 +02:00
parent b40c57f227
commit 072858cbbb
3 changed files with 36 additions and 4 deletions
+18
View File
@@ -996,6 +996,24 @@ export async function federationRoutes(app: FastifyInstance): Promise<void> {
signal: AbortSignal.timeout(10_000),
});
if (response.status === 202) {
// Remote instance also has autoAcceptPeering off — they queued our request.
// Don't activate our peer. Set to awaiting_approval until their admin also approves.
db.update(schema.federationPeers)
.set({ status: 'awaiting_approval' })
.where(eq(schema.federationPeers.id, peerId))
.run();
// Delete the approval request since we already acted on it
db.delete(schema.peerApprovalRequests)
.where(eq(schema.peerApprovalRequests.id, id))
.run();
return reply.code(200).send({
success: true,
awaitingRemoteApproval: true,
message: 'Remote instance also requires admin approval. Your request has been queued on their side.',
});
}
if (!response.ok) {
let errorMessage = `Remote instance rejected handshake (HTTP ${response.status})`;
try {
@@ -152,12 +152,23 @@ export function queueOutboxEvent(
: peers;
// For targeted origins with no existing peer record, create pending placeholders
// (only when autoAcceptPeering is enabled — otherwise the admin controls all peering)
if (targetPeerOrigins) {
const autoAcceptSettings = db
.select({ autoAcceptPeering: schema.instanceSettings.autoAcceptPeering })
.from(schema.instanceSettings)
.where(eq(schema.instanceSettings.id, 1))
.get();
const autoAcceptPeering = (autoAcceptSettings?.autoAcceptPeering ?? 1) === 1;
const matchedOrigins = new Set(matchedPeers.map(p => p.origin));
for (const origin of targetPeerOrigins) {
if (matchedOrigins.has(origin)) continue;
// Don't auto-create placeholders when autoAcceptPeering is off
if (!autoAcceptPeering) continue;
// Check if there's a rejected/revoked peer we should skip
const existingPeer = db
.select({ status: schema.federationPeers.status })