V3 ("Lilith") is a contemplative metaverse layered on top of the existing V1
Oshun platform, and it is large enough that it needs a fixed vocabulary before
anyone can reason about it. This page is that vocabulary plus a map of where
each name actually lives on disk. The glossary in
../V3_ARCHITECTURE.md declares the canonical subsystem
names — module names, namespaces, asset paths, and Game Feature plugins all
inherit from them — and the architecture document then sketches an aspirational
directory tree. The job here is to reconcile that declaration with the code that
exists: a 30-entry contract registry in libs/contracts/src/v3/registry.ts, a
five-crate Rust service workspace under apps/v3/, eighteen TypeScript
libraries under libs/v3/, and a single Unreal Engine 5.5 project at V3/ue/
carrying seventeen C++ modules, three build targets, and twenty-one Game Feature
plugins.
The reason the layout looks the way it does is that V3 deliberately reuses V1.
There is no second identity system, no second billing engine, no second event
bus — the V3 client routes catalog and billing through the V1 BFF, and the new
code is confined to the realtime/embodied layer: an authoritative world server,
a transport gateway, a Pixel Streaming fleet, two tenant services, and the
client itself. That single decision is why apps/v3/ holds only realtime
infrastructure, why libs/v3/ is full of thin "extends V1 subsystem X"
adapters, and why the contract registry tags every record with both a domain
and a clientTenant. Read this page as the index; the sibling pages listed
under Related go deep on each subsystem named here.
What ships, honestly#
The contracts, the Rust services, and the TypeScript SDK layer are real and
substantial. The contract registry compiles 30 Zod schemas with fixtures and
Prisma model bindings (libs/contracts/src/v3/registry.ts); the multiplayer
protocol is a genuine protobuf codec with snapshot-delta application,
client-side extrapolation, and version negotiation
(libs/v3/multiplayer-protocol/src/index.ts, 377 lines over a real .proto);
the avatar pipeline exports 41 functions implementing a VRM 1.0 importer,
retargeting, viseme lip-sync, and costume-slot safety checks
(libs/v3/avatar-pipeline/src/index.ts); and the five Rust services carry real
domain logic — lilith-world-server pulls in rapier3d for physics and sqlx
for Postgres, saraswati-service has thirteen performance-flow modules plus
c2pa provenance signing, lilith-commerce-service has thirteen
billing/royalty modules. The Unreal client is a real, structured project —
17 modules wired into V3.uproject, three build targets, and 33 C++ automation
specs under V3/ue/Source/V3Tests/Private/.
Three honest caveats. First, the project-layout tree in the architecture
monolith is out of date in one concrete way: it shows the Game Feature plugins
directly under V3/ue/Plugins/, but on disk they live one level deeper, under
V3/ue/Plugins/GameFeatures/. Second, those plugins are content-only — none
of the 21 has a Source/ directory; they are GameFeatureData containers, so
the glossary's "owns" column describes data and activation scope, not C++
ownership (the gameplay code lives in the always-loaded modules). Third, the
17 UE modules are not uniformly deep: V3Avatar, V3UI, V3Input, V3Core,
V3Editor, and V3Tests carry real implementation, while V3Gameplay,
V3Animation, V3Cinematics, V3VFX, V3OnlineServices, V3Persistence, and
V3Telemetry are presently three-file module skeletons (a .cpp, a .h, and a
*.Build.cs). Where a name in the glossary outruns its code, this page says so.
The naming spine#
The glossary's first table names twelve platform substrates with the
Lilith- prefix — Lilith-World, Lilith-Gateway, Lilith-PxStream,
Lilith-UE, Lilith-WebFB, Lilith-Avatar, Lilith-Audio,
Lilith-Identity-Bridge, Lilith-Safety, Lilith-Rights, Lilith-Commerce,
Lilith-Studio, Lilith-Operator. These are conceptual names, not import
paths: each one resolves to a concrete surface in the layout below. Lilith is
also the V1 persona-policy domain, which is not a coincidence — the safety frame
that governs a meditation chat in V1 is the same frame that governs an embodied
room in V3 (see libs/v3/lilith-body-policy, which imports directly from
@oshun/persona-policy-lilith). The other three name families are tenants
(tara-studio, saraswati-stage, lilith-commons — the three launch
experiences), UE modules (the V3* prefix), and Game Feature plugins
(V3Tenant_* and V3Mode_*). When you see V3Net in C++,
@oshun/multiplayer-protocol in TypeScript, and multiplayer-protocol as a
Cargo crate, those are three language bindings of the same substrate (Lilith
networking); the naming spine is what lets you trace one concept across all
three.
Where the code actually lives#
V3 code has four homes. The diagram shows them and the direction of dependency; the tables that follow give verified contents.
libs/contracts/src/v3 — the cross-language source of truth#
Ten files
(primitives, lilith, tara, saraswati, commons, consent, fixtures, registry, openapi, index).
The barrel index.ts re-exports all of them, and the root contracts package
surfaces V3 twice — once namespaced and once flat — at
libs/contracts/src/index.ts:28-29
(export * as V3Contracts from './v3/index'; export * from './v3/index';). The
heart is registry.ts: a V3_CONTRACT_REGISTRY array of 30 descriptors built
by a contract() factory, each carrying a contractName, its Zod schema, a
fixture, a routeSegment, a domain
(lilith-platform | tara | saraswati | commons | cross-cutting), a
clientTenant, a prismaSchemaPath, and a derived prismaModelName of
V3${contractName}. getV3ContractsForTenant() filters by tenant. This is the
spine every other layer reads from — see
Data, Tenancy, and Residency for how the
registry drives routing and storage isolation.
| Domain | Count | Contracts |
|---|---|---|
lilith-platform |
8 | LilithSession, AvatarBinding, Presence, Room, Venue, SpatialTranscript, Report3D, ProvenanceBundle3D |
tara |
8 | LiveClassSession, OnDemandClassRecording, AsanaSequence, Asana, InstructorProfile, InstructorCredential, AjaCueEvent, PracticePlan |
saraswati |
8 | ArtistPersona, Track, Catalog, Concert, Setlist, FanInteraction, SignedEdition, RemixRights |
commons |
5 | ProgramSlot, JournalEntry3D, DebateSession, Lectio, SkyObservation |
cross-cutting |
1 | EmbodiedConsent |
The prismaSchemaPath mapping is worth noting because it does not split the way
the domains do: there are only three Prisma schemas
(libs/v3/{lilith-commons,tara-studio,saraswati-stage}/prisma/schema.prisma),
and the lilith-commons schema holds 14 models — every lilith-platform
contract, every commons contract, and EmbodiedConsent — while
tara-studio and saraswati-stage each own their eight. So clientTenant
decides routing and which BFF surface serves the record, but Commons rides on
the shared platform schema rather than a tenant-private one. The Prisma model
names match the registry exactly (model V3LilithSession,
model V3EmbodiedConsent, …).
apps/v3 — the Rust realtime workspace#
apps/v3/Cargo.toml is a resolver = "2" workspace, Rust 1.82, with
unsafe_code = "forbid" set workspace-wide. It has five service members plus
the shared protocol crate (../../libs/v3/multiplayer-protocol/rust):
| Service | Role (glossary substrate) | Real dependencies / shape |
|---|---|---|
lilith-world-server |
Lilith-World | axum, prost, rapier3d 0.21 (physics authority), redis streams, sqlx Postgres; durable_persistence.rs |
lilith-realtime-gateway |
Lilith-Gateway | quinn 0.11 (QUIC/WebTransport), webrtc 0.11, tokio-tungstenite (WebSocket) |
lilith-pxstream-relay |
Lilith-PxStream | axum signalling/relay over the UE Pixel Streaming worker fleet |
saraswati-service |
Saraswati tenant | 13 flow modules (performance_plan, per_song_execution, between_song_speech, recording_pipeline, royalty_settlement, …) + c2pa 0.57 provenance |
lilith-commerce-service |
Lilith-Commerce | 13 modules (lilith_royalty_waterfall, lilith_ticket_issuance, lilith_tip_routing, lilith_rights_takedown_cascade, saraswati_signed_edition, …) |
The two web entries — apps/v3/lilith-web (@oshun/v3-lilith-web, Next/React;
the thin browser shell that hosts the Pixel Streaming player) and
apps/v3/lilith-web-fallback (@oshun/v3-lilith-web-fallback, three.js; the
Tier-2 local renderer) — round out the seven entries. The world server and
gateway are covered in
World Server and Gateway; the relay and the
browser path in
Tier Routing and Pixel Streaming and
Tier-2 Fallback Web Client; the two tenant
services in Saraswati Stage Pipeline and
Commerce and Royalties.
libs/v3 — eighteen TypeScript SDKs and adapters#
Two of these are deep implementation libraries; the rest are V1-extension
adapters and gates. The architecture monolith's project tree lists sixteen; the
two it omits — concert-quality and lilith-body-policy — are real and
shipped.
multiplayer-protocol— the network substrate, generated bybuffromproto/oshun/v3/multiplayer/v1/multiplayer.proto(packageoshun.v3.multiplayer.v1) into both TS (src/) and Rust (rust/src/lib.rs). The proto declares seven enums (CapacityTier,ActivityState,VoiceControlKind,InteractionKind,GameplayActionKind,OperatorControlKind,NegotiationStatus) and the wire messages (SnapshotPacket,SnapshotDeltaPacket,PresencePacket,ClientEnvelope,ServerEnvelope, …). Coordinates are fixed-point integers —Vector3Mm(millimetres),RotationMilliDegrees,intensityBasisPoints— which is how the protocol stays deterministic across the Rust server and the C++/TS clients. The index implementsapplySnapshotDelta()(upsert/remove against a prior snapshot),predictSnapshot()(dead-reckoning extrapolation clamped to 250 ms),negotiateProtocolVersion(), andrunDecoderBenchmark(), with bandwidth capsCLASS_TIER_MAX_BPS = 32_000andSTADIUM_TIER_MAX_BPS = 256_000. Detail in Netcode Protocol and Physics.avatar-pipeline— 41 exported functions over a real VRM 1.0 glTF model (Vrm1GltfDocument, theVRMC_vrmextension):parseVrm1Json(),importVrm1Document(),verifyVrm1IdentityRoundTrip(), an Oshun-60 skeleton retarget (createOshun60RetargetTable,retargetVrmReferenceAnimation,evaluateOshun60RetargetRegression), viseme lip-sync (renderVisemePhrase,evaluateVisemePhraseLipSync), and costume-slot binding with alilithSafetyCostumeRuleCheck()plus per-tenant costume packs. See Avatar, Animation, and Audio.- Tenant adapters —
tara-studio,saraswati-stage,lilith-commonseach export aV3PackageDescriptorcapability descriptor (layer: 'tenant') and own a Prisma schema. The descriptors are honest about scope — e.g. Tara Studio'scanonical-asana-librarycapability carries the operational metriccanonical-asanas:>=300+editorial-signed+design-approved, a target rather than a claim. Covered in Tara Classes, Aja, and Commons. - V1-extension bridges —
aja-pose(in-world pose estimation/cue delivery),memory-iris-spatial,isis-music/isis-motion/isis-world-asset(generation workflows),psyche-3d,sophia-saraswati-grounding,lilith-identity-bridge, the Tier-2 engine wrapperslilith-web-pxstream/lilith-engine-web-fallback, andspatial-audio. - Policy and quality gates —
lilith-body-policyre-binds V1's@oshun/persona-policy-lilith(crisis detection, voice-abuse signals, unsafe-claim classification, contemplative-tone evaluation) to embodied surfaces;concert-qualityshipsGateDefinitions for@oshun/content-release-gatesso a low-quality or homogeneous concert scene fails the export report alongside a revoked-consent or bad-signature failure. See Persona Policy, Provenance, and Rights and Authoring and Content Pipeline.
V3/ue — the canonical Unreal client#
V3/ue/V3.uproject enables seventeen Runtime modules. Loading order matters:
V3Core and V3Gameplay use LoadingPhase: PreDefault (they register engine
subsystems and gameplay tags before anything depends on them); the rest load at
Default. There are three build targets, each a *.Target.cs under
Source/:
| Target | Type | Notes |
|---|---|---|
V3.Target.cs |
Game | Compiles 15 runtime modules; sets V3_LILITH=1, V3_ENGINE_UE55=1; deterministic FP |
V3Editor.Target.cs |
Editor | Adds editor-only modules (V3Editor) on top |
V3PixelStreamingWorker.Target.cs |
Game | Monolithic, Desktop-only, bBuildWithEditorOnlyData=false, logging in shipping |
The determinism posture is explicit and worth citing: V3.Target.cs sets
bUseUnityBuild = false and appends strict floating-point flags —
/fp:strict /fp:except- on Win64 and -fno-fast-math -ffp-contract=off on
clang/Linux — so that physics and replication stay bit-reproducible across the
server, the native client, and the Pixel Streaming worker. The worker target
recompiles the same 15 runtime modules monolithically for the streaming fleet.
The seventeen Source/ module directories map one-to-one onto the glossary's UE
table; their depth varies (113 C++ files total). The substantial ones today are
V3UI (15 files), V3Avatar (12), V3Editor (11), V3Core (9), V3Input
(9), V3World (5), V3Audio (5), V3Net (4), and V3Voice (4). V3Net is
the wire adapter named in the glossary: Private/V3NetProtocol.cpp plus a
parity spec V3NetProtocolTests.cpp, with V3Net.Build.cs depending only on
Core, CoreUObject, Engine, GameplayTags, V3Core. The remaining modules
(V3Gameplay, V3Animation, V3Cinematics, V3VFX, V3OnlineServices,
V3Persistence, V3Telemetry) are three-file compilable skeletons. Test depth
is real: 33 automation specs under V3Tests/Private/, including
V3AvatarRetargetTests, V3OpenXRHandIkTests, V3VrTimewarpTests,
V3SteamAudioVrTests, V3PostureStateMachineTests,
V3TaraPhysicalAdjustmentConsentDialogTests,
V3SaraswatiConcertMasterTemplateTests, and a per-platform cook-profile suite
(Android, iOS, Linux, Mac, PS5, PSVR2, Quest3, SteamDeck, VisionPro, Win64,
XboxSeriesX). The client is detailed in
Tier-1 UE5 Client.
Game Feature plugins — V3/ue/Plugins/GameFeatures#
Twenty-one plugins live here (not directly under Plugins/, as the monolith's
tree implies). Three are tenants (V3Tenant_TaraStudio,
V3Tenant_SaraswatiStage, V3Tenant_LilithCommons) and eighteen are modes:
four Tara (LiveClass, OnDemand, Private, Cohort), five Saraswati
(Concert, Club, Listening, Drop, Festival), and nine Commons
(Atrium, Observatory, DebateHall, LectureHall, Stacks, RitualRoom,
AretAtrium, LanternHall, SolitaryCell). Every one is a content-only
GameFeatureData plugin: a .uplugin with "CanContainContent": true,
"ExplicitlyLoaded": true, "EnabledByDefault": false,
"BuiltInInitialFeatureState": "Registered", declaring dependencies on
GameFeatures and ModularGameplay. None has a Source/ directory. That is
the intended Modular Gameplay shape: the always-loaded V3* C++ modules provide
the machinery, and a plugin is activated when a client joins the corresponding
room — toggling its content, gameplay-tag set (Config/Tags/*Tags.ini), and
feature actions on, then off again on leave. So the glossary's "Owns" column for
these rows means activation scope and data, not compiled code.
A worked trace: one Tara live-class join#
To show how the names connect, follow a single action — a student joining a scheduled Tara live class — through the layers:
- A
LiveClassSessionrecord (registry domaintara, tenanttara-studio, route segmentlive-class-sessions, Prisma modelV3LiveClassSession) defines the class. The V1 BFF reads it; tier routing decides client vs. Pixel Streaming vs. fallback (see Tier Routing and Pixel Streaming). - The client opens a
LilithSession(registry domainlilith-platform) againstlilith-realtime-gateway, which negotiates a protocol version withnegotiateProtocolVersion()and pins the session to alilith-world-servershard hosting theRoom. - On join, the UE client activates the
V3Mode_TaraLiveClassGame Feature plugin and theV3Tenant_TaraStudiotenant plugin, bringing their content and gameplay tags online. - The world server streams authoritative
SnapshotDeltaPackets; each client applies them withapplySnapshotDelta()and smooths withpredictSnapshot(). Pose correction ridesAjaCueEventrecords vialibs/v3/aja-pose. - Safety is continuous:
lilith-body-policyevaluates tone and voice signals;V3TaraPhysicalAdjustmentConsentDialogTestsguards the consent gate for physical-adjustment cues. Identity and reputation come from V1 throughlilith-identity-bridge(see V1 Integration and Identity Bridge).
Every noun in that trace is a name from the glossary and a path in the layout — which is the whole point of fixing the vocabulary first.
Edge cases and where the map diverges from the territory#
- Plugins path. Use
V3/ue/Plugins/GameFeatures/<name>/, notV3/ue/Plugins/<name>/. Automation and packaging scripts that hard-code the shallower path will miss all 21 plugins. - Two undocumented libs.
libs/v3/concert-qualityandlibs/v3/lilith-body-policyexist and are wired in but are absent from the monolith's project tree — treat the tree as illustrative, the directory as authoritative. - Module depth. The seven three-file modules compile and link but carry no domain logic yet; don't read the glossary's "Responsibility" column as a statement of present coverage for those.
- Commons has no private schema. Commons records persist through the shared
lilith-commons/prisma/schema.prisma, so residency/tenancy reasoning for Commons follows thelilith-platformrules, not a tenant-isolated store (see Data, Tenancy, and Residency). - One protocol, three bindings. A change to
multiplayer-protocol/proto/.../multiplayer.protomust regenerate TS, the Rust crate, and stay in parity with the C++V3Netdecoder;V3NetProtocolTestsandrunDecoderBenchmark()are the parity guards.
Related#
- Product Promise and Architecture — the why behind the V1-reuse layout
- Tier Routing and Pixel Streaming, Tier-1 UE5 Client, Tier-2 Fallback Web Client
- World Server and Gateway, Netcode Protocol and Physics
- Avatar, Animation, and Audio, Saraswati Stage Pipeline, Tara Classes, Aja, and Commons
- Authoring and Content Pipeline, Data, Tenancy, and Residency
- V1 Integration and Identity Bridge, Persona Policy, Provenance, and Rights, Commerce and Royalties, Observability, Performance, Security, and Launch
- The section hub: ../V3_ARCHITECTURE.md