feat(safety): report, block and hide chat lines (MODULE_API 1.21.0) #72

Merged
whitlocktech merged 1 commits from feature/user-safety into edge 2026-10-30 09:20:41 -05:00
Member

What & why

Step 3 of docs/website/USER_SAFETY.md (account-deletion step 7): the module half of report, block and hide. Core shipped its half in website#233. This PR makes Rust chat lines reportable, hideable and blockable, as §4.2 and S11-S14 describe.

Server

  • server/safety.js holds all of it:

    • The rust.chat report target. snapshot answers for one reader and returns null when they couldn't have seen the line: a server whose presence is hidden from them, or a line staff hid when the reader isn't staff. hide and unhide are staff's hide for everyone.
    • The steam game identity. ownersOf reads rust_account_links.
  • The events feed filters chat per reader, in the SQL, so a page of 100 is still 100 long. It leaves out:

    • lines from every Steam id linked to an account the reader blocks;
    • lines from the reader's own unlinked Steam-ID blocks;
    • lines the reader hid.

    Only player.chat rows are filtered: a blocked player's deaths and connects stay in the feed. Signed-in readers get canBlock on each chat line. It's false on their own lines and on lines from staff-linked players.

  • Hide for everyone:

    • rust_events gains hidden_at and hidden_by, added with ALTER … ADD COLUMN IF NOT EXISTS.
    • Hidden lines are left out for everyone except staff, who get them with hidden: true.
    • New routes POST /admin/rust/chat/:id/hide and /unhide, for admins and moderators. Both are written to the activity log.
  • If core's safety read fails, the feed is served unfiltered with a warning in the log rather than failing. If the staff lookup fails, every line gets canBlock: false.

  • coreApi is ^1.21.0. ci/core-ref.json is pinned to the website#233 merge (f13b8fe). routes.manifest.json and swagger-fragment.json are regenerated, and ci/bundle.json now ships safety.js.

Client

  • components/ChatMenu.jsx: a ⋯ at the end of each chat line in the feed.
    • Signed out: Sign in to report or block.
    • Members: Report (six reasons plus an optional detail), Hide for me, and Block player where canBlock is true. Block asks for confirmation first.
    • Staff also get Hide for everyone, or Show to everyone again on a hidden line.
  • The feed re-reads itself after any of these. Lines staff hid show dimmed, marked Hidden by staff.

Docs: RunicGateway/docs docs/user-safety-rust. Kit: RunicGateway/Integration-kit docs/core-1.21.0.

How it was tested

  • npm test in server: 750 tests, 0 failing. Includes the new test/safety.test.js.
  • check:imports, check:bundle, check:swagger and check:engagement are all OK.
  • In client: npm run build, npm test (107 tests, 0 failing) and check:externals all pass.
  • Frozen manifest: regenerated against a clean core worktree at f13b8fe, the same way CI does it. --check passes: 91 routes, all documented, none of core's moved.
  • Live walk. Throwaway DB usafety3 on the local MariaDB, a core on :3293 with this branch's module installed, chat lines and Steam links written straight into the tables. 28 API rows over bearer logins, all passing:
    • Signed out: every line, no canBlock.
    • canBlock was correct for unlinked, linked, own and moderator lines.
    • A report reached the queue with its snapshot.
    • These were all 404: a line on a staff-only-presence server, a death's id, and a missing id.
    • Blocking an unlinked speaker made a Steam-ID block. It removed their chat, but not their death, from one member's feed only.
    • Blocking a linked speaker made an account block.
    • Blocking a moderator was refused with 403 staff.
    • Hide for me hid one line for one member.
    • S14: a Steam-ID block, then linking the id, read back as an account block and kept the line out.
    • Hide for everyone from the queue: the report was actioned, the line was gone for members and signed-out readers, and staff saw it marked. It could no longer be reported.
    • The staff route hid and unhid lines and wrote the activity log. A player got 403; a missing line got 404.
    • Unblock and Show them all again brought the lines back.
  • Browser (same core):
    • The menu signed out, as a member and as a moderator.
    • Report: success, plus core's duplicate-report refusal.
    • Block with its confirmation.
    • No Block on your own line or a moderator's.
    • Account → Blocked listed the Steam-ID block and both account blocks.
    • Hide for everyone and Show to everyone again, with the Hidden by staff marker.
    • The Reports queue showed both chat-line reports from their snapshots.
    • No console errors.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • No AI tools were used to produce this contribution.
  • AI tools were used. Tool(s): Claude Code (Claude Opus 5.5). I have reviewed and understand
    every change, and take responsibility for it. AI-authored commits are
    marked with a Co-Authored-By / Assisted-By trailer.

License

  • I agree that my contribution is licensed under this project's license
    (GNU GPL v3.0 or later), and I have the right to contribute it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY

