[rooms] improve room ban/unban, history

[api] mod kick
[match] allow banned users into dorm
This commit is contained in:
Devin Zuczek
2026-09-17 10:43:31 -04:00
parent 61aa125af5
commit fd4264d982
18 changed files with 1804 additions and 260 deletions
@@ -0,0 +1,13 @@
-- A room ban can now carry a reason and lapse on its own.
--
-- Generated from packages/domain/src/rooms-db.ts (ROOM_SCHEMA_DDL) — keep in sync.
--
-- `reason` is the issuer's free text, NULL when none was given. `expires_at` is ISO-8601 UTC
-- (the same format `created_at` is written in, so the two compare as strings), and NULL is a
-- permanent ban — which is what every row written before this migration is, so no backfill.
--
-- A lapsed row is not deleted when it lapses: nothing runs at that moment. Every read that
-- asks whether a player is banned filters on `expires_at IS NULL OR expires_at > now` instead,
-- and the next ban or unban of that player overwrites or removes the stale row.
ALTER TABLE room_ban ADD COLUMN reason TEXT;
ALTER TABLE room_ban ADD COLUMN expires_at TEXT;
@@ -0,0 +1,30 @@
-- Room bans that have ENDED, so `GET /rooms/{roomId}/bans/history` has a past to report.
--
-- Generated from packages/domain/src/rooms-db.ts (ROOM_SCHEMA_DDL) — keep in sync.
--
-- `room_ban` holds only the ban in force: one row per (room, player), DELETEd on unban and
-- overwritten on re-ban. Everything that asks "is this player banned" — `match` among them —
-- reads that table and is unchanged. This table is append-only and written at the moment a
-- ban stops being the live one:
--
-- * lifted by an unban -> status 2 (Lifted), ended_at = the unban, unbanned_by_account_id set
-- * lapsed, then cleared -> status 1 (Elapsed), ended_at = its expiry, unbanned_by_account_id NULL
-- (by an unban of the stale row, or by a new ban replacing it)
--
-- A ban still in force that is re-issued is AMENDED in place, not ended, so it writes nothing.
-- Nothing is backfilled: bans lifted before this migration were deleted and left no record.
CREATE TABLE IF NOT EXISTS room_ban_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
room_id INTEGER NOT NULL,
banned_player_id INTEGER NOT NULL,
ban_mask INTEGER NOT NULL DEFAULT 0,
banned_by_account_id INTEGER NOT NULL,
created_at TEXT NOT NULL,
reason TEXT,
expires_at TEXT,
status INTEGER NOT NULL,
ended_at TEXT,
unbanned_by_account_id INTEGER
);
CREATE INDEX IF NOT EXISTS idx_room_ban_history_player
ON room_ban_history (room_id, banned_player_id);