# Online Backbone & Competitive Integrity

A competitive fighting-and-racing game lives or dies on two promises that are
really one: that the netcode is fair, and that the ladder is honest. V2's online
architecture exists to keep both — to get players into a low-latency,
rollback-clean match across PC, PlayStation, Xbox, and Switch, and to make sure
the result of that match means something on a ranked ladder that cheaters,
smurfs, and throwers cannot quietly poison. This page covers the **online
backbone** — the in-engine `V2OnlineServices` subsystem and the session surfaces
it fronts (auth, friends, parties, matchmaking, ranked, replay, ghost, store) —
and **competitive integrity**: anti-cheat, the replay-hash validation that rides
V2's deterministic simulation, and the cross-play / cross-progression model that
decides who may be matched with whom and what travels with an account. The
deterministic match runtime those services wrap lives one layer down in
[Rollback Netcode & Tag-Team](./rollback-netcode-and-tag-team.md) and
[Combat: GAS, Frame Data & Determinism](./combat-system-gas-frame-data-and-determinism.md);
this page is about everything that happens _around_ the match. The honesty bar
is the project's own: where the code is a deterministic in-engine model rather
than a wired backend, the page says so plainly, because "designed, not yet
built" beats implying a shipped service. The section hub is
[../V2_ARCHITECTURE.md](../V2_ARCHITECTURE.md).

## What ships, honestly

The split here is sharp, and stating it up front keeps the rest of the page
honest — sharper, in fact, than the prose around this module usually admits.

The **client-side online surface is real Unreal C++, but it is a deterministic
_model_, not a wired backend.** `V2/ue/Source/V2OnlineServices` ships a
`UV2OnlineServicesSubsystem` (a `UGameInstanceSubsystem`,
`V2OnlineServicesSubsystem.h`) over a ~25k-line type library
(`V2OnlineServicesTypes.cpp`) and a ~20k-line Blueprint library
(`V2OnlineServicesBlueprintLibrary.cpp`). It is the in-engine seam every menu,
lobby, and matchmaking screen calls, and it is substantial. But its `Build.cs`
declares exactly three dependencies — `Core`, `CoreUObject`, `Engine`. There is
**no `OnlineSubsystem`, no EOS SDK, no `HTTP`/`Json`, no `FSocket`** anywhere in
the module. What the C++ actually does is build configuration structs
(`BuildDefault…Config`), _validate_ them (`Validate…`), _plan_ operations
(`Plan…Operation`, `Resolve…Request`), and fold the results into a large
`FV2OnlineServicesRuntimeSnapshot` of counters and readiness flags. The "EOS /
Steamworks / GOG Galaxy / PlayStation / Xbox" surfaces are config-and-validator
pairs with operation _planners_ — and the console ones are even named honestly:
`FV2PlayStationSdkStubConfig`, `FV2XboxGdkSdkStub…`. This is precisely the
"build a POD struct, never transmit" shape the sister
[V5 backbone](../../V5/architecture/persistence-online-and-crossplay.html)
flagged before V5 replaced it with a real `FHttpModule` transport; **V2 has not
yet replaced it.** The model is real, deterministic, and heavily tested; the
wire is not in this module.

The **real TypeScript in `apps/v2` is the spine _around_ the backbone, not the
backbone itself.** There are 91 service packages — but they are the live-ops,
telemetry, trust-and-safety, AI, and identity tiers (`season-pass-service`, the
`telemetry-*` family, `kuanyin-*` / `themis-*` moderation, `iris-*` / `isis-*` /
`psyche-*` AI, `nous-anti-cheat-classifiers`, `oshun-identity-binding`,
`cross-product-entitlement`). **None of them is a session-backbone service**:
there is no `auth`, `matchmaking`, `ranked`, `replay`, `friends`, `party`,
`lobby`, or `store` package. That backbone is specified as a gRPC surface under
`libs/proto/v2/online/` — which **does not exist in the tree** — so the method
signatures below are the designed contract, not a generated stub. The kernel
anti-cheat client at `V2/ue/Plugins/V2AntiCheat/` is **likewise absent** (the
present plugins are `V2AICommentary`, `V2AdaptiveAI`, `V2AssetLinter`,
`V2Editor`, `BellonaUnrealEditor`).

