Private
Public Access
delete_room() only ever cleaned up Message and RoomMembership rows, but none of the FK constraints referencing a room (or its messages) are declared ON DELETE CASCADE at the DB level -- confirmed across every migration that added one. Any room that ever had an image/file attachment, an incoming webhook, an outgoing event subscription, or was ever #referenced from a message in a *different* room (the one that originally surfaced this as a message_room_references FK violation in production) couldn't be deleted at all. Now explicitly cleans up, in dependency order: message mentions, reactions, and room-references (both the message-id and room-id directions), the messages themselves, then room-scoped images/files (including unlinking the actual stored files after a successful commit, not just their DB rows) and incoming webhooks/event subscriptions, before removing memberships and the room. Added a test reproducing the full scenario -- attachments, integrations, and a cross-room reference all on one room -- that would have 500'd before this fix, plus a sanity check that deleting the room doesn't touch the unrelated room that referenced it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>