# ForgeGuard staff guide (0.6)

This guide covers the modern ForgeGuard core's in-game administration, alerts and violation levels, spectate and notes, live inventory editing, behaviour checks, the response ladder, event guards and the website console. Start with `/fg menu`. ForgeGuard records observations and provides manual staff tools; it only punishes automatically if you switch on the response ladder, and it does not claim complete protection against every cheat.

The universal loader can also provide a smaller portable staff-only runtime. Its available commands, installation paths and exact tested servers are listed in [Version support](VERSION-SUPPORT.md). A staff GUI opening on an older server does not mean modern detection is running there.

## Locate the running configuration

| Installation | Modern configuration and data |
| --- | --- |
| Standalone release `ForgeGuard-0.3.0-alpha.1-obfuscated.jar` | `plugins/ForgeGuard/` |
| `ForgeGuard-0.3.0-alpha.1-universal.jar`, modern core selected | `plugins/ForgeGuard/` |
| Universal loader, portable staff-only runtime | Configuration/audit in `plugins/ForgeGuardLoader/`; shared bans in `plugins/ForgeGuard/moderation/bans.json` |

Install either the standalone modern JAR or the universal JAR, not both. The universal loader includes the modern core and extracts it to `plugins/ForgeGuardLoader/runtime/ForgeGuard-core.jar`. On a qualified modern host, the core still needs PacketEvents. Read startup messages and `/fg health` to establish which runtime actually loaded. See [Version support](VERSION-SUPPORT.md) for requirements and test evidence.

Paper assigns the embedded modern core its normal `plugins/ForgeGuard` data directory even though its JAR is nested. The loader verifies this path and refuses an unexpected location; it does not copy or overwrite a configuration directory. Both adapters read and write the same version-1 UUID ban database at `plugins/ForgeGuard/moderation/bans.json`. Back up that shared database plus the active configuration/audit directories before upgrading. The modern core's existing migration from the sibling `plugins/SentinelForge` directory continues to work normally.

## Grant the right permissions

Web operator accounts and Minecraft permissions are separate. Being a web owner does not grant in-game abilities. All commands and GUI pages require `forgeguard.staff`; actions also require the node below.

| Permission | Allows |
| --- | --- |
| `forgeguard.staff` | Staff menu, player overview, evidence and health |
| `forgeguard.alerts` | Opt in to staff alerts with `/fg alerts` |
| `forgeguard.recordings` | Start an audited scene snippet, invite player-enabled screen sharing, or request a screenshot from the modern staff GUI |
| `forgeguard.spectate` | Audited spectator mode following a player, with your position, game mode and flight restored afterwards |
| `forgeguard.notes` | Read and write short staff notes about players |
| `forgeguard.inventory` | Audited, read-only inventory and ender chest snapshots |
| `forgeguard.inventory.edit` | Live, editable inventory and Ender Chest views (also needs `forgeguard.inventory`) |
| `forgeguard.freeze` | Stage and confirm freeze/unfreeze |
| `forgeguard.teleport` | Stage and confirm teleport-to-player and return |
| `forgeguard.kick` | Stage and confirm a manual kick |
| `forgeguard.ban` | Ban records, temporary and permanent UUID bans |
| `forgeguard.unban` | Stage and confirm removal of a ForgeGuard UUID ban |
| `forgeguard.admin` | Validated configuration changes, reload and movement grace |
| `forgeguard.protected` | Protect the holder against staff targeting unless the actor has override |
| `forgeguard.override` | Explicitly permit otherwise-protected targeting, including self-targeting |
| `forgeguard.bypass` | Exempt experimental movement observations; packet validity and coarse rate observations remain |
| `forgeguard.guard.bypass` | Exempt event-rate and book-content guards |

Staff/action nodes default to operators. The protection, override and bypass nodes default to false. `forgeguard.*` grants staff actions but excludes protection, override and bypass. Use a permissions plugin to grant only the actions each role needs. Existing individual `sentinelforge.*` grants and explicit revocations are supported; an explicitly set current permission takes precedence.