The one integrity claim that is **architecturally real today** is the one that
needs no backend at all: because the match runs on a deterministic,
integer-frame simulator, the server can re-simulate from inputs and compare a
hash. That check rides the determinism the engine already guarantees — and it is
where this page's honesty pays off.

## The online backbone

### A deterministic in-engine service model

`V2OnlineServices` is best understood as the _shape_ of the online backbone
expressed in validated, deterministic C++. Each session surface is a triple: a
config builder, a validator, and — where an operation is involved — a planner
that turns a typed request into a typed result without touching a socket. The
platform-abstraction layer is the clearest example:
`BuildDefaultPlatformSdkAbstractionSpec` → `ValidatePlatformSdkAbstractionSpec`
→ `ResolvePlatformSdkRequest`, with provider-specific siblings
`PlanEosSdkOperation`, `PlanSteamworksSdkOperation`,
`PlanGogGalaxySdkOperation`, and the explicitly-named
`PlanPlayStationSdkStubOperation` / `PlanXboxGdkSdkStubOperation`. The EOS
"baseline" is enforced as a _validation rule_, not a link dependency:
`EV2OnlineBackendProvider::EOS` must bind the PC `OnlineServicesEOS` subsystem,
and a valid backend requires EOS-on-PC plus Sony, Xbox, and Switch shims
(`V2OnlineServicesTypes.cpp:1108–1155`) — so the topology the monolith promises
is checked, even though nothing dials out. The whole runtime is observable
through `UV2OnlineServicesSubsystem::CaptureRuntimeSnapshot()`
(`V2OnlineServicesSubsystem.cpp:3729`), which renders the entire backbone —
friends, parties, matchmaking, ranked seasons, replay theater, moderation,
fleet, server health — into one inspectable `FV2OnlineServicesRuntimeSnapshot`.
That snapshot is what the automation suite asserts against, and it is why the
model is testable without a server.

Enums anchor the surface: `EV2OnlineAuthState` (`V2OnlineServicesTypes.h:7`),
`EV2MatchmakingTeamRole` (`:159`), `EV2PlatformFamily` (`:392`),
`EV2OnlineBackendProvider` (`:421`), and `EV2OnlineInputMethod` for input-class
pairing. Gameplay code never branches on platform — it asks the subsystem and
reads the snapshot.

```mermaid
flowchart TB
  subgraph Client["V2 client · Unreal C++ — deterministic model, no transport"]
    SUB["UV2OnlineServicesSubsystem<br/>config · validate · plan"]
    SNAP["FV2OnlineServicesRuntimeSnapshot<br/>CaptureRuntimeSnapshot()"]
    SUB --> SNAP
  end
  SUB -. designed gRPC · libs/proto/v2/online absent .-> GW[API gateway / EOS baseline]
  GW --> AUTH[auth] & FR[friends · parties] & MM[matchmaking] & RANK[ranked · leaderboards] & REP[replay · ghost] & ST[store]
  MM --> SK[(Glicko-2 / TrueSkill2 profile defaults)]
  RANK --> SK
  REP --> OBJ[(object storage)]
  SUB -. emits v2.match.replay.hash .-> DET{{re-sim 1% · compare state hash}}
  DET -->|drift greater than 0| REVIEW[manual review]
  SUB -. publishes v2.* .-> EB[("@oshun/event-bus")]
  EB -. real TS consumers .-> CONS[themis · kuanyin · maat · iris · nous-anti-cheat-classifiers]
  KERNEL["V2AntiCheat kernel plugin — absent"] -. planned .-> AUTH
```

### The session surfaces and the event-bus contract

