Tactical Action · Architecture

Security, Compliance & Launch

A focused page within the Tactical Action Architecture documentation. The full map and every sibling page live in the Architecture hub.

9sections11 minread1diagram

On this page

V4 ships six tactical-action cells under one account, one operator roster, one currency ledger, and one progression record, across nine day-one platforms — so its security and compliance surface is not a feature, it is a precondition. A platform holder refuses a build over a missing data-safety form; a regulator fines over a deletion that fails to cascade; a competitive ladder rots the day cheating goes unanswered. The defining architectural choice this page documents is that V4 keeps that surface inside the game. Where V2 and V3 reach sideways into the sister monorepos and compose the shared @oshun/data-residency, @themis/privacy, and @aphrodite packages through thin service surfaces, V4 reimplements identity-aware compliance, residency, right-to-be-forgotten, age-gating, statement-of-reasons logging, and anti-cheat as real Unreal C++ subsystems (V4OnlineServices, V4Netcode) and Rust services (apps/v4/online-services), each guarded by a machine-checked TypeScript gate under apps/v4/scripts/. That divergence is deliberate — the enforcement seams live where the gameplay does — but it is also the first thing to state honestly, because it means the shared packages are not this product's compliance root. The section hub is ../V4_ARCHITECTURE.md.

What ships, honestly#

The compliance and anti-cheat logic is real, domain-specific code, not a policy stub. V4/ue/Source/V4OnlineServices/Private/V4ComplianceSubsystem.cpp (489 lines) is a substantive UV4ComplianceSubsystem that builds 30-day DSAR export cases and 45-day deletion cases, evaluates an under-13 / teen / adult age gate, resolves per-region data-residency rules (EU→eu-central-1, PRC→cn-north-1, US→us-east-1, each with a paired KMS region), emits DSA statement-of-reasons logs, and drives an eight-region feature-flag matrix. V4/ue/Source/V4Netcode/Private/V4AntiCheatSubsystem.cpp (187 lines) computes real behavioral-detection thresholds, a trust score, a ten-tier ban ladder, and an appeal validator. apps/v4/online-services/src/lib.rs:954 carries a right-to-be-forgotten replay scrubber (scrub_deleted_account_from_replay) that mutates pawn tracks and returns a typed ReplayScrubResult. All three are backed by tests — V4ComplianceTests/ComplianceSpec.cpp, V4AntiCheatTests/AntiCheatSpec.cpp, and the 388-line ReplayModeSpec.cpp.

Two honest qualifications run through everything below. First, V4 owns no cooked binary content. The repository is text-only; every Unreal asset exists as a .v4asset.json stand-in (~891 today under V4/ue/), as the architecture's own convention note states (V4_ARCHITECTURE.md, "Content Pipeline & Source Control"). Stand-ins carry authored intent and are what the v4-*-check gates attest to, but they cannot be cooked, profiled, or played — so any claim that needs cooked content (a real certification run, a profiled frame rate, a playable day-one build) is fundamentally un-evidenceable from this repo and must be read as forward-looking. Second, the kernel-mode anti-cheat driver and the EAC service themselves are external platform SDKs; V4 ships the config validators, detection models, routing, and ban policy that integrate with them, not the driver. The page labels each seam where it stands.

Identity, session & data security#

Identity roots in the platform, not in V4. Accounts authenticate by OAuth 2.0 against the platform identity providers (PSN, Xbox Live, Nintendo, Steam, Apple Game Center, Google Play Games) with short-lived access tokens and rotated refresh tokens, and cross-surface SSO binds the companion, wiki, roadmap, spectator, and developer-OAuth surfaces through a single v4-account realm, each with its own idle and absolute timeout. This is the same foundation documented at Auth & Identity; the in-game account-link flow (first-party primary, platform accounts link/unlink at will) is detailed in Online Services & Persistence. PII at rest is encrypted under KMS-managed keys, and the residency rules name a per-region KMS key explicitly (eu-kms-v4, prc-kms-v4, us-kms-v4) so an EU subject's keys never leave the EU control plane. AI wiki summaries are fail-closed: resolved through V4/wiki/ai-summary-policy.json, Sophia-grounded and cited, and withheld unless the request carries x-v4-ai-summary-opt-in: true — an honest opt-in seam, not a default-on data flow.

