Files
electric-cherry/docs/guides/moderation.md
T

15 KiB

Player moderation

Players → Moderation provides player search, warnings, private messages, kicks, announcements, bans, mutes, case records and private history. Restrictions can cover a server, a game or the fleet. Saving a restriction records the policy; the coverage table shows whether game runtimes have synchronized it.

Access

Administrators manage all moderation controls and configure integrations. Moderators can read private history, create notes/cases, send live actions, and issue server/game restrictions lasting at most seven days. They can revoke their own server/game restrictions originally lasting at most seven days. Applying or revoking permanent, longer or fleet restrictions, and revoking another staff member's restriction, require Administrator access. These limits also apply after an administrator becomes a Moderator. Super Viewers can inspect moderation but cannot change it. Operators and Viewers cannot read private moderation data. Moderator does not grant fleet operation, script, plugin, credential or account-management privileges.

Assign Moderator through Admin → Users. Existing users retain their roles; changing a role revokes that user's sessions. Each service rechecks current authorization, including immediately before delivering a queued live action.

Player identity and restrictions

Select a player from Moderation, a live scoreboard or a player profile. Search matches known aliases as well as GUIDs. A display name never identifies a restriction target. Manually entered GUIDs can have case records and restrictions before gameplay is observed; their first/last seen dates remain Not recorded.

IDs remain strings. Numeric game IDs are normalized without losing precision; T6 RCON hexadecimal IDs have a separate conversion rule. Historical chat links search for the raw log identity because its encoding is not assumed. Confirm a known player identity before applying a restriction. Fleet restrictions require the same numeric account ID to have been observed in both games. Otherwise use game scope.

Every restriction has a player-visible reason, optional private note, scope, expiry, creator and revision. Reasons and live messages must fit in 240 UTF-8 bytes. The native adapter replaces console control characters in displayed text. Overlapping restrictions remain independent: revoking one mute does not cancel another active mute. Revocation requires a reason and the current revision; concurrent changes require refreshing before another decision.

Server scope follows a logical server registration across instance replacement or rebuild. Deleting and later registering the same server name creates a new registration, which does not inherit the old server-scoped restriction. Game/fleet policies apply to every connected compatible runtime in that scope, including newly provisioned servers. A new runtime must synchronize before it has a complete policy; provisioning readiness alone does not prove moderation coverage. The initial limit is 1,000 active restrictions across the controller.

Enable the game integration

The controller requires EC_PUBLIC_URL to be a public HTTPS origin. The host agent must advertise moderation.configure (agent 1.11.0+). Install the matching TWS moderation script 1.0.0, common 1.2.0+, and TWS native plugin 1.3.0+ from tws-zombies-scripts for each game. New native plugins require a full game-server process restart. Use the normal release/beta workflow and validate one T5 Zombies and one T6 Zombies instance before fleet rollout.

New launches/rebuilds on capable agents receive a private moderation config when EC_PUBLIC_URL is configured. Existing instances can use Enable integration in Moderation. This queues a typed operation that writes the fixed private config and loads its dvars, without restarting gameplay. Existing startup persistence uses the verified private bank config; older instances without that bootstrap must be rebuilt. Installed moderation scripts retry missing configuration.

The private file configs/electric_cherry_moderation.cfg contains the HTTPS endpoint, generation and a separate per-instance credential. It is excluded from shared artifacts, file reads, drift scans, logs and operation receipts. Game credentials are distinct from bank, telemetry and host credentials. They only authorize the active immutable instance generation; retirement/rebuild revokes the previous generation's access. Older agents retain ordinary server launches, but cannot provide this integration.

Coverage states describe runtime communication:

  • Policy current: a fresh runtime supports both bans and mutes and has acknowledged the current policy revision.
  • Pending: the runtime is connected but has not acknowledged the latest revision or does not support both bans and mutes.
  • Offline: no runtime synchronization has arrived for more than 15 seconds.
  • Unavailable: this instance generation has not connected.