The Ban records GUI requires `forgeguard.ban` to browse; confirming removal also requires `forgeguard.unban`. A moderator with only the unban permission can use the UUID command instead.

## Read an alert

Subscribe with `/fg alerts`. Each finding arrives as one line: the player, the check key, the player's current violation level (VL) and the short case ID. Hover over it for the measured value, the bound, how many consecutive violations it took, the coverage state, the client version and the ping. Click it to open the player's staff page. A sound plays (`alerts.sound`); set `alerts.minimum-vl` above zero if you only want alerts once a player has accumulated some VL. Console alerts and the optional Discord webhook receive the plain text.

VL adds one point per finding (`response.finding-weight`) and decays per minute (`response.decay-per-minute`). `/fg vl <player>` shows the per-check breakdown, `/fg top` the highest current totals, and **Violation levels** in the menu ranks everyone with any VL. Treat it as a triage order, not a verdict: the check keys in the breakdown tell you which family to watch.

## Spectate and notes

`/fg spectate <player>` (or **Spectate player** on their page) puts you in spectator mode following them. `/fg spectate` with no name, or the same button, returns you to your previous location, game mode and flight state; both are also restored if you disconnect. Both transitions are audited. Protected players need `forgeguard.override`.

`/fg notes <player>` lists the staff notes left about a player, `/fg notes <player> add <text>` adds one (1–300 plain characters, newest 20 kept, works for offline players this server has seen or a full UUID) and `/fg notes <player> clear` removes them. Notes live in `plugins/ForgeGuard/notes.json`, show as a count on the player card and open from **Staff notes** on their page. Keep them factual; they are retained operational data.

## Investigate from the GUI

1. Run `/fg menu` and choose **Online players**. Use the page arrows or Refresh players.
2. Select a player. Their detail card shows UUID, world, position, health, game mode, ping, observation coverage and findings.
3. Open **Inventory snapshot** or **Ender Chest snapshot**. Inventory slots include storage, armor and offhand. These are copies: moving, dropping, dragging or shift-clicking display items cannot change either player's actual inventory.
4. Use **Refresh snapshot** when you need current contents. The snapshot is not a continuously synchronized view. The target must remain online, and permission/session checks run again after the inspection audit is saved.
5. Open **Player evidence** to review retained cases. A case shows measurements, bounds, context and build/configuration information. **Replay recorded finding** reproduces the observation; it does not establish that a player cheated.

Equivalent shortcuts are `/fg players`, `/fg player <name>`, `/fg inventory <name>` and `/fg enderchest <name>`.

On the supported modern recorder, a player's GUI also has **Save replay snippet** and **Visual
recordings**. A case has **Visual recording**. These provide capture/status information and direct
staff to the linked website for visual playback; the in-game menu is not a 3D replay player.

## Edit an inventory live

With `forgeguard.inventory.edit`, a player's page has **Edit inventory (live)** and **Edit Ender Chest (live)** buttons (or `/fg editinv <name>` and `/fg editender <name>`).

- The inventory editor mirrors the player's items: rows 1–3 storage, row 4 hotbar, row 5 helmet, chestplate, leggings, boots and offhand. Move, add or take items as in any chest. Changes reach the player on the next tick and the view refreshes twice a second.
- If you and the player change the same slot at the same moment, the player's item stays and your stack goes back to your own inventory (dropped at your feet if it is full). Nothing is destroyed or duplicated, and you are told which slot it was.
- The frame and controls cannot be taken. Double-click collection is disabled.
- The Ender Chest opens the player's real Ender Chest directly.
- Opening is audited (`admin.inventory.edit.opened`) and every change is summarised when you close the view (`admin.inventory.edit.applied`). Protected players need `forgeguard.override`.

## The website console

Website members see the same information and act with the same rules. The server owner decides what any website may do under `web:` in `config.yml`; each member's website role (owner, admin, moderator, viewer) narrows it further. Website roles do not grant Minecraft permissions.