## What & why Step 3 of `docs/website/USER_SAFETY.md` (account-deletion step 7): the module half of report, block and hide. Core shipped its half in website#233. This PR makes Rust chat lines reportable, hideable and blockable, as §4.2 and S11-S14 describe. **Server** - `server/safety.js` holds all of it: - The `rust.chat` report target. `snapshot` answers for one reader and returns `null` when they couldn't have seen the line: a server whose presence is hidden from them, or a line staff hid when the reader isn't staff. `hide` and `unhide` are staff's hide for everyone. - The `steam` game identity. `ownersOf` reads `rust_account_links`. - **The events feed filters chat per reader, in the SQL**, so a page of 100 is still 100 long. It leaves out: - lines from every Steam id linked to an account the reader blocks; - lines from the reader's own unlinked Steam-ID blocks; - lines the reader hid. Only `player.chat` rows are filtered: a blocked player's deaths and connects stay in the feed. Signed-in readers get `canBlock` on each chat line. It's false on their own lines and on lines from staff-linked players. - **Hide for everyone**: - `rust_events` gains `hidden_at` and `hidden_by`, added with `ALTER … ADD COLUMN IF NOT EXISTS`. - Hidden lines are left out for everyone except staff, who get them with `hidden: true`. - New routes `POST /admin/rust/chat/:id/hide` and `/unhide`, for admins and moderators. Both are written to the activity log. - If core's safety read fails, the feed is served unfiltered with a warning in the log rather than failing. If the staff lookup fails, every line gets `canBlock: false`. - `coreApi` is `^1.21.0`. `ci/core-ref.json` is pinned to the website#233 merge (`f13b8fe`). `routes.manifest.json` and `swagger-fragment.json` are regenerated, and `ci/bundle.json` now ships `safety.js`. **Client** - `components/ChatMenu.jsx`: a `⋯` at the end of each chat line in the feed. - Signed out: *Sign in to report or block*. - Members: *Report* (six reasons plus an optional detail), *Hide for me*, and *Block player* where `canBlock` is true. Block asks for confirmation first. - Staff also get *Hide for everyone*, or *Show to everyone again* on a hidden line. - The feed re-reads itself after any of these. Lines staff hid show dimmed, marked *Hidden by staff*. Docs: RunicGateway/docs `docs/user-safety-rust`. Kit: RunicGateway/Integration-kit `docs/core-1.21.0`. ## How it was tested - `npm test` in `server`: 750 tests, 0 failing. Includes the new `test/safety.test.js`. - `check:imports`, `check:bundle`, `check:swagger` and `check:engagement` are all OK. - In `client`: `npm run build`, `npm test` (107 tests, 0 failing) and `check:externals` all pass. - Frozen manifest: regenerated against a clean core worktree at `f13b8fe`, the same way CI does it. `--check` passes: 91 routes, all documented, none of core's moved. - **Live walk.** Throwaway DB `usafety3` on the local MariaDB, a core on `:3293` with this branch's module installed, chat lines and Steam links written straight into the tables. 28 API rows over bearer logins, all passing: - Signed out: every line, no `canBlock`. - `canBlock` was correct for unlinked, linked, own and moderator lines. - A report reached the queue with its snapshot. - These were all 404: a line on a staff-only-presence server, a death's id, and a missing id. - Blocking an unlinked speaker made a Steam-ID block. It removed their chat, but not their death, from one member's feed only. - Blocking a linked speaker made an account block. - Blocking a moderator was refused with 403 `staff`. - *Hide for me* hid one line for one member. - S14: a Steam-ID block, then linking the id, read back as an account block and kept the line out. - *Hide for everyone* from the queue: the report was actioned, the line was gone for members and signed-out readers, and staff saw it marked. It could no longer be reported. - The staff route hid and unhid lines and wrote the activity log. A player got 403; a missing line got 404. - Unblock and *Show them all again* brought the lines back. - **Browser** (same core): - The menu signed out, as a member and as a moderator. - Report: success, plus core's duplicate-report refusal. - Block with its confirmation. - No Block on your own line or a moderator's. - *Account → Blocked* listed the Steam-ID block and both account blocks. - *Hide for everyone* and *Show to everyone again*, with the *Hidden by staff* marker. - The Reports queue showed both chat-line reports from their snapshots. - No console errors. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [ ] No AI tools were used to produce this contribution. - [x] AI tools were used. Tool(s): `Claude Code (Claude Opus 5.5)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` / `Assisted-By` trailer. ## License - [x] I agree that my contribution is licensed under this project's license (**GNU GPL v3.0 or later**), and I have the right to contribute it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
wtclaude added 1 commit 2026-10-30 09:05:11 -05:00
feat(safety): report, block and hide chat lines (MODULE_API 1.21.0)
Some checks failed
PR Checks / client-build (pull_request) Successful in 51s
PR Checks / frozen-manifest (pull_request) Successful in 53s
PR Checks / server-tests (pull_request) Failing after -17s
dd9b8b2711
USER_SAFETY.md step 3, the module half of report, block and hide.

- server/safety.js registers the rust.chat report target (snapshot for one
  reader, null when they could not have seen the line; staff's hide and
  unhide) and the steam game identity (ownersOf from rust_account_links).
- The events feed filters chat per reader, in the query: lines from a
  blocked account's Steam ids, the reader's unlinked Steam-ID blocks and the
  lines they hid. Signed-in readers get canBlock on each chat line (false for
  their own and for staff-linked players). Lines staff hid for everyone are
  left out for everyone but staff, who get them with hidden: true.
- rust_events gains hidden_at and hidden_by (ALTER ... IF NOT EXISTS).
- POST /admin/rust/chat/:id/hide and /unhide (admin, moderator), logged.
- The feed's chat lines get a menu: Report, Hide for me, Block player,
  and for staff Hide for everyone / Show to everyone again.
- coreApi ^1.21.0; ci/core-ref.json pinned to the website#233 merge;
  routes.manifest.json and swagger-fragment.json regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
whitlocktech merged commit 0c29dbf6eb into edge 2026-10-30 09:20:41 -05:00
whitlocktech deleted branch feature/user-safety 2026-10-30 09:20:43 -05:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/Module-Rust#72
No description provided.