11 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.
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.
Staff notes are explicitly labeled as notes. Selecting archived chat when opening a case, or attaching a match ID and exact message within an existing case, verifies the target GUID and original message against the recorded match and saves an independent snapshot, including the original timing context. 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.
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.