- **Players** has All, Online and Offline filters for the server's known players. Live players add health, food, ping, world and coverage. The directory is bounded to 1,000 records and reports when truncated; it is not a global Minecraft account search. Offline players must have joined this server before.
- **Inventory** shows the real inventory and Ender Chest with the item catalogue. Edits are drafts until **Apply to player**. Each changed slot is checked against what the member saw, so a slot the player changed first is refused rather than overwritten, and the draft is kept for review. Items listed in `web.blocked-items` cannot be created. Moving an existing stack keeps any plugin data on it.
- **Give items** sends the chosen stacks directly to the selected player. Online delivery needs room for every stack; a full inventory keeps the delivery waiting. Offline delivery is saved on the server and retried on join and periodically. The console shows delivery history and the actual result. No copied command is needed.
- **Moderation** offers freeze, unfreeze, kick, temporary and permanent ban, and unban with a reason, using the same `admin:` limits. Website bans also work for offline players by UUID. **Travel** explicitly moves the selected online Minecraft player to another online player, or returns that player to their saved location. Protected players cannot be targeted from the website.
- **Gameplay replays** on a player profile lists retained server-recorded snippets. Online, unprotected players can be captured manually by members with moderation permission using **Save replay snippet** and a reason. **Watch gameplay replay** in a case opens its automatic clip when one was captured. Pause, scrub, change speed and choose a camera; review partial-data warnings. Saved clips can be watched after a player leaves. The viewer reconstructs nearby blocks and entity positions using simplified geometry; it cannot show the player's screen, mods or private overlays. See [Gameplay recordings](GAMEPLAY-RECORDINGS.md).
- **Recheck finding** runs the same deterministic recorded-case replay logic as the in-game evidence menu and reports whether the stored trace reproduces the observation. It is separate from visual gameplay playback and is not proof of cheating. In-game chat-alert subscriptions remain personal to the Minecraft staff account; the website has its own live findings feed.
- Website actions record the operator's email in `staff-audit.jsonl`; the request audit must succeed before dispatch. Subscribed staff are told about website inventory edits and deliveries (`web.notify-staff`).

Deliveries use a stable UUID so retrying the same request does not create a second reward. If the connection drops, use the console's history/check/retry flow, which retains the original ID and contents. A changed payload under that ID is refused. If Minecraft crashes between applying an item grant and recording completion, the delivery becomes **needs_review**: it is not replayed automatically, because player data and the delivery ledger cannot be committed as one atomic transaction. Check the player's actual inventory before making a separate grant. Keep the delivery ledger with server backups.

Each grant accepts 1–36 stacks and a note of up to 200 characters. History shows the latest 20 receipts and reports truncation. The current core allows 100 pending deliveries per player and 10,000 permanent receipts per server. Receipts are not automatically pruned: deleting them loses the duplicate-prevention history. Reaching capacity refuses further grants and requires a reviewed capacity migration, not deletion of old receipt files. An offline player's protection permissions are checked when they join; a protected player keeps the delivery blocked and receives no items.

These additions require the updated modern core and its advertised web capability flags. The portable runtime and older plugin builds do not gain these routes merely because the website has been updated. See [Version support](VERSION-SUPPORT.md).

## Review, confirm or cancel an action

Choose an action on the player's page, then a reason and, for a temporary ban, a duration. For a custom reason or exact duration use a command:

```text
/fg staff freeze <online-player> <seconds> <reason>
/fg staff unfreeze <online-player> <reason>
/fg staff teleport <online-player> <reason>
/fg staff return
/fg staff kick <online-player> <reason>
/fg staff tempban <online-player> <seconds> <reason>
/fg staff ban <online-player> <reason>
/fg staff unban <full-uuid> <reason>
```

These commands create a preview. They do not apply the action immediately. Check the target UUID, action, reason, duration and expiry. Click **Confirm exact action**, or run `/fg confirm <exact-token>` using the token shown in the preview. The default confirmation window is 30 seconds. Each token belongs to the staff member who requested it; staging a new action replaces their earlier preview.

