Moderation appeals (Phase 6c) + Discord auto-reversal (Phase 6d) #74

Merged
whitlocktech merged 2 commits from feature/moderation-appeals into main 2026-07-19 05:18:20 +00:00
Member

Unblocks the shelved Phase 6c/6d work now that the moderation dashboard (#42) and player accounts (#43) are merged.

6c — Appeals

Players whose linked Discord identity was banned or muted can submit an appeal from the player portal and track it; staff (admin/moderator) get a queue to claim and resolve (approve/deny) with a written response.

  • Schema: new server-owned appeals table (mirrors mod_notes ownership; mod_action_id is a plain column — no cross-owner FK to the bot-owned mod_actions, validated in app code).
  • Server: model/appeals/*, player appeals controller (mine / eligible / submit / withdraw), and admin queue handlers (list / claim / resolve / per-user) mounted in the existing /moderation admin+moderator block. One active appeal per action (app-level); only ban/mute are appealable; eligibility keyed on the caller's linked Discord identity.
  • Client: admin Appeals.jsx queue + resolve modal, PlayerAppeals.jsx, an Appeals tab on the per-user moderation history, nav + routes + API methods.

6d — Bot reversal

Approving a ban/mute appeal best-effort calls the bot's new POST /internal/mod-reverse (shared-secret, like /internal/announce) to lift the ban / clear the timeout and post a mod-log embed. A down bot never fails the resolution — reversal_status is recorded as failed and staff reverse manually. The resolve response carries a reversal object.

Docs / API

  • Swagger annotations + component schemas added; swagger-output.json regenerated.
  • Companion docs PR: RunicGateway/docs#5 (website/MODERATION_APPEALS.md).

Tests

  • server npm test: 224 pass (new appeals.test.js + appeals.pure.test.js).
  • client npm run build: green.

Not yet verified (needs a live environment)

  • DB-backed smoke against MariaDB (Docker wasn't available in the build env).
  • Live 6d: real bot connected + approving an appeal actually lifting a Discord ban.
  • Note: the bot has no test harness, so mod-reverse is only covered indirectly via the mocked server resolve tests.

🤖 Generated with Claude Code

Unblocks the shelved Phase 6c/6d work now that the moderation dashboard (#42) and player accounts (#43) are merged. ## 6c — Appeals Players whose linked Discord identity was **banned** or **muted** can submit an appeal from the player portal and track it; staff (admin/moderator) get a queue to **claim** and **resolve** (approve/deny) with a written response. - **Schema:** new server-owned `appeals` table (mirrors `mod_notes` ownership; `mod_action_id` is a plain column — no cross-owner FK to the bot-owned `mod_actions`, validated in app code). - **Server:** `model/appeals/*`, player appeals controller (mine / eligible / submit / withdraw), and admin queue handlers (list / claim / resolve / per-user) mounted in the existing `/moderation` admin+moderator block. One active appeal per action (app-level); only ban/mute are appealable; eligibility keyed on the caller's linked Discord identity. - **Client:** admin `Appeals.jsx` queue + resolve modal, `PlayerAppeals.jsx`, an Appeals tab on the per-user moderation history, nav + routes + API methods. ## 6d — Bot reversal Approving a ban/mute appeal best-effort calls the bot's new `POST /internal/mod-reverse` (shared-secret, like `/internal/announce`) to lift the ban / clear the timeout and post a mod-log embed. A down bot never fails the resolution — `reversal_status` is recorded as `failed` and staff reverse manually. The resolve response carries a `reversal` object. ## Docs / API - Swagger annotations + component schemas added; `swagger-output.json` regenerated. - Companion docs PR: RunicGateway/docs#5 (`website/MODERATION_APPEALS.md`). ## Tests - `server npm test`: **224 pass** (new `appeals.test.js` + `appeals.pure.test.js`). - `client npm run build`: green. ## Not yet verified (needs a live environment) - DB-backed smoke against MariaDB (Docker wasn't available in the build env). - Live 6d: real bot connected + approving an appeal actually lifting a Discord ban. - Note: the bot has no test harness, so `mod-reverse` is only covered indirectly via the mocked server resolve tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-07-19 03:47:58 +00:00
feat(moderation): appeals (6c) + Discord reversal on approve (6d)
All checks were successful
PR Checks / server-tests (pull_request) Successful in 9m59s
PR Checks / client-build (pull_request) Successful in 9m32s
PR Checks / bot-install (pull_request) Successful in 9m37s
028ba8c5e4
Players whose linked Discord identity was banned or muted can now submit
an appeal from the portal and track it; staff get a queue in the admin
moderation section to claim and resolve (approve/deny) appeals. Approving
a ban/mute appeal best-effort asks the Discord bot to reverse the action
(unban / clear timeout) via the internal API and posts a mod-log embed; a
down bot never fails the resolution (reversal_status is recorded).

- Schema: new server-owned `appeals` table (no cross-owner FK to
  mod_actions; existence validated in app code).
- Server: model/appeals/* + player appeals controller (submit/mine/
  eligible/withdraw) and admin queue handlers (list/claim/resolve/
  per-user) under the existing admin+moderator gate; one-active-appeal
  enforced app-side; eligibility keyed on the caller's linked Discord id.
- 6d: bot POST /internal/mod-reverse (+ modLog.postReversal) and
  server botInternalClient.reverseModAction, wired into resolve().
- Client: admin Appeals queue + resolve modal, ModerationUser appeals
  tab, player Appeals page (submit/withdraw), nav + routes + api methods.
- Docs: swagger annotations + component schemas, regenerated output.
- Tests: appeals controller + pure suites (server npm test 224 green).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmHdsbnLzDMAVQkAoTQSBe
whitlocktech approved these changes 2026-07-19 03:49:29 +00:00
whitlocktech added 1 commit 2026-07-19 03:49:43 +00:00
Merge branch 'main' into feature/moderation-appeals
All checks were successful
PR Checks / server-tests (pull_request) Successful in 9m35s
PR Checks / client-build (pull_request) Successful in 9m51s
PR Checks / bot-install (pull_request) Successful in 9m22s
60e6a60842
whitlocktech scheduled this pull request to auto merge when all checks succeed 2026-07-19 03:49:53 +00:00
whitlocktech canceled auto merging this pull request when all checks succeed 2026-07-19 04:08:33 +00:00
whitlocktech merged commit 896773b8a5 into main 2026-07-19 05:18:20 +00:00
whitlocktech deleted branch feature/moderation-appeals 2026-07-19 05:18:21 +00:00
Sign in to join this conversation.
No description provided.