Privacy, residency & data-subject rights#

V4's privacy posture is codified in UV4ComplianceSubsystem and a set of legal manifests under V4/legal/, and it is the clearest example of the reimplement-rather-than-compose decision. The DSAR portal at support.v4.game/dsar resolves a 30-day JSON export case (BuildDsarExportCase); deletion resolves a 45-day purge case (BuildDeletionCase); both are validated for the exact regulatory windows by ValidateCompliancePolicyAsset (which fails the asset if the DSAR archive is not 30 days or the purge is not 45). Data residency is rule-driven: BuildDefaultDataResidencyRules() pins EU, PRC, and US account data to in-region hosts, and ResolveDataResidencyRule normalises CN/DE/FR/ES aliases to the correct zone, defaulting to US for the unlisted.

Right-to-be-forgotten reaches into replays specifically. When a deletion is accepted, BuildReplayScrubRequest and the Rust ReplayService::scrub_deleted_account_from_replay (lib.rs:954) clear the deleted account's identifiers from every participant pawn track, swap in Skin.Anonymous.DeletedAccount, preserve match-integrity frames, and emit a Privacy.ReplayScrub.Completed audit event — the contract is pinned in V4/legal/privacy/replay-scrubber-policy.json, which names both the C++ and Rust implementations. The scrubber's ReplayScrubResult is an honest state machine: it returns InvalidRequest on empty input, NotFound for a missing replay, and NoAccountFootprint when the account never appeared — it refuses to claim a scrub it did not perform.

Honest divergence. The shared @oshun/data-residency package (libs/shared/data-residency/src/enforcer.ts, dsr-routing.ts) and @themis/privacy (v2-data-subject-rights.ts) are real, substantive platform code — but a repository-wide search finds zero V4 imports of them (or of @aphrodite/age-verification / @aphrodite/consent-engine). V4 re-expresses the same obligations natively in the engine and the Rust tier. The upside is locality; the cost is that a deletion or residency change here does not automatically propagate through the shared cross-product DSR router the way it does for V2/V3. That is a real architectural trade-off, stated plainly rather than papered over.

Compliance, moderation & region rules#

The launch compliance matrix covers GDPR (DSAR + 30-day turnaround), CCPA (right-to-delete, 45-day purge), DSA (a statement-of-reasons log for every moderation action, built by BuildStatementOfReasons, which sets bLogged only when actor, target, reason, evidence, and statement are all present), and COPPA (a verified-under-13 path into a restricted-experience build with voice, text, UGC, and purchases all disabled). EvaluateAgeGate returns Under13RequiresFamilyLink until a guardian verifies, then Under13VerifiedRestricted; BuildDefaultParentalControlPolicy carries time-played caps, under-18 spend caps (defaulting the monthly cap to 0), and chat-default-off.