Click **Cancel** to invalidate the staged action. Closing the inventory alone does not invalidate its command token; it remains pending until cancellation, replacement, expiry, reload or relevant session change. A stale preview, reconnect, revoked permission, protected target or failed request audit causes refusal. Review a new action instead of repeatedly reusing a stale token.

The request audit is saved before dispatch. Temporary/permanent bans and unbans also require a successful database commit. Another plugin may cancel a kick or teleport, so inspect the returned result rather than assuming a click succeeded. The legacy `/fg kick <case-id>` then `/fg kick <case-id> confirm` flow remains separate and requires the reviewed case to belong to the current player session.

## How freezing works

A freeze is a temporary investigation hold. Pure look events and communication remain available. Position-changing movement events are cancelled so the server restores the held position; covered inventory/block/item/interact actions and damage involving the frozen player are blocked, and player commands are restricted to the configured allowlist. It does not set a permanent movement-speed attribute or automatically punish a disconnect.

The default hold is 300 seconds, with a configured maximum of 900 seconds. Freeze expiry is checked every second. A reconnect to the same running plugin preserves the remaining freeze; plugin shutdown/restart clears freezes. Disabling `admin.enabled` on reload releases existing freezes and prevents new moderation requests.

By default `admin.allow-admin-teleports: true` lets server `COMMAND` and `PLUGIN` teleport causes move a frozen player. This is based on the Bukkit teleport cause, not proof that a particular command was issued by staff. Set it to false if your investigation policy needs those teleports blocked as well. Normal chat remains available. The default allowed command roots are `msg`, `tell`, `w`, `r` and `help`; inspect aliases supplied by your other plugins when changing the list.

## UUID bans and appeals

Bans from either adapter live in the shared `plugins/ForgeGuard/moderation/bans.json`. They record target UUID/name, staff UUID, reason, creation and expiry; switching between portable and modern runtimes retains them. They are ForgeGuard's own bans, not a rewrite of the server's vanilla ban list. In the modern core, use `/fg staff unban <uuid> <reason>` and confirm; portable syntax is shown by `/fg help`. Vanilla `/pardon` does not remove a ForgeGuard record.

Temporary bans expire by wall-clock time. Permanent bans have no expiry. Existing committed bans survive restarts and continue to deny login even if `admin.enabled` is later set to false; disabling new staff actions does not clear punishments. The database supports at most 10,000 active records and uses bounded background writes with atomic replacement. A failed write does not publish a new ban state. An unreadable database stops initialization rather than silently discarding bans; preserve the file and restore a known-good backup after investigating.

New player-targeted ban requests require an online target. Unban uses a full UUID and works for an offline player. This is not an IP, hardware or alternate-account ban system. Reliable UUID identity depends on the server's authentication/proxy configuration.

## Staff configuration

The modern core includes these defaults in `config.yml`:

```yaml
admin:
  enabled: true
  confirmation-seconds: 30
  default-freeze-seconds: 300
  max-freeze-seconds: 900
  default-tempban-seconds: 3600
  max-tempban-seconds: 31536000
  max-reason-length: 160
  allow-admin-teleports: true
  frozen-command-allowlist: [msg, tell, w, r, help]
  gui-reasons: ['Staff investigation', 'Confirmed rule violation', 'Repeated exploit abuse', 'Appeal accepted']
```

Use `/fg reload` after editing. Reasons must be nonempty plain text without control characters or Minecraft formatting codes. Bounds are validated; confirmation windows allow 5–120 seconds, maximum freezes up to 3600 seconds, and temporary bans up to 31,536,000 seconds. Defaults cannot exceed their corresponding maxima. Changes clear existing previews; they do not retroactively shorten committed bans or existing freeze deadlines, except that disabling administration releases freezes.

The **Detection settings** GUI edits movement mode, check toggles and numeric thresholds using validated revision checks. A stale screen or external disk edit is rejected. Guard/admin YAML fields are not part of the web configuration-save contract. Worker/storage/bridge infrastructure changes require restart.

