From a380927e72d9824aecebc5ca8c6cd6f6dc1aa392 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:00:19 +0200 Subject: [PATCH] test(dm): assert JOIN users guard drops orphan author in DM membership backfill (S5 review) --- .../src/db/backfillDmMembership.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/server/src/db/backfillDmMembership.test.ts b/packages/server/src/db/backfillDmMembership.test.ts index b269ca04..44c37390 100644 --- a/packages/server/src/db/backfillDmMembership.test.ts +++ b/packages/server/src/db/backfillDmMembership.test.ts @@ -44,4 +44,23 @@ describe('backfillOneOnOneDmMembership', () => { expect(memberCount('healthy')).toBe(2); expect(memberCount('unrecoverable')).toBe(1); }); + + it('does NOT re-add an author whose users row is gone (JOIN users guard — no FK-violating INSERT at boot)', () => { + insUser('survivor'); + insDm('orphan'); insMember('orphan', 'survivor'); + // Author 'ghost' has NO users row — an orphan message whose identity is gone. + // SQLite FK enforcement is per-connection and only checks at write time; it + // never re-validates pre-existing rows. So on disk such an orphan message can + // exist even with FKs on. Reproduce that by seeding it with FKs momentarily + // off, then restore enforcement so the backfill runs under real boot pragmas. + db.pragma('foreign_keys = OFF'); + insMsg('m1', 'orphan', 'ghost'); + db.pragma('foreign_keys = ON'); + insMsg('m2', 'orphan', 'survivor'); + backfillOneOnOneDmMembership(db); + // The JOIN users guard drops 'ghost' → nothing restored, member count stays 1. + // (A blind re-insert would raise "FOREIGN KEY constraint failed" here.) + expect(memberCount('orphan')).toBe(1); + expect(db.prepare('SELECT 1 FROM dm_members WHERE dm_channel_id=? AND user_id=?').get('orphan', 'ghost')).toBeUndefined(); + }); });