252 lines
15 KiB
Markdown
252 lines
15 KiB
Markdown
# 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.
|