Policy current is not proof that an engine mute command took effect. The runtime reports supported capabilities; unsupported live actions stay unavailable. Native kick/mute command behavior and voice/text suppression require testing on the deployed Plutonium build. A disconnected host cannot receive a new ban or revocation until it reconnects.

Live actions and offline enforcement

Live actions expire after 30 seconds and target the runtime's exact player connection. A reconnect, reused slot, changed generation or revoked moderator access prevents stale dispatch. Browser retries preserve the request identity. The native adapter journals one-time actions before dispatch and never executes the same action ID twice, including after restart.

Queued actions can become delivered, confirmed, failed, expired or unknown. An expired undelivered action did not run. Unknown means delivery occurred but the result could not be established; do not assume the action failed. A durable late receipt can resolve an unknown outcome. Confirmation of a message means server dispatch, not proof the recipient read it. Kick confirmation requires an observed disconnect.

The native runtime caches the complete applicable policy on persistent storage, scoped to the server, endpoint, generation and credential fingerprint. Cached bans/mutes continue through controller outages and expire using the host clock. Keep host time synchronized. A ban disconnects a player after connecting; it is not a pre-authentication admission filter. The shared connection handler and a 500 ms reconciliation loop enforce it, retrying still-connected banned players every five seconds. No native ban.txt entries are rewritten.

Preserve tws-moderation/t5/ or tws-moderation/t6/ in the game working directory. The cache includes an increasing runtime session counter that prevents an older process from replacing the active player roster. Losing or rolling back this cache requires a generation rebuild with a new credential before synchronization can resume; re-enabling the same integration does not reset the counter. Corrupt caches and failed durable writes stop new actions and require operator investigation. A controller restored to an older policy revision cannot silently replace a newer cached revision; review the restore and integration before resetting its cache or credentials.

Cases, evidence and review

Create a case for a report, investigation or appeal. Each case has a dedicated, shareable page with the player identity, evidence, staff notes, linked restrictions, and an activity timeline. These pages require moderation access. Give a case a priority and assign it to an eligible administrator or moderator. Filter the case queue by status, priority, or assignment; active cases appear first, ordered by priority and most recent update.

Move active cases between Open, In review, and Escalated, recording a reason for workflow changes. Close a case with one of these outcomes: Resolved, Dismissed, Warning issued, Restriction applied, No action needed, Duplicate, Appeal upheld, or Appeal denied. Every decision requires a reason. Reopen a closed case when new evidence or an appeal needs review; earlier decisions remain in its history. Editing case details does not reopen a case.

Use Edit assessment to keep a concise current summary, list the applicable rules, and record a finding for each concern: hate speech, harassment, threats, safeguarding, spam, cheating, or another concern. Each finding is Substantiated, Inconclusive, or Unsubstantiated, with a short rationale. Findings describe the evidence; the case's workflow status and final outcome remain separate. Every saved assessment retains its author, timestamp, and complete previous revision. Assessments can be revised after closure without reopening the case.

Before opening a case, review existing cases for the same game and GUID. A case also shows same-player candidates; a shared archived match is a useful potential duplicate signal, not a finding that two reports are identical. Link cases as Same incident, Appeal of, or Duplicate of, recording why they belong together. Same-incident links may include different players; appeals and duplicates must concern the same game and player. Links appear from both cases with their direction made explicit. Self-links and circular appeal/duplicate chains are rejected. Removing a mistaken relationship requires a reason and preserves its history. Relationship changes do not close or reopen either case.

Schedule a follow-up using a date and time, or Review when a linked mute expires. Custom date entry uses your browser's local time; displayed dates follow your time zone preference. Reviews remain scheduled after a case closes or reopens. Use Overdue reviews to find due work across open and closed cases, and clear the follow-up with a reason when the review is complete.

In-app case updates notify the assignee and case creator when another staff member adds evidence or a staff note. Assignment changes notify the previous and new assignees and the creator, excluding the person making the change. Your unread updates is personal to your account. Open a case to review and mark existing updates read; notifications arriving afterward stay unread. Queue and case pages refresh every 15 seconds while visible. These are in-app notifications, with no email or external messaging delivery.

