# Operations, Rollout & Launch

```mermaid
flowchart LR
  Candidate[Versioned client world content and service candidate] --> Gates[Functional accessibility quality safety rights and security gates]
  Gates --> Platform[Platform cook store certification and patch readiness]
  Gates --> Region[Residency provider legal and locale readiness]
  Platform --> Capacity[World pixel-streaming voice and delivery capacity]
  Region --> Capacity
  Capacity --> Cohort[Staged account tenant region and client-tier cohort]
  Cohort --> Observe[SLO telemetry support receipts and incident posture]
  Observe --> Expand[Controlled rollout expansion]
  Observe --> Rollback[Rollback takedown or tier fallback]
```

Launch is a matrix, not one boolean. Each client tier, platform, region, tenant,
provider, and capability enters only after its gates and can be independently
held, degraded, or rolled back.

V3 — the **Lilith Metaverse** — is not one product that ships once. It is three
tenants (Tara, Saraswati, Lilith Commons) across four client tiers and nine
certification platforms, opening **region by region** under a different rating
board, residency rule, and music-rights clearance in each one, staffed by a 24×7
trust-operations org, and held back from "go" by a gate that refuses to go green
while any of those disagrees. The operational question is therefore not "does
the feature work?" but "is _this_ tenant cleared in _this_ region for _this_
device, with operators on shift to answer a report in the user's language, and
is the launch gate honestly green?" This page is the answer: how one identity
follows a user across web, mobile, and VR (**cross-platform &
cross-progression**); how GA opens in wave-1 regions and routes everyone else to
a waitlist (**region rollout**); how the **operator staffing model** scales from
a lean day-one pool to steady state; and how **launch readiness** aggregates all
of it into a single, unforgeable go/no-go that today reads — correctly —
**red**. Each claim below is pinned to the code that enforces it, or labelled
honestly where the code is a policy artifact rather than a runtime. The
enforcement spine it rides on — observability, eval gates, performance budgets,
security — is its architecture companion
[../architecture/observability-performance-security-and-launch.md](../architecture/observability-performance-security-and-launch.md);
the device ladder it routes across is
[./client-tiers-fidelity-stadium.md](./client-tiers-fidelity-stadium.md); the
accessibility, localization, and QA gates a region must clear are
[./accessibility-localization-quality.md](./accessibility-localization-quality.md).
The feature hub this page belongs to is [../V3_features.md](../V3_features.md).

## What ships, honestly

The **identity bridge is real and account-authoritative.**
`bindV3AvatarToV1Account` (`libs/v3/lilith-identity-bridge/src/index.ts`) binds
a V3 avatar to the V1 Oshun account id (`v1UserId`), writes it to the V1 profile
field `v3.activeAvatarId` with `persistedToV1Profile: true`, and emits a
`v3.account_avatar.linked` audit event — there is no V3-private account store.
The canonical single-account authority is `@oshun/identity` itself
(`V2OshunIdentityAccountState.sourceOfTruthPackageName === '@oshun/identity'`,
with `validateV2OshunIdentityAccountState` asserting
`platformAccountsBindToSingleOshunAccount`).

The **region router is a real two-layer decision, typed and tested.** The shell
BFF availability gate `resolveV3LilithLaunchDecision`
(`apps/oshun/bff/src/routes/v3-lilith-launch.ts`) answers "is this region open
and this tenant cleared here?" over a typed region/tenant matrix; the per-region
**rules engine** `evaluateV3PerRegionRules`
(`libs/v3/lilith-identity-bridge/src/per-region-rules.ts`) applies five
jurisdiction profiles' fan-token, age, content-rating, and residency rules and
returns an `allow | adapt | block` decision. Both are exercised by report
builders that assert the decisions match expected fixtures, and both back green
standalone gates (`verify:v3 region-rollout-compliance`,
`verify:v3 per-region-rules`).

The **operator staffing model and GA-week rota are authored machine-readable
artifacts** (`V3/operations/operator-staffing-model.json`,
`V3/operations/on-call-rota-ga-week.json`) — pools, SLAs, language coverage,
incident-commander rota, and a green pager test — not prose promises.