Privacy-by-design extends the launch posture into year-one operations, validated by ValidatePrivacyByDesignCoverage and the v4-privacy-by-design-check gate. Three AI DPIA summary cards are published to legal.v4.game/dpia (V4/legal/dpia-summary-cards.json: AI auto-moderation, behavior detection, and in-game commentary), each annually refreshed and each insisting human review remains required for sanctions. The sub-processor registry (V4/legal/subprocessors.json: cloud evidence storage, Perspective API toxicity scoring, Whisper transcription, Cinedubs VO) publishes before processing and notifies opt-in subscribers within 30 days of a contract change. The eight-region feature-flag matrix (BuildRegionFeatureFlagMatrix, mirrored in V4/legal/privacy/region-feature-flags.json) is enforced, not decorative: China defaults voice chat off, and CN, KR, and IN resolve to a cosmetic-only economy that disables Economy.RealMoneyAdvantage. Transparency reporting closes the loop: BuildTransparencyReport clamps moderation-action and statement-of-reasons counts to non-negative integers and points at a per-period legal.v4.game/transparency/<period> URL, and ValidateLaunchCoverage ANDs the full policy-asset validation with the privacy-by-design coverage check so a single missing DPIA card, an absent jurisdiction note, or a mis-defaulted China flag fails the whole launch-coverage assertion. Per-jurisdiction notes (per-jurisdiction-compliance-notes.json, covering EU, UK, BR, JP, KR, IN, CN plus a US state-privacy matrix) and the refund policy (V4/legal/refunds/refund-policy.json, routed to each storefront's own cancellation flow) round out the documented obligations.

Anti-cheat & competitive integrity#

The threat model for V4 is skill-cheating on the ranked tactical and battle-royale ladders, and the posture is layered. Easy Anti-Cheat is the kernel-mode default (BattlEye where EAC is not regionally certified); UV4AntiCheatSubsystem::BuildDefaultEACConfig / ValidateEACConfig validate the integration config (DA_EACIntegration requires kernel mode and protects RankedPvP + BattleRoyale). Above the driver sits real detection logic: EvaluateBehavior flags impossible recoil (≥20 shots with a recoil-control score ≥ 0.98) and wallhack-shaped visibility (≥3 hidden-target pre-aims or a wall-visibility ratio ≥ 0.35), assigning severity 6–9; RouteToAntiCheatService sends severity ≥ 8 to the anti-cheat.eac-review queue and the rest to anti-cheat.live-review. CalculateTrustScore is a concrete formula — clamp(100 − strikes·25 − investigations·10, 0, 100), low-trust pooling below 50 — so flagged accounts matchmake together rather than against clean players. BuildBanTiers returns the full ten-tier ladder (mute / match-ban / cell-ban at 1d·7d·30d, plus a permanent account ban), and ValidateAppeal makes every sanction appealable (statement ≥ 24 characters). Crucially, detection never auto-bans: ValidateLadderReplay and the human review queue mean a permanent ban requires replay evidence plus telemetry plus manual review, matching the DPIA mitigation that automated models triage but humans sanction.

DRM, code-signing & build integrity#

V4 ships no third-party DRM — Denuvo, VMProtect, and Arxan are explicitly forbidden in V4/release/drm-code-signing.json against decision record 0006-no-denuvo.md. Ownership is enforced through platform entitlement checks instead: Steam and EOS DRM, PSN title licenses, Xbox Store licenses, Nintendo eShop tickets, App Store receipts, and Google Play Integrity, each paired with a server_entitlement_sync. Code-signing is configured per platform — Authenticode via signtool (Windows), Apple notarization with hardened runtime (macOS/iOS), Google Play App Signing (AAB), and platform-holder signing on the consoles — driven by V4/release/signing/sign-artifacts.sh with secrets referenced by name, never embedded. These are honest config manifests and a real script; the actual signing happens in a restricted CI runner against secrets that do not live in the repo.

Testing, QA & certification#

Automation lives in the V4Tests module: per-module unit specs, per-cell feel tests (V4Mode*Tests/*Spec.cpp), per-system functional specs, Gauntlet end-to-end runs, and a golden-replay regression corpus under V4Tests/GoldenReplays/. The merge gate (V4/ops/launch/feel-test-merge-gate.json) requires all six cells green on the merge commit, sourced from V4TestHarnesses.cpp. Certification is documented in V4/release/certification.json — Sony TRC, Microsoft XR, Nintendo Lotcheck, Steam Deck Verified, and Apple/Google store review, each with evidence tokens and a zero blocker count — and the v4-cert-check gate enforces that a platform is counted only when status is passed/verified with ≥4 evidence items. The honest caveat from "What ships" applies in full here: these are manifest declarations of cert intent and checklist coverage, because a real TRC pass requires a cooked, bootable build that the stand-in repo cannot produce.

Launch readiness#

§94 aggregates everything above into a go/no-go, and unlike V3's deliberately red aggregate, V4's launch gate is green — but green in an honest way worth understanding. The gate is apps/v4/scripts/src/v4-launch-readiness-check.mjs, a 615-line validator that reads ~20 manifests and asserts real thresholds: the matchmaking soak holds p99 at 34.2 s under the 35 s bar at 5× concurrency (matchmaking-soak-5x.json), the Open Beta crash dashboard reads 0.079 % under the 0.1 % threshold (open-beta-crash-dedup-dashboard.json), the verified ban roster carries an ed25519 signature over reviewed entries, all seven compliance sub-gates (GDPR, CCPA, COPPA, DSA, region-rating, sub-processor, DPIA) report green, and a no-coming-soon-screens scanner walks the shipping client roots.

What makes the green honest is validateDocs: the gate requires the real-world operations milestones in §94 (the closed alpha/beta, the open beta, the launch soak, 24/7 support staffing, the 60-minute hotfix SLA, day-one cert, anti-cheat live) to be marked [~] — "real claim, not locally verifiable" — rather than [x]. Re-checking any of them to [x] without real evidence fails the gate (per the 2026-06-12 remediation note in the script). So the aggregate passes precisely because the corpus does not fabricate operations that cannot have happened before the 2026-10-01 launch. The launch manifests themselves (launch-readiness.json, with four "complete" milestones and a 30-day Watchtower rota) are forward-looking declarations the gate cross-checks against the honest backlog marks — and the whole thing sits beneath the stand-in caveat, which keeps the truly cooked claims (a played soak, a passed TRC) out of [x] reach until binary content exists.

Service lifecycle & sunset#

Launch readiness is bracketed by an end-of-life plan, because a real-money, account-bound live service carries deletion and entitlement obligations that outlast the servers. V4/release/final-polish-readiness.json declares a five-year service window (2026-10-01 → 2031-10-01) with a phased sunset: T-12-month public announcement, T-9-month entitlement export, T-6-month last-paid-content lock, T-3-month live-ops wind-down, a T-1-month window that prioritises DSAR and delete queues, and a T0 shutdown that preserves an offline mode. The guarantees are concrete — a 365-day account-data and replay-archive export window, a 45-day privacy-deletion SLA that survives shutdown, 180 days of post-shutdown support, and a public archive of the wiki, balance ledger, and roadmap final state. It is the same honesty discipline as the launch gate, applied to the other end of the timeline: the obligations are documented and owned by named services, and the dates are forward-looking by construction.

flowchart TB feel["feel-test-merge-gate<br/>6/6 cells green"] --> AGG crash["crash dedup<br/>0.079% < 0.1%"] --> AGG mm["matchmaking soak<br/>p99 34.2s ≤ 35s · 5×"] --> AGG ac["anti-cheat<br/>EAC + ed25519 ban roster"] --> AGG comp["7 compliance sub-gates<br/>GDPR·CCPA·COPPA·DSA·…"] --> AGG cert["certification.json<br/>9 platforms passed/verified"] --> AGG AGG{"v4-launch-readiness-check.mjs<br/>(615-line validator)"} todos["§94 ops milestones<br/>must be [~], not [x]"] -->|validateDocs| AGG AGG -->|"only if no fabricated [x]"| green["launch gate: GREEN"] standins["~891 .v4asset.json stand-ins<br/>no cooked binaries"] -.->|caps cooked claims| green

Where this connects#

  • Sideways: Online Services & Persistence owns the identity binding, the Rust service tier, and the replay store this page's scrubber mutates; Telemetry, Observability & Performance owns the Sentry/Prometheus/OpenTelemetry spine, the crash-dedup dashboard the launch gate reads, and the PII-handling at ingest.
  • Platform foundations: Auth & Identity is the OAuth/SSO root V4's session security composes; the shared @oshun/data-residency, @themis/privacy, and @aphrodite privacy packages are the cross-product analog V4 reimplements natively rather than wiring in — noted here so the divergence is on the record.
  • The section hub: ../V4_ARCHITECTURE.md.