fix: prevent resolveOrCreateReplicatedUser from recreating deleted user stubs

When a federated user's identity has been tombstoned (isDeleted=1),
findFederatedUser filters them out, causing resolveOrCreateReplicatedUser
to silently create a new stub — a "zombie" resurrection. This guard checks
for a deleted row before creating a stub and returns null instead.

All 11 call sites across federation.ts and dm.ts have been updated with
appropriate null guards: federation relay handlers reject or skip the event
(participant_not_found / accepted no-op), while dm.ts routes convert null
to undefined so the existing 404 path handles it.
This commit is contained in:
Jannis Braun
2026-04-03 02:32:36 +02:00
parent bb4b031423
commit 4da373c970
2 changed files with 64 additions and 14 deletions
+3 -3
View File
@@ -384,7 +384,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
if (homeUserId && homeInstance) {
// Federated identity: resolve or create a replicated user stub
targetUser = resolveOrCreateReplicatedUser(homeUserId, homeInstance, db);
targetUser = resolveOrCreateReplicatedUser(homeUserId, homeInstance, db) ?? undefined;
} else if (userId && typeof userId === 'string') {
// Local ID: direct lookup (existing behavior)
targetUser = db.select().from(schema.users).where(eq(schema.users.id, userId)).get();
@@ -570,7 +570,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
if (identity.homeUserId && identity.homeInstance) {
// Federated user — resolve via homeUserId, creating a replicated stub if needed
localUser = resolveOrCreateReplicatedUser(identity.homeUserId, identity.homeInstance, db);
localUser = resolveOrCreateReplicatedUser(identity.homeUserId, identity.homeInstance, db) ?? undefined;
} else {
// Local user — direct ID lookup
localUser = db.select().from(schema.users).where(
@@ -865,7 +865,7 @@ export async function dmRoutes(app: FastifyInstance): Promise<void> {
if (homeUserId && homeInstance) {
// Federated identity: resolve or create a replicated user stub
targetUser = resolveOrCreateReplicatedUser(homeUserId, homeInstance, db);
targetUser = resolveOrCreateReplicatedUser(homeUserId, homeInstance, db) ?? undefined;
} else if (targetUserIdRaw && typeof targetUserIdRaw === 'string') {
// Local ID: direct lookup (existing behavior)
targetUser = db.select().from(schema.users).where(eq(schema.users.id, targetUserIdRaw)).get();