Apply a ban or mute directly from an active case. The case fixes the target game and GUID and records the resulting restriction alongside the evidence. The same role, scope, and duration limits apply as elsewhere in Moderation. Applying a restriction leaves the case active so staff can finish reviewing it. Selecting a closure outcome records a decision; it does not itself send a warning, create a restriction, or revoke one. Linked restrictions can be revoked separately with the required permission and reason, including after a case closes. Reopening a case also leaves its restrictions in place. Check enforcement coverage after applying or revoking a restriction.

Use Link existing action to associate a warning, kick, private message, ban, or mute already recorded for this player with the case. This preserves the original action, author, time, delivery state, and expiry; it does not issue another action or extend a restriction. The same action can support more than one related case. Linking requires the current case revision and a reason, and appears in its timeline. When closing with Warning issued or Restriction applied, optionally reference one of the linked records. Warning references require a confirmed warning; failed or uncertain delivery remains visible without being presented as a confirmed warning.

Staff notes are explicitly labeled as notes. In match chat, select up to 100 messages and choose Attach to case to open a case or add them to an existing case for the selected subject. Select at least one message from that subject; messages from other participants can be selected alongside it. Each attachment preserves selected messages and, by default, three surrounding messages on either side, with names, GUIDs, original timing, and highlighted subject messages. The selection preview shows the excerpt before saving. Server verification uses stable archived message identifiers; repeated text remains separate occurrences, and attaching the same selected messages again does not duplicate evidence. Exact-text attachments remain available and include every matching occurrence, without the former ten-occurrence limit.

Snapshots remain readable after source-match cleanup. Unknown or estimated timestamps remain such; the snapshot does not turn them into exact observations. Unarchived or already deleted chat cannot be attached as verified evidence.

Open Chat archive from Moderation to include all recorded matches, including round-one games, interrupted games, and games missing an end report. Archive access requires moderation read permission. Filter by server, game, map, status, or date and open a match to select its preserved messages. Incomplete matches show their observed state rather than final results. Ordinary match history and leaderboard qualification are unchanged.

Both public (say) and team (sayteam) log messages are captured. Team messages carry a Team chat label in chat and saved excerpts. Collection runs without a live viewer and checks surviving logs once after startup, including idle servers. Archive coverage still depends on the source log and accepted match telemetry: logs that were deleted or rotated before collection, or old clock segments that cannot safely be associated with a match, cannot be reconstructed. The collector retains a bounded log tail (up to 2,000 lines / 256 KiB); it is not a full historical log import. Already saved case excerpts survive later source cleanup.

Case decisions, edits, and restrictions check the current revision; refresh before retrying a decision if another staff member has changed the case. Evidence, restrictions and append-only moderation events survive source-match cleanup and server deletion. They currently have no automatic retention cleanup. Authentication audit cleanup does not remove moderation history. Correct decisions by reopening, adding notes, or revoking restrictions; there is no history-erasing delete endpoint.

Leaderboard disqualification, bank balance changes, automatic escalation and a public report/appeal portal are separate features. This workflow supports staff review of reports and appeals without exposing private evidence publicly.

Development and acceptance

Controller tests cover permission boundaries, migrations, idempotency, exact instance credentials, stale connections, expired actions, late receipts, restriction expiry/revocation, policy coverage and evidence preservation. Agent tests cover private configuration delivery and secret redaction. Companion native tests exercise real policy/journal code and adapters with engine shims.

Before deploying, build the x86 native plugins on Windows and validate both games: duplicate names, account reconnects, slot reuse, kick reasons, voice/text mute/unmute, overlapping restrictions, map/process restart, new server policy sync, expiry, revocation, controller outage and persistent-storage failure. Portable tests cannot establish the live Plutonium ABI or engine behavior. Package and offline-sign the agent release before publishing it; local builds remove any stale manifest signature and do not sign or deploy the release.