← Back to Docs

Suspicion Scoring

How the self-hosted integrity server scores a player: one running number per player that rises when checks fail and falls when they pass, with three action thresholds — warn, escalate, kick. The exact point values, thresholds and intervals are fixed defaults in the server source you host, where you can read and tune them for your title.

Spot-Check Mechanism

The integrity server does not see every operation. Instead it periodically performs spot-checks: it picks a few of the variables the client has registered and sends a challenge with a fresh nonce. The client has a short deadline to answer with the current integrity state and claimed value for each challenged variable; the server re-derives the encoding under the session key and checks that the two agree. Only challenged variables count — extra payloads are ignored, so a client cannot farm clean matches on variables it was not asked about.

Two slower timers run alongside: a periodic variable inventory, and, for sessions that opted into the per-session key handshake, periodic key rotation.

These intervals are fixed defaults in the server source. They are not configurable from the dashboard; changing them means changing the server you host.

Score Accumulation

Each player has one integer suspicion score. It starts at 0, never goes below 0, and every scored event moves it by a fixed amount defined in the server source:

-Match — a challenged variable verified (and, if it is bounded, its value was plausible). Lowers the score.
+Mismatch — the integrity state and the claimed value disagree under the session key. Raises the score the most of any single event.
+Missed spot-check — no answer within the deadline, or a challenged variable answered with an empty or unparseable integrity state (counted once per check). Raises the score, less than a mismatch.
+Implausible-but-authentic value — the integrity state verifies but the value falls outside its archetype envelope (range, monotonic, rate of change). Raises the score only when value-bounding runs in enforce mode; in the default shadow mode the event is logged and scores nothing (it is not rewarded as a match either).
-Decay — a periodic pass lowers the score of any player the server has not heard from recently, so an isolated event fades over time.

The score is accumulative: a single failed check sits well below the first action threshold, and matches in between pull it back down, so an honest player with the occasional network hiccup never approaches action while a persistent tamperer climbs steadily toward it.

Action Thresholds

After every scored response the server derives an action from the score. Whenever the action is not none, it sends the client a VERDICTmessage and the SDK hands the action to your verdict callback. The integrity server does not close the connection or ban anyone itself — what your game does on warn, escalate and kick is your decision.

None
Below the first threshold. No message is sent; an isolated mismatch stays here.
Warn
VERDICT with action warn ("Suspicious activity").
Escalate
VERDICT with action escalate ("Repeated integrity violations").
Kick
VERDICT with action kick ("Integrity violation detected").

The thresholds are fixed in the server source and are not editable from the dashboard.

False Positive Handling

+Accumulative model — a single mismatch sits below the first threshold; reaching warn takes several consecutive failed checks with nothing subtracted in between.
+Malformed reports are not mismatches — an integrity state that fails to parse (a transient desync, for example) is not scored as a mismatch; it counts as an unanswered check for that variable, which is weighted less.
+Unknown nonces are discarded — a response whose nonce the server did not issue, or has already consumed, is dropped without scoring.
+Key rotation grace — the server keeps the keys for a few recent epochs, so a report encoded just before a rotation still verifies.
+Counter resets — a monotonic counter (kills, score, XP) that resets to its starting value begins a fresh run rather than being flagged as a decrease.
+Bounding starts in shadow — implausible values score nothing until you promote the project to enforce on the server (CLOUD_BOUNDING_ENFORCE). Read the shadow logs first.
+Decay — the score fades while a player is idle, and an actively checked honest player pulls it down with each match instead.

None of this makes a false positive impossible. The consistency check itself is exact — an integrity state is either consistent with the claimed value under the session key or it is not — but the missed-check path depends on network timing, and the bounding envelope is a plausibility model you write. Keep a variable in shadow until its logs look clean.

Reading the Score

Two REST endpoints on the integrity server return a player's current score. Both require the project API key in the X-Compuon-Key header and are scoped to that project: a key for project A only sees players observed under project A, and an unknown player returns 0.

GET /v1/player/:id/suspicion → { "suspicion": 45 }
GET /v1/player/:id/status → { "varCount": 12, "suspicion": 45, "addressCount": 0 }
curl -H "X-Compuon-Key: ck_..." https://your-integrity-server/v1/player/p123/suspicion

varCountis the number of variables registered by the player's live session, or 0 if the player is not currently connected (the score still persists in server memory until it decays). addressCount is how many distinct source addresses that player has been seen from; it is reported as evidence and is never scored, since an honest client changes address on a network handover. It is recorded only for a project the server runs in key-identity mode (CLOUD_KEY_IDENTITY_PROJECTS— one API key per policed party, as in a contest or a per-seat licence, where the score is kept under the key rather than under the client-declared player id); for the default mode, where one project key is shared by every player, it is always 0. Scores are held in memory only — there is no detection history, per-variable log or export. The dashboard's detection feed is not yet fed by the integrity server; the VERDICT message and these two endpoints are the integration surface today.