VOIDERATION V27: STARTUP GATE + DUAL BANS + BADGUYSCENE Date: 2026-10-30 Scope: Research/planning only. No Unity, backend, dashboard, revision or production changes. Reuses V24-V26 and local source. All proposed components are unbuilt. ARCHITECTURE / STARTUP FLOW Make `VoiderationBoot` the first enabled build scene, followed by the existing Loading and Tutorial scenes unchanged. Keep the existing scene assets and their behavior intact; adjust ordering only after staging review. Boot initializes the persistent Voideration guard before loading Loading, verifies required local configuration/components, and holds progression behind a loading gate while it requests trusted session verification. Use a singleton/persistent runtime object plus scene-load observation for accidental duplicate/removal detection. A `BeforeSceneLoad` runtime initializer is a fallback/defense-in-depth if the boot scene is bypassed by ordinary scene loads; it is not tamper-proof. Flow: 1. Quest launches `VoiderationBoot`; initialize XR/login prerequisites in the compatible order, start the guard once, validate component/build/rule version. Do not let local scene checks authorize multiplayer. Show retry/status rather than blank screen on startup errors. 2. Authenticate to PlayFab using existing account path; use session ticket only for PlayFab/Worker endpoints that accept that credential. Worker derives canonical PlayFabId from verified credential or verified Meta-to-PlayFab binding; never trust client PlayFabId/username. Issue a short-lived one-time startup challenge/session response with expiry, sequence and idempotency. Do not persist a reusable “approved” client flag. 3. Trusted response: Approved/no active restriction -> continue to existing Loading then Tutorial flow. PendingReview -> BadGuyScene. Effective PlayFab or Voideration ban -> BadGuyScene with source/details. Temporary backend outage -> remain at boot with retryable service error; do not falsely label banned. Hard-fail rule -> submit incident first, receive durable receipt if available, then call `Application.Quit()` as specified below. 4. During later scene transitions, guard observes loads, verifies it remains initialized, checks expected components and reports unexpected removal. Recheck backend policy on new/re-authenticated sessions and every Photon admission, not on every scene load. On a valid ban/restriction response, route to BadGuyScene; never depend on scene routing for actual denial. Project inspection confirms the current first enabled scene is `YesNewTut`, followed by TOS, Menu and Game. Existing startup includes `Core.AsyncInitialize`, Oculus login and `AppEntitlementCheck` (which currently logs failure without stopping startup). `PhotonVRManager` may auto-join after login and `AutomaticallySyncScene` can change scenes after joining. Therefore the gate must complete before any Photon connect/join, not just before visual progression. Component requirements must be scene-specific; a global component list would falsely fail Tutorial, PVP, Sandbox and Game. Coordinate/replace existing `KickIfBanned` scene-index behavior and `Oculus_Login.HandleBan` UI so they cannot race the trusted BadGuyScene route. No current scene has the specified layout. Security boundary: Unity `VoiderationBoot`, component-presence checks, scene callbacks, checksums and `Application.Quit()` only improve honest-client startup and UX. A modified client can delete/patch them, load another scene or ignore quit. Preventing multiplayer access requires the trusted Photon authentication gate to reject all clients whose verified account has an active PlayFab ban, Voideration D1 ban or PendingReview restriction. Verify Photon custom-auth contract and disable anonymous access/remove every anonymous Connect fallback. Meta App Attestation/Quest integrity eligibility remains unverified and cannot replace backend checks. PENDING REVIEW AND DUAL BAN STATE Keep separate entities: - Incident review state: PendingReview / Approved / Dismissed (false positive). - PendingReview restriction: temporary rejoin hold, not a ban. Approval clears this hold and allows next Photon admission after backend confirms release. - PlayFab ban: authoritative PlayFab BanUsers/GetUserBans/RevokeBans record. - Voideration ban: independent authoritative D1 ban record. - Hard-fail incident: detection action only; it is not automatically either ban. Dashboard is the primary owner control center. Only owner-authenticated, server-authorized actions can approve/dismiss, apply/extend/revoke either ban, or release a PendingReview hold. Require owner re-auth, reason, duration, confirmation, idempotency and audit. A dismissal closes a false positive without banning. Voideration and PlayFab bans are independent; revoking one does not clear the other or a PendingReview restriction. Log every attempt and result. Discord is optional notification, never approval authority. HARD-FAIL POLICY / RELIABLE SUBMISSION Hard-fail is enabled only for an explicitly configured, versioned rule with high-confidence server-verifiable evidence (e.g. repeated authenticated replay of a one-use challenge). Never trigger for lag, tracking loss, normal movement, temporary network/provider errors, missed heartbeat or weak behavioral suspicion. On hard-fail: authenticated incident intake validates the session, derives player identity server-side, bounds/redacts evidence and uses an idempotency key scoped to authenticated session plus rule/event identity. Worker must atomically persist incident plus dashboard-visible status/outbox in one D1 transaction and return an explicit durable incident receipt. Concurrent retries or a lost response return the same receipt without duplicate incidents/alerts. Unity waits for that receipt only within a bounded deadline with a few backoff retries; it must not wait for Discord delivery. After receipt, call `Application.Quit()`. Dashboard can poll D1 and show the incident immediately; optional Discord notification retries separately. If offline, Worker/D1 unavailable, or no receipt by deadline, delivery is unconfirmed: do not claim logged/alerted and do not create a ban from failed delivery. Optionally retain a minimal local retry record for next launch (best effort and tamperable), show unconfirmed status, then still request Quit because the configured hard-fail rule selected that client response. `Application.Quit()` on Quest/mobile is best-effort; it is not enforcement. Backend must independently deny future admission if policy requires. Current Worker has no D1 incident intake or durable outbox; `/updateplayers` is a no-op and must not be reused. BADGUYSCENE DISPLAY SPECIFICATION One scene displays a trusted response type, not a client-selected status. Use plain text/UI text elements (no rich-text interpretation of untrusted reason), natural wrapping, scroll/fit for long reasons, and separate issuer label when relevant. Layout requirements: Normal temporary ban: Time Remaining 30 Days Ban Reason ------------ [Actual ban reason] Appeal in discord https://discord.gg/kffma6VyZd For exact runtime layout, show the time title/value on separate lines and reason title/reason on separate lines; dashed separator immediately below “Ban Reason”. The invite is plain text inside the Ban Reason section, not a separate button. Use actual reason and remaining duration computed from trusted UTC expiry; do not hardcode `30 Days` except as a rendering example. State issuing system (PlayFab or Voideration) in the reason/detail area or nearby without changing required line ordering. If both bans apply, show each ban’s issuer/reason/expiry distinctly. Permanent ban: Time Remaining Permanent PendingReview: Time Remaining Unknown Ban Reason ------------ Your account is pending review by the ScreechVR team. Appeal in discord https://discord.gg/kffma6VyZd Do not auto-create a ticket or release on Discord join/appeal. Only trusted owner action changes review/restriction state. For pending review, identify state as PendingReview in UI even though requested display title is “Ban Reason”. If reason, expiry or identity cannot be verified, show a generic unavailable/retry state, not fabricated details or false permanent ban. SECURE BAN INFORMATION / BACKEND - Worker endpoints accept only validated PlayFab SessionTicket where supported, or server-verified Meta User Proof plus verified account binding if PlayFab login is rejected. Do not accept PlayFabId/Discord username from client as lookup authority. Meta proof eligibility and existing-account mapping are unresolved; without trusted mapping, show generic provider ban message. - Photon custom auth: validate Photon token through documented PlayFab/Photon contract, derive canonical identity, check PlayFab ban + D1 ban + PendingReview restriction on each fresh auth/reconnect/quick rejoin. Photon token is not a PlayFab SessionTicket. Exact Worker proxy wire protocol/provider support is a blocking staging gate; do not guess. Fail closed with retryable service error if either state cannot be checked. No anonymous fallback or cached client allow. - Bans are enforced at next authentication; existing PUN Cloud sessions may remain connected. PlayFab ban and Worker request do not prove a targeted live kick. Client disconnect is cooperative. Do not disrupt other room members or claim kicked unless observed. - PlayFab actions call Admin BanUsers/GetUserBans/RevokeBans from Worker with Title Secret Key in server-only secret storage. D1 Voideration ban is separately committed and audited. Cross-provider actions can partially succeed; surface each status. Persist PlayFab operation intent/idempotency key before calling; reconcile uncertain timeout or D1 write failure with GetUserBans before retry, and retain all BanIds. Owner dashboard shows both systems independently. - Protect startup verification against replay with short expiry, one-use nonce, session binding, monotonic sequence and idempotency. These stop stale/replayed requests, not a modified client from obtaining fresh valid requests. FAILURE HANDLING / COMPATIBILITY - Boot required-check failure: do not enter multiplayer scenes; show specific component/config or retryable backend issue. Do not call hard-fail quit unless the configured detection rule actually fired. Product owner must decide whether offline local Tutorial is allowed; default is permit local tutorial only if it cannot reach Photon or protected services, but hold multiplayer. - Backend state unavailable: no Photon admission, no ban label, retry with bounded backoff. A persistent outage can block new multiplayer; no fail-open. Existing connected Photon sessions are not guaranteed to disconnect. - Discord unavailable: D1 incident remains; outbox retries; dashboard is primary. - Keep existing Loading and Tutorial scene assets/flows intact. Integrate only startup ordering and gate transitions after Quest staging confirms XR startup. Preserve Oculus/PCDEBUG login, inventory, currencies, purchases, `/link`, MOTD, CCU, Photon rooms/Voice, Tag/Infection, PVP, locomotion, Sandbox/welding, horror hub/LVL1-7, scene transitions and reconnects. REQUIRED INTEGRATIONS / TESTS Dependencies: first-scene/build ordering for `VoiderationBoot`; persistent bootstrap and transition checks; authenticated Worker startup/incident/ban endpoints; D1 incidents, Voideration bans and outbox; PlayFab Admin ban APIs; proven Photon custom auth adapter, anonymous admission disabled and all fallback connects removed; trusted ban display endpoint; owner dashboard operations; optional Meta proof mapping; owner policy for offline tutorial, evidence retention and hard-fail rule allowlist. Staging regression tests: 1. Quest cold launch into Boot then unchanged Loading/Tutorial; XR/Core async init, Oculus login/entitlement ordering, suspend/resume during auth, duplicate bootstrap, scene-specific component validation and scene transitions. 2. Approved, PendingReview, PlayFab-only ban, Voideration-only ban, both bans, expired/revoked state and backend outage; verify routing and Photon denial. 3. BadGuyScene exact line layout, pending text, permanent text, timed remaining time, actual reason, issuer, wrapping, overflow, invite placement; untrusted rich text rendered as plain text. Discord join/appeal does not release. 4. Auth checks on fresh login, quick rejoin, app restart, region/server switch and Voice; forged ID/username, invalid credentials and no anonymous bypass. Verify live existing session limitation without kicking other players. 5. Hard-fail allowlisted rule produces one durable incident receipt before Quit; duplicate submission is idempotent; dashboard receives it; Discord may fail without losing incident. Offline/timeout gets bounded wait, unconfirmed state, best-effort local retry and quit only because rule is hard-fail. 6. Worker/PlayFab/D1 outage, malformed response, expiry/clock edge, owner revoke, partial cross-system ban and reconciliation; no false ban, no silent allow. 7. Full feature regression for all listed existing systems and actual Quest build. Also test Photon `AutomaticallySyncScene`, join/leave ordering, duplicate manager guard, `KickIfBanned`/HandleBan race, and horror jumpscare transitions that must not strand disabled colliders. REMAINING UNKNOWNS - Can the Worker safely proxy PlayFab Photon authentication and obtain canonical identity for banned/denied accounts? Photon dashboard auth, anonymous, Voice, reconnect/quick-rejoin and denial response settings are unverified. - Exact Meta User Proof/Attestation eligibility and verified legacy account mapping for ban details when PlayFab login is rejected. - A ban-rejected PlayFab login may not provide a usable SessionTicket; D1 lookup and ban details then need independently verified identity (such as proven Meta proof/account binding). Never fill this gap with a client-supplied PlayFabId. - Which local checks/components qualify as required; hard-fail rule allowlist and whether offline Tutorial is permitted. Local gate cannot stop modified clients. - D1 deployment, Worker quotas, durable incident receipt latency and actual Quest `Application.Quit()` behavior. Delivery cannot be guaranteed offline. - Existing PUN sessions cannot be assumed kickable; only new admission is enforceable with custom auth absent a separately proven server feature. Evidence reused: V24 `research/VOIDERATION_PLAYFAB_BANS_V24.txt`, V25 `research/VOIDERATION_DUAL_BAN_V25.txt`, V26 `research/VOIDERATION_PRE_SCENE_GATE_V26.txt`, V22/V23 and local Unity/Worker source. No implementation or production changes. END OF REPORT