The scoring engine
Seven layers, 44+ rules, and the exact math that turns them into a 0–100 score.
Layers and weights
Every rule belongs to exactly one layer. Each layer's highest-scoring fired rule (not a sum of all fired rules in that layer) contributes its weighted share to the final score:
| Layer | Weight | What it covers |
|---|---|---|
behavior | 25% | Mouse dynamics, keystroke timing, uncanny-valley detection |
device | 20% | User-Agent analysis, known-bot TLS fingerprints (JA3/JA4) |
environment | 15% | JS engine tampering, iframe/worker context mismatches |
journey | 15% | Page-view sequence, dwell time, journey confidence |
network | 10% | IP type (datacenter/VPN/Tor/CGNAT), impossible travel |
entity | 10% | Cross-request velocity, bad-actor registry matches |
session | 5% | Cookie binding mismatches, token replay abuse |
These sum to 100%. Weight distribution is a deliberate statement about where trust should come from: behavior + device + environment = 60% of the total, because a real human doing something a script can't cheaply fake is worth more than any single static signal.
Why max-per-layer, not sum-per-layer
If layer scoring summed every fired rule instead of taking the max, a single behavioral anomaly could double- or triple-count across multiple rules that all key off the same underlying signal, artificially inflating a score that's really evidence of one thing, not three. Taking the layer maximum means adding more rules to a layer never mechanically raises scores for sessions that were already going to fire the strongest one.
Deterministic vs. probabilistic rules
Rules are split into two categories that get treated differently downstream by ML fusion:
- Deterministic rules are identity facts: a User-Agent string either
matches a known automation signature or it doesn't; a TLS fingerprint
either matches a known bad client or it doesn't; a JS engine's
Function.prototype.toStringeither has been patched or it hasn't. These are exactly as reliable regardless of how much behavioral data exists for the session, so they pass through fusion at full value, ungated by data completeness. - Everything else (mouse/keyboard dynamics, journey confidence, cookie binding checks) genuinely needs an adequate sample size to be trustworthy — a session with almost no behavioral data shouldn't get to claim high confidence on a thin behavioral read. These stay gated by a completeness score.
The completeness gate ("the Golden Rule," enforced mathematically)
completeness =
0.40 if HasMouseData
+ 0.20 if DeterminismRatio > 0
+ 0.20 if HasEnvironmentData
+ 0.20 if IPType is knownIf completeness falls under a hard threshold (0.40), the final score is
capped — regardless of how high the raw probabilistic component would
otherwise be — at a ceiling below the SOFT_CHALLENGE band. A session
KaizoCore doesn't have enough evidence about can never be confidently
escalated on a guess. This is the same principle as Why KaizoCore's
"absence is never suspicious," made literal in the score formula rather than
left as a design intention.
The fusion formula
deterministic_component = deterministic_score (full weight, never gated)
probabilistic_component = (probabilistic_score × 0.85)
+ (ml_bot_prob × 100 × 0.10)
+ (if_anomaly_dev × 100 × 0.05)
final_score = deterministic_component + (probabilistic_component × completeness)The 0.85 / 0.10 / 0.05 split is a deliberate Stage A rollout weighting
— rules dominant, ML models contributing a real but conservative share while
their track record builds on live traffic. See ML fusion
for what Stage B/C promotion would look like and what has to be true before
that happens.
Escalation on top of the score
After the fused score maps to a decision band (see Decision scores), three more mechanisms can push a decision up — never down:
- Per-action thresholds — you can configure tighter or looser block/challenge thresholds per event type (login vs. checkout vs. payment often warrant different tolerances).
- Policy overrides — see The policy engine.
- The late GHOST override — high-confidence uncanny-valley behavioral
timing detected after scoring forces a hard
BLOCK, bypassing the numeric threshold entirely for the highest-confidence robotic cases.
Rule reference
The full, current list of every registered rule — ID, layer, base score, and whether it's deterministic — is in Rules reference. That list is generated from the same rule registry the engine actually runs, so it never drifts out of sync with production behavior.