feat(federation): add client peering integration, transparency indicator, and admin federation settings

Task 13: Hook server-to-server peering into connectToRemote (non-fatal)
and add federation API namespace to the client (initiate, peers, revoke).

Task 14: Show a transparency notice in the DM welcome header when the
other user is on a remote instance, informing that messages are stored
on both home instances and are not end-to-end encrypted.

Task 15: Add Federation section to the instance settings General panel
with DM relay toggle, TTL config, and a live peer list with revoke
buttons. Also extends InstanceAdminSettings type and the server settings
route to support federationRelayEnabled / federationRelayTtlDays.
This commit is contained in:
Jannis Braun
2026-03-25 21:47:10 +01:00
parent 3898e4940a
commit 44de9b6f41
6 changed files with 215 additions and 2 deletions
+19
View File
@@ -198,6 +198,12 @@ export class BackspaceApiClient {
enabled: () => Promise<{ enabled: boolean }>;
};
readonly federation: {
initiatePeering: (data: { remoteOrigin: string }) => Promise<{ peer: { id: string; origin: string; instanceName: string | null; status: string; lastSeenAt: number | null; createdAt: number } }>;
peers: () => Promise<{ peers: Array<{ id: string; origin: string; instanceName: string | null; status: string; lastSeenAt: number | null; lastFailureAt: number | null; consecutiveFailures: number | null; lastSyncedAt: number | null; createdAt: number }> }>;
revokePeer: (id: string) => Promise<{ success: boolean }>;
};
readonly admin: {
storageStats: () => Promise<StorageStats>;
storageOrphans: () => Promise<{ orphans: OrphanedFile[] }>;
@@ -615,6 +621,19 @@ export class BackspaceApiClient {
enabled: () => request<{ enabled: boolean }>('GET', '/gif/enabled'),
};
this.federation = {
initiatePeering: (data: { remoteOrigin: string }) =>
request<{ peer: { id: string; origin: string; instanceName: string | null; status: string; lastSeenAt: number | null; createdAt: number } }>(
'POST', '/federation/peer/initiate', data
),
peers: () =>
request<{ peers: Array<{ id: string; origin: string; instanceName: string | null; status: string; lastSeenAt: number | null; lastFailureAt: number | null; consecutiveFailures: number | null; lastSyncedAt: number | null; createdAt: number }> }>(
'GET', '/federation/peers'
),
revokePeer: (id: string) =>
request<{ success: boolean }>('DELETE', `/federation/peers/${id}`),
};
this.admin = {
storageStats: () => request<StorageStats>('GET', '/admin/storage/stats'),
storageOrphans: () => request<{ orphans: OrphanedFile[] }>('GET', '/admin/storage/orphans'),