## ARENA BATTLE — RISK, OPERATOR IDENTITY AND BRANDING

This guide covers player identity, connection evidence, risk rules and site-specific notifications. Risk signals support staff review; they are not proof of abuse or cheating on their own.

## 1. Player identity at the source site
Send `externalId` and optional `siteUsername` through the server-side `/provider/v1/player` and `/provider/v1/launch` APIs. `externalId` is your immutable member ID; `siteUsername` is the source site's username or account label. Omit the username field if your site only uses member IDs.

For new accounts, `name` is the legacy fallback when `siteUsername` is absent. Omitting the field on an existing account preserves its previous value; supplying it updates the stored source username. The generated `publicId` (for example cio1545) remains stable for the same site + `externalId`. Derive identity from your authenticated backend session, never from browser-supplied names or IDs.

Authorized provider staff see `publicId`, source username, `externalId` and connection/device history. The operator portal shows only that site's players. Private fields are excluded from public/shared-room player responses and browser launch-ticket projections.

## 2. Connection and device evidence
The default IP is the server-observed socket peer. A proxy explicitly listed in `TRUSTED_PROXY_IPS` may supply one valid `X-Real-IP`, verified per request. Headers from unlisted peers are ignored; `X-Forwarded-For` and `Forwarded` chains are not parsed. Trusted proxies must overwrite the header from their own connection peer, and the backend port must remain private. Do not interpret an unconfigured proxy's IP as the player's address. See ACCESS-SECURITY.en.txt.

Bounded fields include browser version, operating system, device type, User-Agent, language, timezone, screen dimensions, pixel ratio and touch capacity. The device code is an installation-keyed HMAC of a random first-party browser identifier. It can be compared across sites in the same installation, but can change after storage resets or differ between profiles on the same device.

These editable signals are not hardware identity or proof of abuse. No canvas/audio fingerprint, hardware serial or location tracking is collected. New device records are retained for 90 days. Operators must disclose the fields collected and retention period in their privacy notice.

```http Player connection evidence
POST /play/:slug/api/telemetry
```

The client sends this at startup and on room changes. A full player session and allowed Origin are required. A read-only spectator ticket or another site's player session cannot create evidence.

## 3. Risk rules
Configure these in the provider console under Risk and alerts:

- `sameIp`, `sameDevice`: matching connection or browser identifiers within a room.
- `repeatedOpponents`, `historyWindowHours`: repeated battles against the same opponents within the configured window.
- `highMultiplier`: bonus payout divided by buy-in threshold.
- `highPayoutMinor`: individual bonus payout threshold, in minor units in the API and TRY in the panel. Zero disables it.
- `winRateEnabled`, `winRateMinimumBattles`, `winRatePercent`, `winRateMinReturnBps`: alert only when both win rate and total prize-to-entry return exceed their thresholds with enough completed samples. 15,000 bps means a 150% return.
- `rapidJoinCount`, `rapidWindowMinutes`: rapid room entries based on actual reservation timestamps.
- `activeRoomLimit`: simultaneous active battles; zero disables it.
- `apiErrorRate`, `apiErrorMinimum`: API error-rate threshold with a minimum sample size.
- `waitingMinutes`, `cancelWaiting`: waiting-room alerts and optional cancellation/refund for rooms that have not started.

Automatic waiting-room cancellation is disabled by default; this rule cannot cancel a started battle. Risk signals do not change balances, confiscate winnings or automatically block players.

Scans run about every 10 seconds. Identical evidence is deduplicated, and acknowledgements survive subsequent scans. Rule/evidence snapshots are stored. Each context scans at most 5,000 rooms; `coverage.truncated` and the panel warn about partial coverage when exceeded. Shorten the history window in that case.

## 4. Site-specific Telegram
Site owners use Risk and alerts in the operator portal. Provider administrators use Site risk notifications in the site detail drawer.

1. Add the bot to the destination chat.
2. Enter the bot token and numeric chat/group ID or @channel name.
3. Select warning, critical or informational severity, enable notifications and save.
4. Use Send test to confirm delivery. HTTP success alone is insufficient; the Telegram response must contain `ok=true`.

Tokens are encrypted with AES-256-GCM and never appear in read responses or audit logs. An empty token field preserves the stored token. Back up `tenant-risk-master.key` securely with the database; never include it in client packages.

Messages contain the site name/slug/ID, `publicId`, source username/member ID, room, rule and evidence summary. Other sites' private player details are redacted. Only Telegram's fixed API host is contacted, using plain text. Official Bot API: https://core.telegram.org/bots/api#sendmessage

```http Operator panel routes
GET /operator-api/risk
GET /operator-api/risk/notifications
PATCH /operator-api/risk/notifications
POST /operator-api/risk/notifications/test
POST /operator-api/risk/notifications/retry
```

A panel session cookie is required; mutations also require the same panel Origin and CSRF verification. Site scope comes from the session and cannot be changed by a query parameter.

```text PATCH fields · notation, not JSON
{enabled, botToken?, chatId, severities?, types?}
```

`types=[]` selects every type. Equivalent provider routes:

```http Provider panel routes
GET /control/api/tenants/:id/risk-notifications
PATCH /control/api/tenants/:id/risk-notifications
POST /control/api/tenants/:id/risk-notifications/test
POST /control/api/tenants/:id/risk-notifications/retry
```

Provider reads require `sites.read` + `risk.read`; mutations require `sites.manage` + `risk.manage`. The durable outbox retries up to five times and respects Telegram 429 delays. Invalid tokens or forbidden chats are permanent failures; staff can retry failed records from the panel.

Pending records are not redirected after destination, credential or filter changes. Delivery is at least once: a lost success response can produce a duplicate message, identified by its alert ID. Test delivery is limited to once per site every 30 seconds.

## 5. Site branding
Provider administrators choose Player interface accent when creating or editing a site. `accentColor` requires the exact `#RRGGBB` format and defaults to `#FF5B36`.

Player buttons, accent/surface tints and contrasting text update together. The admin palette, semantic alert colors and individual player colors remain unchanged. Iframe and file clients use the same site capabilities. Redeploy the current client ZIP for file integrations, including site-theme and player-device assets.

## 6. Ready-to-use site rules
New sites inherit platform rules. Initial thresholds: shared IP/device review enabled; 1,000× multiplier and TRY 1,000,000 bonus payout; 5 rooms with the same opponent in 24 hours; at least 10 completed battles with an 80% win rate and 150% total return; 10 joins in 5 minutes; 3 concurrent active rooms; a 20% API error rate with at least 20 requests; a waiting-room alert after 120 minutes. These are starting review thresholds, not guarantees or findings of fraud.

Operators can change their own thresholds under Risk and alerts > Edit rules. The main admin can select a site and edit its rules too. Restore defaults removes site overrides. Review rules do not change player funds. Operators cannot enable automatic room cancellation; that is a separate platform setting and cannot cancel started battles.

```http Session-scoped rules
GET /operator-api/risk/rules
PATCH /operator-api/risk/rules
GET /control/api/risk/sites/:tenantId/rules
PATCH /control/api/risk/sites/:tenantId/rules
```

```json Example threshold update
{"rules":{"highMultiplier":1500,"repeatedOpponents":8}}
```

```json Restore platform defaults
{"reset":true}
```

Reading requires `risk.read`; editing requires `risk.manage`. Writes require a panel session, matching Origin and CSRF token. An operator's site is resolved from its session. Changes are audited and apply on the next evaluation; existing alerts are retained.