The subsystem fronts the full session set: **auth** (platform-token sign-in
exchanged for a V2 session, with refresh), **friends & presence** (including a
cross-platform unified friends list that resolves identities and de-duplicates
aliases), **parties** (≤ 8, the unit matchmaking submits on a player's behalf),
**matchmaking** (per-mode queues, below), **lobby** (custom rooms and the Battle
Hub), **ranked / leaderboards** (seasonal, per mode), **replay cloud & ghost
store** (`UploadReplayFileToCloud`, `V2OnlineServicesSubsystem.cpp:926`, plus
share-by-code and Tekken-ghost export), and **store** (the cosmetic catalogue,
detailed in the live-ops sibling).

The backbone's _integration_ contract is event-bus-native by design. The
monolith specifies the lifecycle topics it publishes —
`v2.player.session.started/ended`, `v2.match.ended`, `v2.match.replay.hash`,
`v2.player.reported`, `v2.cosmetic.purchased`, `v2.matchmaking.ticket.completed`
— and the cross-domain signals it consumes — `themis.appeal.resolved`,
`maat.balance.recommendation`, `iris.commentary.generated`,
`kuanyin.action.taken`. The honest seam: the C++ model does not itself publish
to a bus (it has no transport); the live publication rides the platform
`@oshun/event-bus`, and the _consumers_ are the real TS services in `apps/v2`
(themis, kuanyin, maat, iris). This is what lets moderation, balance, and AI
commentary act on match outcomes without V2 reaching into their databases.

### Matchmaking and the ranked ladder

Matchmaking is the backbone's most fairness-sensitive job, and the model carries
it as data plus deterministic policy. A ticket is an `FV2MatchmakingTicket`
submitted through `SubmitMatchmakingTicket(…)`
(`V2OnlineServicesSubsystem.cpp:342`); each queue is **per-mode** (ranked 1v1,
2v2 tag, FFA, the racing modes) and each player carries an
`FV2MatchmakingSkillProfile`. That profile is a genuine dual-model record with
the _canonical_ default constants: TrueSkill **μ = 1000, σ = 83.333** and
Glicko-2 **rating = 1500, RD = 350, volatility = 0.06** — the same constants
Glickman's reference uses and the same family the platform's `@oshun` rating
services use elsewhere. `HasExplicitSkillProfile`
(`V2OnlineServicesTypes.cpp:774`) treats any deviation from those defaults (or a
non-zero placement-match count) as "this player has played," which is how
placement-vs-established is told apart. Role balancing is real logic, not a
flag: `ContainsPointAndPartnerRole` requires a `Point` plus an `Assist` /
`Anchor` / `Support` for tag and FFA team formation, and the snapshot exposes
`bHasRoleBalancedFourPlayerQueue`. Region weighting, a ping cap, and
search-radius expansion over wait time are modeled as
`bRegionAwareMatchmakingReady`, `LastRegionAwareMatchmakingPingMs`,
`bLastRegionAwareMatchmakingWithinPing`, and `bLastMatchmakingUsedExpansion`.

The honest qualification: this is a **skill-and-policy data model with
validators**, not a live rating _solver_. Unlike the V5 backend — which runs an
actual Glicko-2 update with an Illinois root-find on the volatility step — V2's
module stores the profile and its defaults and records results.
`RecordRankedMatchResult` (`:681`) delegates to `ApplyRankedMatchResult` and
copies the resulting skill into the ladder entry rather than re-deriving a
rating from a worked formula. The seasonal ladder on top is modeled in depth:
`ApplyRankedSeasonReset` (`:747`), a hidden-MMR policy
(`bRankedSeasonHiddenMMRReady`, asserted to keep hidden MMR never-shown and to
split the primary and secondary skill models), a unified cross-platform MMR pool
with cross-platform leaderboards, placement, promotion/demotion thresholds, and
a per-season reset. The designed **SLOs** are concrete enough to test against
once the backend exists: ticket **p50 ≤ 12 s, p99 ≤ 35 s** under 5× expected
launch concurrency, auth **p99 ≤ 200 ms**, replay upload **p99 ≤ 8 s** for a
10-MB replay, and ≥ 99.9% per-region availability. One correction to earlier
drafts of this page: the ranked/matchmaking _tuning_ does **not** live in
`V2/balance/online` — that directory holds only
`world-boss-community-raid.json`. The matchmaking defaults are the C++ constants
above, and the tag-pairing curves live in `V2/balance/tag/`.

## Competitive integrity

Integrity is defended in depth, and — critically — **the load-bearing line of
defense is the one that is architecturally real.** Because the match runs on a
deterministic, integer-frame simulator (see
[Rollback Netcode & Tag-Team](./rollback-netcode-and-tag-team.md)), the server
can do what most fighting games cannot: **re-simulate a match from its inputs
and compare the result hash.** Every match emits a golden-replay hash on
`v2.match.replay.hash`; the design re-runs ~1% of matches end-to-end on a Linux
validator pool, and any non-zero frame drift flags manual review. The runtime
snapshot already carries the gate result
(`bLastRankedReplayDeterminismGatePassed`). That check needs no kernel driver —
only the determinism the engine guarantees — which is why it is the integrity
claim this architecture can stand behind today.

The other tiers are real **as validated contracts and modeled state**, and the
test surface here is genuinely large:
`V2/ue/Source/V2Tests/Automation/OnlineServices.Module.spec.cpp` carries **736**
assertions, and `V2Tests/Private/Online/` holds **53** dedicated contract specs.

- **Server-side input/state validation.** Input-rate sanity (≤ 180 inputs/s,
  bursts > 240 flag) and per-ability gameplay-effect whitelisting, exercised by
  the `ServerMovementValidation`, `ServerHitValidation`,
  `ServerDamageValidation`, `ServerEconomyValidation`, `SpeedHackDetection`,
  `AimbotDetection`, `MovementHackDetection`, `WallhackMitigation`, and
  `StatisticalAnomalyDetection` specs. These ride the same authoritative path
  the netcode owns, and a fabricated effect application invalidates the match.
  Modeled and tested; the live server that would run them is the absent backend.
- **Kernel client anti-cheat.** EAC primary / BattlEye fallback on PC,
  platform-native anti-tamper on console (PSN ban-list, Xbox TruePlay, Switch
  NEX). This is the `V2/ue/Plugins/V2AntiCheat/` surface that **is not present**
  — but the _client-signal contracts_ are modeled and contract-tested
  (`DriverIntegrity`, `ProcessScanner`, `MemoryIntegrityScanner`,
  `OverlayHookDetection`, `HardwareFingerprint`,
  `ThirdPartyAntiCheatIntegration`, and `AntiCheatModeOptIn` /
  `MinimalFootprint` / `ModuleObfuscation` / `SelfUpdate` / `ReportSystem`),
  backed by `ClientHeartbeat` and the `FairPlay*` snapshot counters
  (`FairPlayDetectionSignalCount`, `HwidBanCount`, `FairPlayForensicLogCount`).
  Treat the kernel driver as the planned client tier, not a shipped one.
- **ML cheat classifiers.** `nous-anti-cheat-classifiers` (real TS) over
  `@nous/training` + `@nous/safety` — smurf, win-trading, coordinated-throw,
  geographic-anomaly. Its governing rule is the honest one: classifier output
  **can prioritise human review but cannot issue automatic discipline and cannot
  touch rollback frames** (`bLastSmurfBlockedRankProgression`,
  `bLastTournamentVpnBlocked` are queue/priority signals, not bans).
  Model-driven moderation never silently bans, matching the platform's
  review-only, appealable posture and the `@oshun/audit-platform`
  forensic-retention contract.

Discipline, shadow-bans, and appeals are modeled (`FairPlayBanSystem`,
`FairPlayShadowBan`, `FairPlayBanAppealWorkflow`, `ReplayCheatReview`,
`TrustedPlayerProgram`) and route out to the shared trust-and-safety plane —
Themis (`themis-dispute-resolution`, DSA Statement-of-Reasons) and Kuanyin —
over the event bus, so a ban is auditable and reversible by the same machinery
that governs every Oshun product. Rage-quit escalation (5-minute → 30-minute +
50 points → 24-hour ranked ban + 150 points) is carried as
`bLastRageQuitPenaltyEscalated`.

**Edge cases and failure modes**

- **Unconfigured or malformed backend.** Every operation returns through an
  `OutFailureReason` seam; an invalid ticket or backend config fails the
  validator loudly rather than silently "succeeding" — a fail-loud surface, not
  a fabricated ack.
- **Replay determinism drift.** A re-sim mismatch surfaces as
  `bLastRankedReplayDeterminismGatePassed = false` and routes to
  `ReplayCheatReview`, never an automatic ban.
- **Console with no kernel driver.** The SdkStub path validates platform-native
  anti-tamper bindings (`PlayStationSdkStub`, `XboxGdkSdkStub` specs) instead of
  asserting an EAC driver that cannot exist on console.
- **Classifier false positive.** Output prioritises a review queue; the appeal
  workflow (`FairPlayBanAppealWorkflow`) is the only path to discipline, with a
  ≤ 0.5%-overturn threshold as the model-retrain trigger.
- **Cross-process hash drift.** Mitigated upstream by the netcode's stable,
  content-based state hash, so a regression surfaces as a golden-replay mismatch
  in CI rather than a desync — or a false cheat flag — in the wild.

## Cross-play & cross-progression

Cross-play decides _who can match whom_; cross-progression decides _what travels
with the account_. Both are policy-rich, and both are modeled as validated state
in the subsystem (`bCrossPlayPolicyValid`, `bCrossProgressionSnapshotValid`)
with the implementations specified as the backend services above.

**Cross-play** is on by default for ranked 1v1, 2v2 tag, custom lobbies, the
Battle Hub, and World Tour across PC, PS5/PS5 Pro, XSX, and Switch 2, with
per-platform system opt-out honoured at session start (toggle changes
mid-session never affect the current match —
`bLastCrossPlatformMatchmakingOptOutRespected`). The subtle part is
**input-method pairing**: a ticket carries an `EV2OnlineInputMethod`, and
matchmaking compares `TicketInputMethod` against `CandidateInputMethod`
(`V2OnlineServicesTypes.h:7353`), so KBM, gamepad, fight-stick, fight-pad,
arcade-stick, and adaptive-controller classes can be paired or segregated per
mode. Cross-class is opt-in in ranked and default-on in unranked, and adaptive
controllers are always opt-in for both sides, so accessibility hardware is never
forced into a competitive mismatch. The iOS/Android companion is explicitly
**read-only and not a play surface**. The `CrossPlatformSocial` spec covers the
unified friends list, cross-platform party/lobby, and the central-server-routed
voice (native voice disabled, moderation enabled) the platform TRCs require.

**Cross-progression** roots every player in one identity. `@oshun/identity` is
the single account root; per-platform shadow accounts (PSN, Xbox Live, Nintendo
Account, Steam) bind to it. The real TS composition is `oshun-identity-binding`
over the shared `@oshun/identity` contract, mirrored in-engine as
`FV2OshunIdentityAccountBinding`, with re-binding gated behind a 30-day cool-off
and a TOTP step. The subsystem models the unified identity service
(`bUnifiedPlayerIdentityServiceValid`, internal-id-keyed so display names stay
distinct from platform usernames), cross-platform progression sync
(`CrossPlatformProgressionLinkedPlatformCount`), cross-platform ban
synchronisation (`bCrossPlatformBanSynchronizationSystemValid` — an Oshun-side
ban applies everywhere, a platform-side ban stays on that platform), and the
account-data privacy plane (`bAccountDataPrivacyComplianceSystemValid`, with
DSAR export and deletion propagated to every linked platform). Shared state
spans profile, the Crowns currency ledger (with per-platform IAP credit kept
separate for store-compliance reasons), cosmetic inventory, fighter unlocks,
ranked rank, Battle Pass progress, and the single-player career saves; conflict
resolution is last-write-wins for non-cosmetic state and union-of-unlocks for
cosmetic and fighter unlocks. Platform-only entitlements — a disc-bundle
cosmetic that cert forbids transferring — are verified through
`PlatformEntitlementVerification` and the real `cross-product-entitlement`
service, and region-locked cosmetics are region-stamped so a cross-region
account sees them _locked_ rather than seeing the wrong variant. The identity
root is the platform's, not V2's — which is exactly why a ban or a deletion
request resolves consistently across every surface a player touches.

## Where this connects

- **Down to the match:**
  [Rollback Netcode & Tag-Team](./rollback-netcode-and-tag-team.md) and
  [Combat: GAS, Frame Data & Determinism](./combat-system-gas-frame-data-and-determinism.md)
  — the deterministic sim and stable state hash the replay-hash integrity check
  depends on.
- **Sideways to live-ops:**
  [Live-Ops, Store, Progression & Community](./live-ops-store-progression-and-community.md)
  — the store, season-pass, and player-compensation services that share the
  backbone and the event bus.
- **Sideways to esports:**
  [Esports, Companion & AI Services](./esports-companion-and-ai-services.md) —
  tournaments, the spectator/companion surfaces, and the `@nous` AI services.
- **Operability & assurance:**
  [Telemetry, Performance, Testing & Release Gates](./telemetry-performance-testing-and-release-gates.md)
  — reliability scores, network-diagnostics stamps, and the CI determinism gate
  behind the replay-hash check; and
  [Security, Compliance & Sister-Monorepo Integration](./security-compliance-and-sister-monorepo-integration.md)
  — the cross-play / cross-progression and anti-cheat cert constraints.
- **Platform foundations:** [Contracts](../../platform/contracts.html),
  [Auth & Identity](../../platform/auth-identity.html), and the
  [BFF & gateway](../../platform/bff-gateway.html) tier the V2 services compose.