Two honest qualifications carry the page. **First**, the staffing/rota artifacts
read `green` _standalone_, but the **aggregate** launch-readiness run currently
records `operator-console-staffed: fail` and `operator-pools-day-one: fail`; the
page reports the aggregate, not the more flattering standalone file. **Second**,
the launch-readiness gate as a whole is honestly **red — 30 of 41 constituent
verifiers passing, `gaReady: false`** — and that red is the point: the gate is
wired so its green cannot be faked.

## Cross-platform and cross-progression

V3 has no platform-specific account and no platform-specific progression. A user
is one identity everywhere, and the code makes "everywhere" concrete.

### One account, bound to the V1 Oshun identity

Every V3 binding is keyed by `v1UserId`. `bindV3AvatarToV1Account` refuses to
proceed without one (`errorCode: 'missing-v1-user'`), and on success writes the
active avatar into the V1 profile (`profileField: 'v3.activeAvatarId'`,
`persistedToV1Profile: true`) so the V1 account — not a V3 shadow record — is
the source of truth. `v3AvatarIdVisibleInV1Profile` then confirms an avatar is
visible from the V1 side only when both the active-avatar pointer _and_ a
persisted binding agree. Upstream, `@oshun/identity` enforces the invariant that
matters for cross-progression: a platform account binds to **exactly one** Oshun
account (`validatePlatformBinding` pushes an error if
`binding.linkedOshunAccountId !== oshunAccountId`), so two headsets cannot
silently fork one player into two progressions.

### Headset account linking — Quest, Vision Pro, PSVR 2

The VR platforms link through a typed OAuth bridge.
`V3_SUPPORTED_OAUTH_BRIDGE_PLATFORMS` is exactly
`['quest', 'vision-pro', 'psvr2']`, and `v3OAuthBridgeIssuerForPlatform` pins
each to its real issuer — `auth.meta.com/quest`, `appleid.apple.com/vision-pro`,
`ca.account.sony.com/psvr2`. The bind path fails closed on two distinct
dishonest inputs: an unrecognised platform (`unsupported-oauth-platform`) and an
account whose `issuer` does not match the platform's canonical issuer or that
lacks a verified access-token proof (`oauth-account-not-verified`). The headset
issuer's subject is mapped to the V1 account and the link is persisted to the V1
profile and audit-logged — exactly the "audit-logged" link the feature canon
promises.

### Server-authoritative progression

State authority lives on the Rust world server, not the client, which is _why_
switching devices cannot diverge: a ticket consumed on desktop is consumed on
the Quest because both read and write the same authoritative shard (the interest
and capacity model is in
[./world-rooms-presence-multiplayer.md](./world-rooms-presence-multiplayer.md),
and the cross-tier authority rule — authority sees only gateway RTT, never the
video path — is in the
[architecture companion](../architecture/observability-performance-security-and-launch.md)).
The identity bridge is the persistence seam for the parts that are _profile_
state (active avatar, linked headsets, operator display-name overrides); the
broader "wardrobe / follow lists / subscriptions / ticket inventory / Arete
continuity all follow the user" claim is a **server-authority property of the
world server**, honestly labelled here rather than re-implemented in the bridge.
One operator-facing seam closes the loop: `applyV3RealmDisplayNameOverride` lets
a moderator rename a user's realm display name with the change
`writtenToV1AuditLog` and `visibleToOperatorConsole` — cross-progression and
operations meet at the V1 audit log.

## Region rollout strategy

GA does not mean global. V3 opens in **wave-1 regions**; everyone else is routed
to a waitlist, and the wave structure is encoded, not aspirational.

### The wave structure, in code

`resolveV3LilithLaunchDecision` carries a region-profile table whose `status`
field is the rollout gate:

| Wave / status                | Regions (region id)                   | Code status                  |
| ---------------------------- | ------------------------------------- | ---------------------------- |
| **Wave 1 (GA, `open`)**      | US-CA, Germany, UK, India, Brazil     | `open`                       |
| **Wave 2 (planned)**         | South Korea (`kr`), GCC block (`gcc`) | `wave-2-plan`                |
| **Wave 3 (partner project)** | Mainland China (`cn-mainland`)        | `partner-of-record-required` |
| **Wave 3 (prohibited)**      | Russia (`ru`)                         | `sanctions-prohibited`       |

Any region whose `status !== 'open'` — or any wave-1 region whose requested
tenant is not `availableAtGa` — returns `tier: 'regional-waitlist'` with a
landing URL of the form `/v3/landing?mode=regional-waitlist&region=…&tenant=…`.
This is currently a routing state, not a persisted signup flow. Because no
consent, delivery, DSAR, or durable lead authority is configured,
`POST /api/v3/lilith/launch/waitlist` fails closed with
`503 regional_waitlist_not_configured` and `emailStored: false`; the legacy
record lookup always returns 404. The machine-readable mirror of this matrix is
`V3/regions/tenant-region-availability.json`, and the whole thing is gated by a
green `verify:v3 region-rollout-compliance`.

### Per-tenant rollout differs from the wave