## Behaviour checks and the response ladder

**Behaviour checks** in the menu (also from Detection settings) lists all 26 server-side checks with their coverage line and current enforcement. Clicking a check toggles it; the bottom row toggles the behaviour mode (OBSERVE records, CANCEL also cancels the offending hit, block action or move), setback (with CANCEL, movement findings return the player to their last server-verified floor) and the response ladder. Every click goes through the same audited, revision-checked configuration write as the detection settings. Thresholds are edited in `config.yml` under `behaviour:` followed by `/fg reload`.

The response ladder (`response:` in `config.yml`) is off by default and should stay off until you have watched your own server's cases for a while. When enabled, each step is `{vl: <number>, action: ...}`:

```yaml
response:
  enabled: false
  decay-per-minute: 1.0
  finding-weight: 1.0
  excluded-checks: [packet.movement-rate, timing.window, combat.attack-rate]
  steps:
    - {vl: 10, action: ALERT_STAFF}
    - {vl: 25, action: KICK, message: 'Disconnected by ForgeGuard after repeated {check} findings. Reference {case}'}
    - {vl: 40, action: TEMPBAN, seconds: 3600, reason: 'Automatic: repeated {check} findings (VL {vl})'}
```

`SETBACK` and `COMMAND` (`command: 'say {player}'`, no leading slash, run as console) are also available. A step fires once as the VL climbs past it and again only after the VL has fully decayed. Temporary bans use the same `admin:` limits, audit-before-apply and `bans.json` as staff bans and are lifted with `/fg staff unban`. Protected and bypassing players only ever produce the staff alert. Every applied step is audited as `response.<action>` in `staff-audit.jsonl`, and ladder events are announced to subscribed staff (and Discord when configured).

## Event guards and health

Event guards have their own `guards.mode`, independent of movement `protection.mode`:

| Setting | Behavior |
| --- | --- |
| `protection.mode: OBSERVE` | Records supported movement observations |
| `protection.mode: MITIGATE` | Also cancels non-finite movement packets |
| `guards.mode: OBSERVE` | Records over-budget event/book incidents; cancels none |
| `guards.mode: CANCEL` | Requests cancellation of the particular excess event or rejected book edit |

Start with both modes in OBSERVE. Inspect ordinary inventory/menu bursts, command usage, interactions and books before tuning individual `guards.rates` budgets or `guards.book-limits`. Run `/fg guards` and use **Abuse guards** in the GUI or **Server health** in the web console. [Exploit coverage](EXPLOIT-COVERAGE.md) gives every default, validated range and unimplemented area.

Capacity misses mean events were processed without guard enforcement because player tracking was full. Skipped book scans mean the edit budget was exhausted and extra metadata scans were avoided. Notification/evidence queue errors indicate incomplete persistence or delivery. Guard counters are lifetime service counters, reset on restart; reloading resets transient player budgets while preserving those counters. Recent incidents are aggregated counts, not movement replay cases.

The web console exposes these health snapshots, family thresholds and active freeze/ban counts. Its only bridge operations remain status, case retrieval, allowlisted movement configuration and reload. It cannot remotely freeze, kick, ban, execute console commands or retrieve inventory contents. Web accounts, roles, invitations, sessions and TOTP remain governed by the separate website access controls.

## Audit and operational limits

Modern staff/guard/configuration audit entries are written to `<active-data-directory>/cases/staff-audit.jsonl`, with a rotating previous file. Inventory inspections audit the request and player identity, not the item contents. Staff reasons are retained, so avoid putting credentials or unrelated personal information in them. Back up moderation and case/audit data together.

If a menu reports an unavailable action, check permissions, current player sessions, the active runtime, configuration and server logs. If health reports dropped analysis or rejected evidence, investigate capacity before treating a lack of cases as proof of clean play. This alpha has no complete combat model, general duplication proof, X-ray system, login-bot filter or network DDoS defense, and has not certified every historical Minecraft version.
