DEV Guide: Building ZORGAX Party Mode, Realtime Sessions and Moderation in MyZubster
Over the last development cycle, we pushed a significant part of the MyZubster Social Life / Metaverse architecture forward.
What started as a social metaverse prototype is gradually becoming a structured system where:
- communities can connect to virtual environments;
- live sessions have authoritative lifecycle state;
- AI can understand operational context without receiving unrestricted access;
- creator actions can pass through bounded capability checks;
- moderation has persistent policy and audit primitives;
- realtime communication can use short-lived authenticated socket sessions;
- live experiences can transition into post-event archives.
This guide explains what we built, why we designed it this way, and what still remains.
1. The Starting Point: Neon Plaza
The MyZubster Metaverse currently exposes Neon Plaza, our shared social environment:
https://www.myzubster.com/metaverse
Before this development cycle, Neon Plaza already had some important foundations:
- MongoDB-backed shared presence;
- browser and touch movement;
- public chat and emotes;
- proximity awareness;
- guest and authenticated characters;
- portals to other areas of the MyZubster ecosystem;
- session and browser capability diagnostics.
The existing presence model is intentionally ephemeral.
Presence records expire after approximately:
90 seconds
Public chat has also been designed around limited retention rather than indefinite persistence.
The current shared-presence implementation uses a serverless-compatible polling architecture.
That remains useful, but it is not enough for the architecture we want next.
2. The Goal: ZORGAX Party Mode
The next layer is ZORGAX Party Mode.
The idea is not:
put a chatbot inside a metaverse.
The real objective is:
create a bounded AI orchestration layer that can understand a live social environment, reason about it, and eventually trigger authorized actions without becoming the source of truth.
The high-level architecture is:
Community
↓
Public Event
↓
Virtual Room / Virtual Twin
↓
Live Session
↓
ZORGAX Party Mode
↓
Moderation / Creator Actions
↓
Archive / Replay
↓
Community
The central architectural rule is:
System state first.
AI reasoning second.
ZORGAX can explain state.
ZORGAX can reason about state.
ZORGAX can eventually request actions.
But the backend defines what is true and what is authorized.
3. Z1 — PartyContext
The first Party Mode component was PartyContext.
Before giving an AI access to a live application, we need to answer a basic security question:
What information is the model allowed to know?
Instead of sending raw database objects into an LLM, the backend builds a bounded context.
Conceptually:
Authenticated Actor
↓
Server Authorization
↓
PartyContext
↓
ZORGAX
PartyContext can represent authorized information such as:
Actor
Community
Event
Room
Session
Capabilities
Restrictions
But it intentionally excludes information that the model does not need.
Examples include:
- authentication tokens;
- authorization headers;
- private keys;
- internal account identifiers;
- email addresses;
- private location data;
- raw session identifiers;
- permanent movement history.
One important lesson from implementation was that context itself is part of the security boundary.
During review, we caught an early version exposing an internal account identifier.
That field was removed and covered by a regression test.
4. Z2 — Grounded Community and Event Assistant
Once PartyContext existed, we implemented the first Party Mode assistant.
Endpoint:
POST /api/zorgax/party-assistant
The key design decision was not how much the assistant could answer.
It was how it behaved when information was unavailable.
For example, if the backend does not contain an authoritative lineup for an event, ZORGAX must not invent one.
Instead of:
"DJ X is playing at midnight."
the correct behavior is:
event information unavailable
The same applies to:
- private locations;
- account data;
- restricted system information;
- unverified event details.
This gave us another core rule:
Missing product state must remain missing product state.
An LLM should never convert absence of data into fictional application state.
5. Z3 — Room and Session Telemetry
The next step was giving ZORGAX operational awareness.
We introduced a Party Mode telemetry adapter:
GET /api/zorgax/party-telemetry
The purpose is to expose useful live-system information without exposing user-level surveillance data.
The telemetry model includes concepts such as:
Room health
Transport state
Aggregate presence
Storage state
Reconnect metadata
Retention metadata
For example:
room: healthy
presence: available
storage: shared
or:
room: degraded
presence: unavailable
storage: degraded
That distinction matters.
A degraded database or realtime service does not necessarily mean a party has ended.
We explicitly distinguish states such as:
healthy
degraded
offline
ended
not-modeled
6. Why not-modeled Matters
At the time Z3 was implemented, the full production WebXR session lifecycle did not yet exist.
So Party Mode was not allowed to pretend that stage, media or portal state already existed.
Instead of saying:
{
"stage": "offline"
}
we used the more accurate concept:
{
"stage": "not-modeled"
}
This may seem like a small detail, but for AI-integrated software it is extremely important.
These are not equivalent:
false
offline
unknown
unavailable
not implemented
An AI orchestration layer should preserve those differences.
7. Z4 — Creator Capability Gateway
Once Party Mode could understand state, the next question was:
What should ZORGAX be allowed to do?
This became the Creator Capability Gateway.
Endpoints include:
GET /api/zorgax/party-capabilities
POST /api/zorgax/party-command
The model is:
Creator
↓
ZORGAX
↓
Capability Gateway
↓
Server-side Authorization
↓
Approved Action
The important part is that Party Mode does not receive unrestricted tool execution.
Capabilities are allowlisted.
The first implemented capabilities were deliberately small.
For example:
request_session_status
publish_notice
publish_notice requires elevated authorization and explicit confirmation.
We also introduced:
- idempotency keys;
- audit records;
- bounded action scopes;
- expiry semantics;
- role checks.
At that stage the backend only had a concrete admin authorization model.
So instead of inventing a new creator role, mutating operations remained admin-gated until a richer role system exists.
8. Z5 — Moderation Assistance
Party Mode also needs trust and safety.
But the model is not:
AI detects something
↓
AI bans user
Instead:
Signal / Report
↓
ZORGAX
↓
Moderation Queue
↓
Human / Authorized Moderator
↓
Action
The first Party Mode moderation layer introduced:
POST /api/zorgax/party-reports
GET /api/zorgax/party-moderation-summary
POST /api/zorgax/party-moderation-action
Initially, supported moderator operations were intentionally limited to workflow actions such as:
mark-reviewed
escalate
dismiss
Permanent sanctions were not exposed to ZORGAX.
This keeps the AI in an assistance role rather than making it the final enforcement authority.
9. Z6 — Post-Event Archive Handoff
A social experience should not necessarily disappear when the live session ends.
We therefore added the post-event handoff model:
LIVE
↓
ENDED
↓
ARCHIVE
↓
REPLAY / HIGHLIGHTS
↓
COMMUNITY
Endpoints:
POST /api/zorgax/party-archive-handoff
GET /api/zorgax/party-archive
At that stage, the actual replay engine was not implemented yet.
So the API explicitly represented:
replayEngine: not-modeled
What we did implement was the important state boundary.
When archive handoff becomes active:
- live-only capabilities expire;
- public archive assets require approval;
- asset consent must be verified;
- unsafe URLs are rejected;
- private/unlisted archive content is not exposed publicly.
This means a live capability such as:
publish_notice
should no longer remain valid once the event has transitioned into archive state.
10. Z7 — Safety and End-to-End Acceptance
The final Party Mode stage was a dedicated safety and acceptance gate.
The tests cover scenarios including:
- identity spoofing;
- private-field leakage;
- prompt injection;
- attempts to obtain secrets or private locations;
- unauthorized creator commands;
- missing confirmation;
- idempotency replay;
- unauthorized moderation actions;
- unsafe archive URLs;
- missing asset consent;
- anonymous access to privileged routes;
- degraded telemetry behavior.
We also documented the boundary between what Party Mode implements and what still depends on upstream infrastructure.
At that point, the ZORGAX Party Mode core reached:
Z1 PartyContext ✅
Z2 Community Assistant ✅
Z3 Telemetry Adapter ✅
Z4 Capability Gateway ✅
Z5 Moderation Assistance ✅
Z6 Archive Handoff ✅
Z7 Safety / E2E Gate ✅
But some upstream product layers were still incomplete.
11. Building the Real Room/Session Lifecycle
The next major step was implementing the server-authoritative room/session lifecycle.
This work was tracked as:
MYZ-88
The system now models:
draft
↓
published
↓
scheduled
↓
live
↓
ended
↓
archive
We introduced persistent concepts such as:
VirtualRoom
VirtualSession
and server-side operations for:
- room creation;
- room updates;
- session creation;
- session start;
- join;
- leave;
- session end;
- short-lived session token issuance.
The lifecycle also supports:
- access policy;
- capacity limits;
- allowlists;
- blocklists;
- host/admin checks;
- scene manifest versioning.
12. Short-Lived Session Tokens
Joining a room does not mean handing a browser unlimited access.
Clients receive a short-lived realtime/session credential.
The principle is:
Authenticated browser
↓
Server checks room/session policy
↓
Short-lived token
↓
Realtime / session capability
This reduces the lifetime and scope of exposed credentials.
It also gives the backend a clean place to reject:
- ended sessions;
- blocked users;
- full rooms;
- unauthorized private-room access.
13. Persistent Lifecycle Event Stream
MYZ-88 also required reliable state broadcasting.
Instead of depending only on in-memory sockets, we implemented a persistent event stream.
Endpoint:
GET /api/metaverse/sessions/:id/events?after=<cursor>&limit=<n>
Events include:
session_created
session_started
participant_joined
participant_left
session_ended
Events are persisted in MongoDB.
Consumers poll incrementally using a cursor based on:
lifecycleVersion
This gives us:
- resumability;
- serverless compatibility;
- ordering;
- idempotent writes;
- shared state across instances.
The public event payload remains aggregate-focused and does not expose:
- participant account identifiers;
- host IDs;
- tokens;
- chat;
- movement history.
This persistent event stream is the authoritative state history.
WebSockets can later become a faster delivery mechanism, but they do not need to become the source of truth.
14. Moderation Foundation: Block, Mute, Report
After the room lifecycle was complete, we moved into deeper realtime safety.
The first moderation foundation introduced persistent interaction controls.
API surface:
POST /api/moderation/controls/:kind
POST /api/moderation/delivery-check
POST /api/moderation/reports
POST /api/moderation/actions
GET /api/moderation/events?after=<timestamp>
Supported control concepts include:
block
mute
We also introduced a server-side:
deliveryDecision()
hook.
This gives future messaging code a single policy boundary:
message candidate
↓
deliveryDecision()
↓
allowed / denied
That is better than duplicating block logic in every realtime transport.
15. Contextual Reports
Reports can carry bounded context relating to:
message
user
session
Inputs are sanitized and rate-limited.
The system also creates a durable moderation event/audit stream with a retention policy.
Moderator actions currently include concepts such as:
warn
remove_content
mute
suspend
escalate
Privileged operations are recorded.
The system is designed to fail closed when moderation storage is unavailable.
16. Why MYZ-82 Is Not Finished Yet
The moderation foundation exists, but full realtime enforcement depends on actual realtime messaging delivery.
Two upstream tasks are involved:
MYZ-78 — realtime gateway
MYZ-80 — direct messages and community channels
Without those layers, we cannot truthfully claim:
block/mute instantly affects all live socket delivery
or:
moderation.action propagates immediately to connected clients
The policy layer is ready.
The transport and messaging layer must now consume it.
17. MYZ-78 — Realtime Gateway and Socket Authentication
We are now implementing that missing transport layer.
The realtime gateway introduces:
POST /api/realtime/token
and a Socket.IO endpoint mounted at:
/realtime
Instead of sending the browser's normal JWT directly into a long-lived realtime session, the backend exchanges it for a dedicated short-lived realtime token.
Conceptually:
Browser JWT
↓
POST /api/realtime/token
↓
5-minute realtime token
↓
Socket.IO handshake
The realtime token includes dedicated checks for:
- issuer;
- audience;
- purpose;
- expiry.
18. Server-Side Channel Authorization
The gateway uses three planned namespace types:
user:{id}
community:{id}
session:{id}
Authorization happens on the server.
For user channels:
user:123
the authenticated user must be 123, unless a specific privileged policy says otherwise.
For session channels:
session:abc
the caller must be:
- a participant;
- the host;
- or an authorized admin.
For community channels, authorization currently fails closed for normal users.
Why?
Because the authoritative community membership system belongs to MYZ-80 and is not implemented yet.
Rather than guessing membership:
community subscription denied
until the backend has a real authority source.
19. Reconnect Without Duplicate Presence
Realtime reconnect introduces another common distributed-system problem:
What happens when the browser reconnects?
The gateway uses a restore flow through:
realtime.resume
But subscriptions are not blindly restored.
Every requested channel is re-authorized.
Conceptually:
disconnect
↓
reconnect
↓
send previous subscriptions
↓
server re-authorizes every channel
↓
restore approved subscriptions
The gateway also does not directly mutate persistent presence during reconnect.
This helps prevent duplicate presence records.
20. Heartbeat and Connection Lifecycle
Socket.IO provides ping/pong heartbeat behavior.
The gateway also includes connection metadata and correlation identifiers useful for observability.
A ready event can include a request/session correlation ID so backend logs can associate:
token issuance
connection
subscription
resume
disconnect
without logging authentication secrets.
21. An Important Deployment Constraint
One major architectural point became clear during implementation:
Vercel serverless should not be treated as the production WebSocket host for this gateway.
The current MyZubster frontend and many HTTP APIs can continue using Vercel.
But a persistent Socket.IO/WebSocket service requires:
long-lived Node runtime
or a compatible managed realtime platform.
That means our architecture separates:
Frontend / serverless HTTP
+
Persistent realtime transport
rather than pretending every deployment environment has the same connection model.
22. Current State
At the moment the architecture looks roughly like this:
MyZubster
│
┌───────────┴───────────┐
│ │
Social Life Metaverse
│ │
Community Neon Plaza
│ │
└──────────┬────────────┘
│
Virtual Rooms
│
Live Sessions
│
Persistent Event Stream
│
Realtime Gateway
│
┌───────────────┼───────────────┐
│ │ │
user:{id} community:{id} session:{id}
│
PartyContext
│
ZORGAX
│
┌───────────────┼───────────────┐
│ │ │
Telemetry Commands Moderation
│
Archive Handoff
23. What Still Needs to Be Built
There are still several important layers.
The immediate next sequence is:
MYZ-78
Realtime gateway
↓
MYZ-80
DM + community channels
↓
MYZ-82
Complete realtime moderation
After MYZ-80 exists, the gateway can authorize:
community:{id}
from real membership data.
Messaging can call:
deliveryDecision()
before persisting or emitting a message.
And moderation events can propagate immediately to the affected realtime clients.
24. The Longer-Term Architecture
Once these blocks are complete, the MyZubster Social Life experience moves closer to:
Community
↓
Event
↓
Virtual Twin / Neon Plaza
↓
Authenticated Realtime
↓
ZORGAX Party Mode
↓
Creator Actions
↓
Live Moderation
↓
Event Ends
↓
Archive / Replay
↓
Community
Eventually, additional systems can connect around the same authorization boundaries:
Identity
Marketplace
LIFE environmental projects
Robotics
Space Station
Creators
AI agents
Real-world data
25. The Main Engineering Lesson
The most important lesson from this work is not about AI.
It is about boundaries.
Every feature forced us to answer questions like:
Who is authoritative?
What can this component know?
What can this component do?
What happens when data is missing?
What happens when storage fails?
What happens after reconnect?
How long does a capability remain valid?
Who approved the action?
What is recorded in the audit trail?
The AI layer becomes safer and more useful when those answers exist before the prompt reaches the model.
That is the direction we're taking with ZORGAX.
Not:
AI controls everything
but:
Authoritative systems
↓
bounded context
↓
bounded capabilities
↓
AI orchestration
↓
auditable outcome
Links
MyZubster Metaverse:
https://www.myzubster.com/metaverse
MyZubster Space Station:
https://www.myzubster.com/space-station
GitHub:
https://github.com/MyZubster-Ecosystem/myzubster
Current development sequence
ZORGAX Party Mode Z1–Z7 ✅
Room/session lifecycle MYZ-88 ✅
Persistent lifecycle stream ✅
Moderation foundation MYZ-82 ✅ partial
Realtime gateway MYZ-78 🚧 current
DM/community channels MYZ-80 ⏳ next
Realtime moderation completion ⏳
Replay/highlights engine ⏳
We're building the project publicly and deliberately separating production functionality, experimental infrastructure and roadmap ideas.
If you're working on realtime systems, WebXR, AI agents, authorization or multiplayer infrastructure, I'd be interested in your perspective:
Would you make the socket layer authoritative, or keep persistent state authoritative and treat realtime as a delivery optimization?
Top comments (0)