Saraswati Stage opens in fewer regions than Tara and Commons, because music
rights clear jurisdiction by jurisdiction.
`V3_LILITH_TENANT_REGION_AVAILABILITY` encodes it precisely: all three tenants
are `ga` in US-CA, Germany, and UK, but in **India and Brazil** Saraswati is
`availableAtGa: false`, `mode: 'waitlist'` ("Music-rights and lyric-tone review
remain gated…"), while Tara and Commons open normally. A user in Mumbai gets
Tara at GA and a Saraswati waitlist sign-up on the same screen — the router
resolves tenant availability independently of region openness. (Saraswati's
rights model is detailed in
[./saraswati-economy-voice-genre-rights.md](./saraswati-economy-voice-genre-rights.md).)

### Per-region prerequisites, made executable

The "must be cleared before a region opens" checklist is not a doc — it is the
five-profile rules engine `evaluateV3PerRegionRules`. Each
`V3PerRegionJurisdictionProfile` binds a region to its rating authority,
fan-token policy, age floor, content-rating ceiling, and residency zone:

| Profile | Rating authority | Fan-token policy     | Max content rating | Residency zone |
| ------- | ---------------- | -------------------- | ------------------ | -------------- |
| `us-ca` | ESRB/IARC        | `native-token`       | `mature-18`        | `us-west`      |
| `de`    | USK              | `v1-account-benefit` | `saraswati-16`     | `eu-de`        |
| `gb`    | BBFC/IARC        | `v1-account-benefit` | `saraswati-16`     | `uk`           |
| `in`    | IARC India       | `v1-account-benefit` | `teen`             | `in`           |
| `br`    | ClassInd         | `v1-account-benefit` | `saraswati-16`     | `br`           |

The engine returns `block` if any of age, content-rating, residency, or
fan-token fails; `adapt` when a rule is satisfied via fallback (Germany's
`native-token` request becomes a `v1-account-benefit` delivery —
`adaptationApplied: true`); and `allow` otherwise. Residency is genuinely
pinned: `passed` requires both `storageResidencyZone === requiredResidencyZone`
and the compute zone to be in the profile's `allowedComputeResidencyZones`, so a
German user's storage and compute stay in `eu-de`. This composes the shared
`@oshun/data-residency` machinery — `resolveHomeZoneFromClaim`
(`libs/shared/data-residency/src/home-zone.ts`) and the enforcer — whose GDPR
Art. 9 special-category branch (blocking a `voice_profile` or `avatar_pack` from
leaving its zone) is documented in the
[architecture companion](../architecture/observability-performance-security-and-launch.md).
`buildV3PerRegionRulesJurisdictionReport` asserts all five profiles are covered
and every fixture's decision matches — the gate fails if a jurisdiction is
dropped or a rule silently stops applying.

## Operator staffing model

Lilith Operator Console actions are staffed by a mix of shared and per-tenant
pools, lean on day one and ramping against measured concurrency. The model is a
checked-in artifact (`V3/operations/operator-staffing-model.json`) with a
GA-week rota beside it (`V3/operations/on-call-rota-ga-week.json`), both gated
by `verify:v3 operator-runbooks-on-call` (§73).

### Minimum viable launch (day one)

Sized for ~5 k DAU growing to ~25 k across wave-1 over 90 days, ~30 staff total:

| Pool                           | Day-one staffing                                         | SLA / coverage                         |
| ------------------------------ | -------------------------------------------------------- | -------------------------------------- |
| **Lilith-Safety (shared)**     | 16 operators, 3 shifts — APAC 5 / EU 5 / NA 6            | 24×7 follow-the-sun                    |
| **Tara editorial**             | 4 (NA + EU split)                                        | instructor verification ≤ 5 business d |
| **Saraswati editorial**        | 4 specialists                                            | track ≤ 3 d; concert calendar ≤ 1 d    |
| **Commons editorial**          | 2                                                        | business hours                         |
| **Lilith-Rights**              | 2 specialists                                            | takedown ≤ 24 h                        |
| **Lilith-Commerce**            | 2                                                        | refund / chargeback ≤ 48 h             |
| **Capacity / Pixel Streaming** | ≥ 1 engineer always + 2nd during every scheduled concert | 24×7 on-call rota                      |

Lilith-Safety's three shifts carry in-house language coverage — APAC English /
Japanese / Hindi, EU and NA English / Spanish / Portuguese — and other wave-1
locales (`fr`, `de`, `ar`, `he`) route to a localization partner under a
**4-hour SLA** (`localizationPartner.contractId: 'loc-wave1-2026-ga'`). The
GA-week rota is drilled: a green pager test (`ackP95Seconds: 41`,
`missedPages: 0` across PagerDuty, the Slack incident bridge, and the Operator
Console) and a follow-the-sun incident-commander rotation
(`ic-na`/`ic-eu`/`ic-apac`) covering each launch-week day with a backup.

### Scale-up ramp and steady state

A `hiringPlaybook` maps measured triggers to staffing actions with named owners
and a 60-day lead-time cap: Safety queue p95 SLA breach → +2 operators per
affected shift; sustained DAU 50 k → +safety per shift across wave-1; DAU 100 k
→ full per-region editorial; a new wave-2 region → +1 operator per active pool
before the region opens; a large festival → double the safety and capacity rota
for the event window. The `scaleOutTarget` (GA + 12 months, `status: 'on-plan'`)
is 8–12 Safety operators per shift, per-region editorial across all pools, and a
weekly leadership rebalancing review. Tone policy differs per tenant — Tara
contemplative vs. Saraswati pop-cultural — and is maintained per tenant by the
owning editorial pool even though in-the-moment moderation runs on the shared
Safety pool. Every operator action audit-logs into V1 `@oshun/audit-platform`;
the realm display-name override above is one such audited action.

### The honest gate state

Standalone, both `operator-staffing-model.json` and `on-call-rota-ga-week.json`
declare `releaseGate.status: green`. But a passing standalone artifact is
structural, not operational, and the **aggregate** launch-readiness run is the
source of truth — and it currently records `operator-console-staffed: fail`,
`operator-pools-day-one: fail`, and `verify:v3 operator-runbooks-on-call: fail`
among its red gates. The gate fails closed (a missing dependency, an unchecked
local task, or evidence drift all flip it red), so the page reports the
aggregate's `fail`, not the standalone `green`.

## Launch readiness and exit criteria

§75 aggregates everything above into one go/no-go. It is not a checklist someone
ticks — it is the output of `scripts/v3/verify-v3-launch-readiness.mjs`, which
**executes every verifier command the 39 named gates declare** (41 distinct
constituent commands), ANDs the results, and writes
`V3/launch/launch-readiness-release-gate.json`. The verifier refuses to pass
while the committed artifact disagrees with the run it just performed, so a
hand-edited green fails on drift. The artifact's own note records why this
machinery exists: a 2026-05-31 audit (`V3/VERIFICATION_AUDIT_2026-05-31.md`)
found a circular gate reporting green over red sub-gates, and the
de-circularized verifier exists to make that impossible.

### Today's measured state — honestly red

```
status: red   ·   passingGateCount: 30 / 41   ·   passingNamedGateCount: 24 / 39   ·   gaReady: false
```

The red is load-bearing, not a defect in the doc. Gates that **pass** on real
evidence include `c2pa-every-export`, `dsar-v3-session-data`,
`ue-anti-mod-anti-cheat-posture`, `recording-consent-drills`,
`wave1-region-prerequisites`, `pxstream-abuse-posture`, `pxstream-pop-capacity`,
`stadium-banded-seating`, `saraswati-stadium-concert`, `minor-protection`,
`royalty-quarter-settlement`, and `public-web-store-listings`. Gates that
honestly **fail** include `cross-platform-certification`,
`pixel-streaming-fleet-5x`, `tara-ga-inventory` / `saraswati-ga-inventory` /
`commons-ga-inventory`, `client-build-size-budgets`, `mobile-deep-links`,
`steam-deck-compatibility`, `metahuman-mobile-streaming`,
`tier2-fallback-parity`, `concert-authoring-cadence`,
`operator-console-staffed`, `operator-pools-day-one`, `release-thresholds`, and
`sections-1-74-complete`. Many fail because they need real fleet load, store
certification, or committed UE content this repo's engineering scaffold does not
yet carry — the truthful state of a pre-GA build. The aggregate flips to green
only when §1–74 carry no unchecked or waived local tasks **and** all 41
constituent commands exit green — not a moment before.

### The high-level checklist behind the gates

The §75 checklist the gates encode: all three tenants ship the GA inventory (≥
12 Tara instructors, ≥ 6 Saraswati artists with debut catalogs, ≥ 8 Commons
venues); cross-platform clients pass cert / browser-compat / perf budgets across
all nine platforms; the Pixel Streaming fleet sustains **5× expected concurrency
for 7 consecutive days** at p99 ≤ 60 ms and ≥ 99.5 % session-start success; the
operator console is fully staffed with documented runbooks; generation-provider
failover is drilled and the provenance inspector signed off by Lilith-Rights;
and all eval-set release gates plus the adversarial stub scan are green.
Accessibility is itself a gate, not an aspiration — the Tier-2 fallback's WCAG
2.2 AA conformance is a launch-readiness item, detailed in
[./accessibility-localization-quality.md](./accessibility-localization-quality.md).

### V3 exit criteria

V3 is feature-complete **only** when every section above is fully shipped,
**and** the adversarial scan turns up zero actionable hits, **and**
launch-readiness drills have run on all six certification surfaces — web, iOS,
Android, Quest 3, Vision Pro, and PSVR 2. The exit bar is deliberately
conjunctive: a green eval set with a red fleet gate is not GA, and a green
launch gate that drifted from its evidence is — by construction — not possible.

## Where this connects

- [./client-tiers-fidelity-stadium.md](./client-tiers-fidelity-stadium.md) — the
  four-tier client ladder the region router hands a cleared user to, and the
  stadium banding that launch-readiness gates against.
- [./accessibility-localization-quality.md](./accessibility-localization-quality.md)
  — the WCAG, localization, and QA gates a region must clear and that the launch
  gate aggregates.
- [./world-rooms-presence-multiplayer.md](./world-rooms-presence-multiplayer.md)
  — the world server that holds the server-authoritative progression
  cross-device consistency rides on.
- [./saraswati-economy-voice-genre-rights.md](./saraswati-economy-voice-genre-rights.md)
  — why Saraswati opens in fewer regions than Tara and Commons at GA.
- [../architecture/observability-performance-security-and-launch.md](../architecture/observability-performance-security-and-launch.md)
  — the architecture companion: the release-gate machinery, residency
  enforcement, performance budgets, and the de-circularized launch verifier in
  engineering depth.
- The feature hub: [../V3_features.md](../V3_features.md).
