feat: lift DM gates for federated users

Remove requireLocalUser from DM routes, include DMs in federated
ready payload, replace blanket dm_* WS gate with call-only blocklist.
DM calls remain gated (separate scope).
This commit is contained in:
Jannis Braun
2026-04-07 19:48:07 +02:00
parent 9b8330fcdb
commit 662143bf08
3 changed files with 14 additions and 10 deletions
+4 -5
View File
@@ -145,11 +145,12 @@ export function handleClientEvent(
): void {
const type = event.type as string;
// Federation gating: federated users must use their home instance for DM operations
if (isFederated && type.startsWith('dm_')) {
// Federation gating: DM calls remain blocked for federated users (separate scope)
const DM_CALL_EVENTS = ['dm_call_start', 'dm_call_accept', 'dm_call_reject', 'dm_call_end'];
if (isFederated && DM_CALL_EVENTS.includes(type)) {
connectionManager.sendToUser(userId, {
type: 'error',
message: 'Federated users must use their home instance for DM operations',
message: 'Federated users cannot use DM calls on remote instances',
});
return;
}
@@ -1278,7 +1279,6 @@ function handleChannelAck(event: Record<string, unknown>, userId: string, isFede
if (spaceId) {
if (!isMember(spaceId, userId)) return;
} else {
if (isFederated) return;
if (!isDmMember(channelId, userId)) return;
}
@@ -1333,7 +1333,6 @@ function handleMarkUnread(event: Record<string, unknown>, userId: string, isFede
if (spaceId) {
if (!isMember(spaceId, userId)) return;
} else {
if (isFederated) return;
if (!isDmMember(channelId, userId)) return;
}
+8 -2
View File
@@ -1108,8 +1108,8 @@ function buildReadyPayload(userId: string): {
// Store user's space IDs for broadcasting
connectionManager.setUserSpaces(userId, spaceIds);
// Get DM channels — skip entirely for federated users (they get DMs from their home instance)
const dmMemberships = isFederated ? [] : db.select()
// Get DM channels
const dmMemberships = db.select()
.from(schema.dmMembers)
.where(and(
eq(schema.dmMembers.userId, userId),
@@ -1198,6 +1198,7 @@ function buildReadyPayload(userId: string): {
dmChannels.push({
id: dmChannel.id,
federatedId: dmChannel.federatedId ?? null,
ownerId: dmChannel.ownerId ?? null,
createdAt: dmChannel.createdAt,
members,
@@ -1214,6 +1215,11 @@ function buildReadyPayload(userId: string): {
}
// Include DM channel IDs in the visible set for read state filtering
for (const dm of dmChannels) {
visibleChannelIdSet.add(dm.id);
}
// Get Space Folders
const folderRows = db.select()
.from(schema.spaceFolders)