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