Sneedchat: moderators have no moderation #112

Closed
opened 2026-09-02 23:25:46 -04:00 by Salastil · 1 comment
Owner

ServerResponse.perms is decoded and only can_send is used (sockchat/mod.rs:558). Everything else the site grants a moderator - deleting somebody else's message, timing out or banning a user in a room - has no path here, so a moderator has to open the site to moderate.

Done looks like: the permissions already parsed decide which actions the userlist and message menus offer, and the actions send what the site's own chat sends.

`ServerResponse.perms` is decoded and only `can_send` is used (sockchat/mod.rs:558). Everything else the site grants a moderator - deleting somebody else's message, timing out or banning a user in a room - has no path here, so a moderator has to open the site to moderate. **Done looks like:** the permissions already parsed decide which actions the userlist and message menus offer, and the actions send what the site's own chat sends.
Salastil added the feature label 2026-09-03 13:11:37 -04:00
Salastil added the low priority label 2026-09-04 15:52:50 -04:00
Author
Owner

Investigated and closing without implementing, because there is no way to test any of it here.

What exists today

  • The permission frame is decoded but modelled as two fields (can_view, can_send) and only can_send is read. Unlike RawResponse, Perms has no #[serde(flatten)] extra, so whatever else the server grants is dropped silently rather than showing up in the undecoded-keys log.
  • Deleting a message already works end to end: prepare_delete builds /delete <uuid>, deleteMessage is wired for Sneedchat, and incoming batch deletes (a moderator removing somebody else's post) are applied to the log.
  • The client already has everywhere to put the rest: RoomPermissions, the canRedactOthers gate and its "Delete (moderator)" entry in the message menu, and the per-service onModerate switch in the member list.

What Sneedchat inherits

It is a stripped rewrite of Siropu Chat for XenForo. That add-on's own feature list names user sanctions (Mute/Kick/Ban) and 21 global user commands, which is the vocabulary to look for — but in Siropu, sanctions are a moderator action against the XenForo backend, not something typed into the chat stream, while Sneedchat's /delete and /edit are socket commands. So this build could plausibly send either, and the daemon can already do both: the room socket, or the logged-in Session with post_form and the _xfToken reader that the login flow uses.

Why this cannot be finished blind

The hazard is recorded in the code above WHISPER_COMMAND: an unrecognised command is not rejected by the site, it is posted into the room as ordinary text. That is how every whisper this client sent went to the whole room with /whisper @name written in front of it. A guessed /ban is therefore not a failed action — it is publicly writing "/ban Someone" into a channel.

And the account moho signs in with is an ordinary user, not a moderator. So there is no moderator permission frame to model, no action that can be exercised, and no way to confirm a spelling except by sending it in public and seeing what happens.

What a future attempt should do first

  1. Add #[serde(flatten)] extra to Perms and log its outline with the existing outline() helper, the way RawResponse already does. Connect as a moderator and read what the server actually grants — that is where the gate for each action comes from.
  2. Fetch the chat page and its scripts through the daemon's gated HTTP client (Session::fetch) and grep the bundle for both shapes: slash-command literals, and route names like mute, kick, ban, sanction. /delete and /edit are the control that proves the read works.
  3. Implement only what both reads confirm.

Reopening this is worth it the moment there is a moderator account to connect with.

Investigated and closing without implementing, because there is no way to test any of it here. ## What exists today - The permission frame is decoded but modelled as two fields (`can_view`, `can_send`) and only `can_send` is read. Unlike `RawResponse`, `Perms` has no `#[serde(flatten)] extra`, so whatever else the server grants is dropped silently rather than showing up in the undecoded-keys log. - Deleting a message already works end to end: `prepare_delete` builds `/delete <uuid>`, `deleteMessage` is wired for Sneedchat, and incoming batch deletes (a moderator removing somebody else's post) are applied to the log. - The client already has everywhere to put the rest: `RoomPermissions`, the `canRedactOthers` gate and its "Delete (moderator)" entry in the message menu, and the per-service `onModerate` switch in the member list. ## What Sneedchat inherits It is a stripped rewrite of **Siropu Chat** for XenForo. That add-on's own feature list names **user sanctions (Mute/Kick/Ban)** and 21 global user commands, which is the vocabulary to look for — but in Siropu, sanctions are a moderator action against the **XenForo backend**, not something typed into the chat stream, while Sneedchat's `/delete` and `/edit` *are* socket commands. So this build could plausibly send either, and the daemon can already do both: the room socket, or the logged-in `Session` with `post_form` and the `_xfToken` reader that the login flow uses. ## Why this cannot be finished blind The hazard is recorded in the code above `WHISPER_COMMAND`: **an unrecognised command is not rejected by the site, it is posted into the room as ordinary text.** That is how every whisper this client sent went to the whole room with `/whisper @name` written in front of it. A guessed `/ban` is therefore not a failed action — it is publicly writing "/ban Someone" into a channel. And the account moho signs in with is an ordinary user, not a moderator. So there is no moderator permission frame to model, no action that can be exercised, and no way to confirm a spelling except by sending it in public and seeing what happens. ## What a future attempt should do first 1. Add `#[serde(flatten)] extra` to `Perms` and log its outline with the existing `outline()` helper, the way `RawResponse` already does. Connect **as a moderator** and read what the server actually grants — that is where the gate for each action comes from. 2. Fetch the chat page and its scripts through the daemon's gated HTTP client (`Session::fetch`) and grep the bundle for both shapes: slash-command literals, and route names like `mute`, `kick`, `ban`, `sanction`. `/delete` and `/edit` are the control that proves the read works. 3. Implement only what both reads confirm. Reopening this is worth it the moment there is a moderator account to connect with.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#112