Close out chat: owner settings, wipe-now, mention highlight, entry point
Multithreaded chat had its crate, storage, trait impls, routes and client
island but no way in and no way for an owner to shape it. Four things:
The community page links to the room. Nothing did, so /p/{slug}/chat was
reachable only by typing it. The link resolves through room_state rather
than reading chat_policy, so it appears exactly when the route does not
404 and a read-only room still links.
The settings screen writes chat_policy and both retention bounds, owner
only, generated from ChatPolicy::ALL so a fifth variant needs no template
edit. Both bounds are validated against the crate ceilings before the
write, leaving migration 039's CHECKs as the backstop they were meant to
be. Saving calls recompute_chat_expiry, which had no caller: expiry is
stamped at insert, so a shortened window that does not reach back applies
only to future messages.
Wipe-now is a new ChatEvent::Wipe rather than a fan of Delete or Purge
frames, since a wipe is not addressed at anyone and the client just
empties the log. Owner-only through a separate flag on MtChatModeration:
moderators moderate people, and emptying the room is not that. Logged as
ModAction::ChatWipe on the same transaction as the deletion.
Mentions highlight in-room and notify nobody. Matched against docengine's
username rule on the rendered body, since render_chat deliberately leaves
@name as plain text. Code spans and tag interiors are excluded, and a
name markup splits stays split, so the client and the forum agree on what
counts as naming someone.
Also: button.danger had no CSS, so the admin clean-slate button rendered
as an ordinary one.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-09 19:00 UTC