<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged metaverse</title>
<link>https://coderlegion.com/tag/metaverse</link>
<description>Powered by Question2Answer</description>
<item>
<title>How We Secured the MyZubster Metaverse: Session Ownership, Verified Explorers and the Road to Realti</title>
<link>https://coderlegion.com/31491/how-secured-the-myzubster-metaverse-session-ownership-verified-explorers-and-road-realti</link>
<description>&lt;p&gt;A technical update on the architecture, security controls, testing and remaining roadmap behind the open-source MyZubster Metaverse.&lt;br&gt;
The MyZubster Metaverse is moving from an experimental interface toward a secure, testable multiplayer environment.&lt;br&gt;
Our goal is not simply to display avatars in a browser. We want to create an open-source world connecting public profiles, verified contributors, Zorgax characters, community knowledge and software-development workflows.&lt;br&gt;
The public Metaverse is available at:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;br&gt;
This article describes what we have implemented, the security problem we recently solved and what remains before the platform can support realtime interaction at scale.&lt;br&gt;
The current experience&lt;br&gt;
A user can enter the MyZubster world as a guest without providing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a cryptocurrency wallet;&lt;/li&gt;
&lt;li&gt;identity documents;&lt;/li&gt;
&lt;li&gt;a GitHub account;&lt;/li&gt;
&lt;li&gt;an installed application.&lt;br&gt;
The current interface supports guest onboarding through a public display name and also presents verified explorers associated with authorized public accounts.&lt;br&gt;
This creates two identity levels:&lt;ol&gt;
&lt;li&gt;Guest explorers use temporary world sessions.&lt;/li&gt;
&lt;li&gt;Verified explorers have characters linked to a MyZubster account or confirmed GitHub identity.&lt;br&gt;
“Verified” does not mean KYC or legal identity verification. It only confirms control of the connected public account.&lt;br&gt;
Building the presence layer&lt;br&gt;
The backend maintains a presence record for every active participant.&lt;br&gt;
A simplified record may contain:&lt;br&gt;
{&lt;br&gt;
sessionId,&lt;br&gt;
displayName,&lt;br&gt;
characterId,&lt;br&gt;
accountId,&lt;br&gt;
githubLogin,&lt;br&gt;
position,&lt;br&gt;
status,&lt;br&gt;
lastSeenAt&lt;br&gt;
}&lt;br&gt;
This model supports the main world operations:&lt;br&gt;
Join&lt;br&gt;
Synchronize&lt;br&gt;
Move&lt;br&gt;
Chat&lt;br&gt;
Emote&lt;br&gt;
Leave&lt;br&gt;
Retrieve events&lt;br&gt;
Public players must be discoverable by other clients, so each presence has a public session identifier.&lt;br&gt;
However, a public identifier must never be treated as proof that a request belongs to that player.&lt;br&gt;
That distinction became the focus of our latest security milestone.&lt;br&gt;
The original session-ownership problem&lt;br&gt;
A multiplayer client needs to identify which session it wants to update.&lt;br&gt;
For example:&lt;br&gt;
{&lt;br&gt;
&quot;sessionId&quot;: &quot;public-session-id&quot;,&lt;br&gt;
&quot;x&quot;: 120,&lt;br&gt;
&quot;y&quot;: 80&lt;br&gt;
}&lt;br&gt;
If the backend trusts only sessionId, a malicious user may be able to submit another player’s identifier and perform actions on their behalf.&lt;br&gt;
Depending on the exposed routes, this could allow an attacker to:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;move another character;&lt;/li&gt;
&lt;li&gt;send chat messages under another identity;&lt;/li&gt;
&lt;li&gt;publish unauthorized emotes;&lt;/li&gt;
&lt;li&gt;retrieve session-specific events;&lt;/li&gt;
&lt;li&gt;terminate another player’s session.&lt;br&gt;
A public session ID is an identifier, not an authorization credential.&lt;br&gt;
Implementing possession-bound sessions&lt;br&gt;
We implemented a new security boundary in:&lt;br&gt;
Pull Request #34 — Bind world actions to session credentials&lt;br&gt;
The change was merged into main as commit:&lt;br&gt;
148a798&lt;br&gt;
Every new Metaverse session now receives two different values:&lt;br&gt;
Public session ID&lt;br&gt;
Private session token&lt;br&gt;
The public ID can appear in world-state responses. The private token proves that the client controls the session.&lt;br&gt;
Cryptographically random credentials&lt;br&gt;
The server generates a token using 32 random bytes:&lt;br&gt;
const sessionToken = crypto&lt;br&gt;
.randomBytes(32)&lt;br&gt;
.toString(&quot;base64url&quot;);&lt;br&gt;
This provides 256 bits of entropy.&lt;br&gt;
The raw token is returned only during session creation and is never included in public presence data.&lt;br&gt;
Storing only a digest&lt;br&gt;
The server does not persist the raw credential.&lt;br&gt;
Instead, it calculates a SHA-256 digest:&lt;br&gt;
const sessionTokenHash = crypto&lt;br&gt;
.createHash(&quot;sha256&quot;)&lt;br&gt;
.update(sessionToken)&lt;br&gt;
.digest(&quot;hex&quot;);&lt;br&gt;
Only sessionTokenHash is stored with the presence record.&lt;br&gt;
This prevents a database reader from immediately obtaining active bearer credentials.&lt;br&gt;
Constant-time comparison&lt;br&gt;
When a protected request arrives, the server hashes the submitted credential and compares it with the stored digest.&lt;br&gt;
The verification uses a constant-time comparison:&lt;br&gt;
crypto.timingSafeEqual(expected, received);&lt;br&gt;
A shared ownership middleware verifies that:&lt;/li&gt;
&lt;li&gt;the session exists;&lt;/li&gt;
&lt;li&gt;a credential was supplied;&lt;/li&gt;
&lt;li&gt;the credential has the expected format;&lt;/li&gt;
&lt;li&gt;its digest matches the stored value;&lt;/li&gt;
&lt;li&gt;the caller owns the requested session.&lt;br&gt;
Invalid or missing credentials return:&lt;br&gt;
HTTP 401 Unauthorized&lt;br&gt;
Protected world routes&lt;br&gt;
Session ownership is now required for mutable and session-specific operations such as:&lt;br&gt;
/sync&lt;br&gt;
/move&lt;br&gt;
/chat&lt;br&gt;
/emote&lt;br&gt;
/leave&lt;br&gt;
/events&lt;br&gt;
Knowing another participant’s sessionId is no longer sufficient to control their character.&lt;br&gt;
The authorization rule is now:&lt;br&gt;
Public session ID&lt;pre&gt;&lt;code&gt;  +
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Private possession token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  =
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Authorized world action&lt;br&gt;
Keeping credentials out of public payloads&lt;br&gt;
The frontend sends the private token through a dedicated HTTP header:&lt;br&gt;
X-Metaverse-Session-Token: &amp;lt;private-token&amp;gt;&lt;br&gt;
Example:&lt;br&gt;
const createSessionHeaders = (sessionToken) =&amp;gt; ({&lt;br&gt;
&quot;X-Metaverse-Session-Token&quot;: sessionToken,&lt;br&gt;
});&lt;br&gt;
The world-state body remains limited to operational data:&lt;br&gt;
{&lt;br&gt;
&quot;sessionId&quot;: &quot;public-session-id&quot;,&lt;br&gt;
&quot;x&quot;: 120,&lt;br&gt;
&quot;y&quot;: 80&lt;br&gt;
}&lt;br&gt;
This separation reduces the probability that credentials are accidentally copied into:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;world events;&lt;/li&gt;
&lt;li&gt;analytics;&lt;/li&gt;
&lt;li&gt;public API responses;&lt;/li&gt;
&lt;li&gt;application logs;&lt;/li&gt;
&lt;li&gt;debugging output;&lt;/li&gt;
&lt;li&gt;cached payloads.&lt;br&gt;
The credential is also kept in React runtime memory instead of being written to localStorage or public profile objects.&lt;br&gt;
An in-memory token is not a complete defense against browser compromise, but it reduces persistent credential exposure.&lt;br&gt;
Identity boundaries&lt;br&gt;
The Metaverse now distinguishes between several layers:&lt;br&gt;
Account identity&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Public profile&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Character identity&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Temporary world session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Private session credential&lt;br&gt;
These layers have different meanings.&lt;br&gt;
A verified GitHub account does not automatically prove legal identity, employment, payment eligibility or institutional affiliation.&lt;br&gt;
Similarly, a public session ID identifies a player’s presence but does not authorize requests for that player.&lt;br&gt;
Documenting these boundaries is essential for avoiding security and governance problems later.&lt;br&gt;
Testing the implementation&lt;br&gt;
The session-ownership change includes backend, frontend and architecture-level tests.&lt;br&gt;
Backend tests&lt;br&gt;
The targeted backend suites verify:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;secure token generation;&lt;/li&gt;
&lt;li&gt;SHA-256 digest storage;&lt;/li&gt;
&lt;li&gt;valid credential acceptance;&lt;/li&gt;
&lt;li&gt;missing credential rejection;&lt;/li&gt;
&lt;li&gt;invalid credential rejection;&lt;/li&gt;
&lt;li&gt;cross-session mutation prevention;&lt;/li&gt;
&lt;li&gt;protected movement and chat;&lt;/li&gt;
&lt;li&gt;protected emotes and leave operations;&lt;/li&gt;
&lt;li&gt;exclusion of secrets from public responses.&lt;br&gt;
Results:&lt;br&gt;
3 backend suites&lt;br&gt;
22 tests passed&lt;br&gt;
Frontend tests&lt;br&gt;
Frontend coverage verifies:&lt;/li&gt;
&lt;li&gt;token retention in application memory;&lt;/li&gt;
&lt;li&gt;use of the session-token header;&lt;/li&gt;
&lt;li&gt;authenticated world operations;&lt;/li&gt;
&lt;li&gt;removal of tokens from normal JSON bodies;&lt;/li&gt;
&lt;li&gt;correct handling of protected session requests.&lt;br&gt;
Results:&lt;br&gt;
1 frontend suite&lt;br&gt;
5 tests passed&lt;br&gt;
Integration and deployment&lt;br&gt;
The completed verification included:&lt;br&gt;
Production frontend build: successful&lt;br&gt;
git diff --check: clean&lt;br&gt;
Marketplace regression suite: passed&lt;br&gt;
Vercel preview deployments: successful&lt;br&gt;
Main CI workflow: successful&lt;br&gt;
Production deployment: successful&lt;br&gt;
The public Metaverse route was also loaded after deployment.&lt;br&gt;
Current architecture&lt;br&gt;
The current system can be summarized as:&lt;br&gt;
React Metaverse Client&lt;pre&gt;&lt;code&gt;  |
  | HTTPS
  | X-Metaverse-Session-Token
  v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Node.js / Express API&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  |
  | Session ownership middleware
  | Hash verification
  v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Metaverse Presence Storage&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  |
  v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Shared world synchronization&lt;br&gt;
This is a practical foundation, but it is not yet the final realtime architecture.&lt;br&gt;
What remains to be built&lt;br&gt;
Realtime communication&lt;br&gt;
The current synchronization model still depends on polling in important areas.&lt;br&gt;
We need a versioned realtime protocol supporting:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;authenticated WebSocket connections;&lt;/li&gt;
&lt;li&gt;session-to-connection binding;&lt;/li&gt;
&lt;li&gt;reconnect handling;&lt;/li&gt;
&lt;li&gt;ordered events;&lt;/li&gt;
&lt;li&gt;duplicate-event protection;&lt;/li&gt;
&lt;li&gt;presence expiration;&lt;/li&gt;
&lt;li&gt;backpressure;&lt;/li&gt;
&lt;li&gt;slow-client management.&lt;br&gt;
The protocol should remain usable by multiple clients, including future community-built and WebXR clients.&lt;br&gt;
Distributed rate limiting&lt;br&gt;
Per-process rate limiting is not enough when the backend runs across multiple instances.&lt;br&gt;
We need a distributed limiter for:&lt;br&gt;
Session creation&lt;br&gt;
Authentication attempts&lt;br&gt;
Movement&lt;br&gt;
Chat&lt;br&gt;
Emotes&lt;br&gt;
Reconnects&lt;br&gt;
Limits should be calculated using combinations of:&lt;/li&gt;
&lt;li&gt;IP address;&lt;/li&gt;
&lt;li&gt;account ID;&lt;/li&gt;
&lt;li&gt;session ID;&lt;/li&gt;
&lt;li&gt;route;&lt;/li&gt;
&lt;li&gt;world ID;&lt;/li&gt;
&lt;li&gt;time window.&lt;br&gt;
Chat and authentication need stricter limits than normal movement updates.&lt;br&gt;
Session expiration and revocation&lt;br&gt;
The possession credential is now implemented, but lifecycle controls still need improvement:&lt;/li&gt;
&lt;li&gt;explicit expiration;&lt;/li&gt;
&lt;li&gt;server-side revocation;&lt;/li&gt;
&lt;li&gt;abandoned-session cleanup;&lt;/li&gt;
&lt;li&gt;token rotation;&lt;/li&gt;
&lt;li&gt;reconnect-safe renewal;&lt;/li&gt;
&lt;li&gt;active-session limits;&lt;/li&gt;
&lt;li&gt;multi-device logout;&lt;/li&gt;
&lt;li&gt;suspicious-session invalidation.&lt;br&gt;
Canonical authentication&lt;br&gt;
Verified characters require a stable account-linking process.&lt;br&gt;
The remaining work includes:&lt;/li&gt;
&lt;li&gt;canonical GitHub OAuth;&lt;/li&gt;
&lt;li&gt;verified account-to-character relationships;&lt;/li&gt;
&lt;li&gt;account-link substitution protection;&lt;/li&gt;
&lt;li&gt;reauthorization;&lt;/li&gt;
&lt;li&gt;identity-change audit trails;&lt;/li&gt;
&lt;li&gt;account recovery procedures.&lt;br&gt;
The backend must never trust a GitHub username supplied directly by a browser.&lt;br&gt;
Privacy-safe analytics&lt;br&gt;
We need enough telemetry to maintain the platform without introducing unnecessary tracking.&lt;br&gt;
Useful operational metrics include:&lt;/li&gt;
&lt;li&gt;concurrent sessions;&lt;/li&gt;
&lt;li&gt;API latency;&lt;/li&gt;
&lt;li&gt;reconnect frequency;&lt;/li&gt;
&lt;li&gt;server errors;&lt;/li&gt;
&lt;li&gt;world capacity;&lt;/li&gt;
&lt;li&gt;rate-limit events;&lt;/li&gt;
&lt;li&gt;event throughput.&lt;br&gt;
Retention, aggregation and access rules must be documented before expanding analytics.&lt;br&gt;
Reliability and load testing&lt;br&gt;
Future tests must simulate:&lt;/li&gt;
&lt;li&gt;simultaneous joins;&lt;/li&gt;
&lt;li&gt;movement bursts;&lt;/li&gt;
&lt;li&gt;reconnect storms;&lt;/li&gt;
&lt;li&gt;malformed messages;&lt;/li&gt;
&lt;li&gt;database latency;&lt;/li&gt;
&lt;li&gt;backend restarts;&lt;/li&gt;
&lt;li&gt;multiple server instances;&lt;/li&gt;
&lt;li&gt;slow or disconnected clients.&lt;br&gt;
We also need measurable targets for latency, error rate, recovery time and maximum concurrent participants.&lt;br&gt;
Complete E2E acceptance testing&lt;br&gt;
The complete guest flow should be automated:&lt;br&gt;
Join&lt;br&gt;
→ receive credential&lt;br&gt;
→ become visible&lt;br&gt;
→ move&lt;br&gt;
→ chat&lt;br&gt;
→ publish an emote&lt;br&gt;
→ reject impersonation attempts&lt;br&gt;
→ reconnect safely&lt;br&gt;
→ leave or expire&lt;br&gt;
The same acceptance flow is required for verified characters.&lt;br&gt;
WebXR&lt;br&gt;
WebXR remains part of the roadmap, but it should follow security and realtime stabilization.&lt;br&gt;
The eventual world protocol should support:&lt;br&gt;
2D web client&lt;br&gt;
3D browser client&lt;br&gt;
WebXR client&lt;br&gt;
Mobile client&lt;br&gt;
Independent community clients&lt;br&gt;
All clients should use the same documented API and event protocol.&lt;br&gt;
Dependency-security debt&lt;br&gt;
The repository currently reports vulnerabilities during npm audit.&lt;br&gt;
These findings were already present and were not introduced by the Metaverse session-ownership pull request, which did not change package manifests or lockfiles.&lt;br&gt;
However, they remain technical debt.&lt;br&gt;
A separate dependency-hardening milestone should include:&lt;ol&gt;
&lt;li&gt;classifying production and development exposure;&lt;/li&gt;
&lt;li&gt;updating direct dependencies;&lt;/li&gt;
&lt;li&gt;reviewing transitive dependencies;&lt;/li&gt;
&lt;li&gt;replacing abandoned packages;&lt;/li&gt;
&lt;li&gt;regenerating lockfiles;&lt;/li&gt;
&lt;li&gt;running complete regression tests;&lt;/li&gt;
&lt;li&gt;updating SBOM and audit evidence.&lt;br&gt;
Disabling the audit to produce a green badge would hide the problem instead of solving it.&lt;br&gt;
Recommended roadmap&lt;br&gt;
The recommended implementation sequence is:&lt;/li&gt;
&lt;li&gt;Session expiration and revocation&lt;/li&gt;
&lt;li&gt;Distributed rate limiting&lt;/li&gt;
&lt;li&gt;Canonical account authentication&lt;/li&gt;
&lt;li&gt;Versioned realtime protocol&lt;/li&gt;
&lt;li&gt;Authenticated WebSocket transport&lt;/li&gt;
&lt;li&gt;Privacy-safe monitoring&lt;/li&gt;
&lt;li&gt;Reliability and load testing&lt;/li&gt;
&lt;li&gt;Complete E2E acceptance tests&lt;/li&gt;
&lt;li&gt;Dependency-security remediation&lt;/li&gt;
&lt;li&gt;WebXR client development&lt;br&gt;
Security, reliability and protocol stability must come before graphical complexity.&lt;br&gt;
Open-source participation&lt;br&gt;
We are looking for contributors interested in:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;React;&lt;/li&gt;
&lt;li&gt;Node.js and Express;&lt;/li&gt;
&lt;li&gt;MongoDB;&lt;/li&gt;
&lt;li&gt;Redis;&lt;/li&gt;
&lt;li&gt;WebSockets;&lt;/li&gt;
&lt;li&gt;application security;&lt;/li&gt;
&lt;li&gt;privacy engineering;&lt;/li&gt;
&lt;li&gt;abuse prevention;&lt;/li&gt;
&lt;li&gt;load testing;&lt;/li&gt;
&lt;li&gt;WebXR;&lt;/li&gt;
&lt;li&gt;technical documentation.&lt;br&gt;
Repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/danieldirimini-myzubster/myzubster&quot;&gt;https://github.com/danieldirimini-myzubster/myzubster&lt;/a&gt;&lt;br&gt;
Public Metaverse:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;br&gt;
Security implementation:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/danieldirimini-myzubster/myzubster/pull/34&quot;&gt;https://github.com/danieldirimini-myzubster/myzubster/pull/34&lt;/a&gt;&lt;br&gt;
Conclusion&lt;br&gt;
The MyZubster Metaverse now has a stronger session-security foundation.&lt;br&gt;
We moved from public identifier-based operations to possession-bound authorization using:&lt;/li&gt;
&lt;li&gt;256-bit random credentials;&lt;/li&gt;
&lt;li&gt;SHA-256 token digests;&lt;/li&gt;
&lt;li&gt;constant-time verification;&lt;/li&gt;
&lt;li&gt;dedicated authorization headers;&lt;/li&gt;
&lt;li&gt;memory-only client credentials;&lt;/li&gt;
&lt;li&gt;protected world routes;&lt;/li&gt;
&lt;li&gt;backend and frontend security tests.&lt;br&gt;
The next milestone is transforming this foundation into a distributed realtime system with strong authentication, rate limiting, privacy-safe observability and measurable reliability.&lt;br&gt;
The Metaverse is online, but the deeper work is still ahead: building an open world protocol that other developers can inspect, test and extend.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31491/how-secured-the-myzubster-metaverse-session-ownership-verified-explorers-and-road-realti</guid>
<pubDate>Sat, 17 Oct 2026 05:20:55 +0000</pubDate>
</item>
<item>
<title>Engineering a Browser-First Metaverse: WebXR Fallbacks, Server-Authoritative Rooms, and Versioned</title>
<link>https://coderlegion.com/30813/engineering-browser-first-metaverse-webxr-fallbacks-server-authoritative-rooms-versioned</link>
<description>&lt;p&gt;Engineering a Browser-First Metaverse: WebXR Fallbacks, Server-Authoritative Rooms, and Versioned Scene Manifests&lt;/p&gt;
&lt;p&gt;The MyZubster Metaverse is being developed as a browser-first platform rather than a VR-only application.&lt;br&gt;
Our baseline requirement is straightforward:&lt;br&gt;
A user must be able to access the experience from a normal desktop or mobile browser. WebXR should enhance the experience when available, but its absence must never block access.&lt;/p&gt;
&lt;p&gt;During the latest development cycle, we implemented two foundational components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A browser and WebXR capability-detection layer with graceful fallback&lt;/li&gt;
&lt;li&gt;A versioned scene-manifest contract validated by the backend before publication&lt;br&gt;
This article explains the architecture, implementation details, validation rules, current production evidence, and the remaining roadmap.&lt;br&gt;
Project Links&lt;ul&gt;
&lt;li&gt;Repository: MyZubster-Ecosystem/myzubster&lt;/li&gt;
&lt;li&gt;Live Metaverse: myzubster.com/metaverse&lt;/li&gt;
&lt;li&gt;WebXR fallback: Pull Request #1597&lt;/li&gt;
&lt;li&gt;Scene-manifest validation: Pull Request #1601&lt;/li&gt;
&lt;li&gt;LIFE Pilot entry point: myzubster.com/life-pilot&lt;br&gt;
System Architecture&lt;br&gt;
The current metaverse architecture separates device capabilities, presentation, room authority, scene configuration, and evidence.&lt;br&gt;
┌─────────────────────────────────────────────────────────┐&lt;br&gt;
│                    React Browser UI                     │&lt;br&gt;
│                                                         │&lt;br&gt;
│ Capability checks → status UI → browser/WebXR fallback  │&lt;br&gt;
└────────────────────────────┬────────────────────────────┘&lt;pre&gt;&lt;code&gt;                    │
                    ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;┌─────────────────────────────────────────────────────────┐&lt;br&gt;
│                  Metaverse Client Runtime               │&lt;br&gt;
│                                                         │&lt;br&gt;
│ Scene loading → controls → chat → emotes → interactions │&lt;br&gt;
└────────────────────────────┬────────────────────────────┘&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                    │
                    ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;┌─────────────────────────────────────────────────────────┐&lt;br&gt;
│                 Server-Authoritative API                │&lt;br&gt;
│                                                         │&lt;br&gt;
│ Rooms → sessions → access → capacity → stage → tokens   │&lt;br&gt;
└────────────────────────────┬────────────────────────────┘&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                    │
                    ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;┌─────────────────────────────────────────────────────────┐&lt;br&gt;
│                  Versioned Scene Contract               │&lt;br&gt;
│                                                         │&lt;br&gt;
│ Assets → spawn points → zones → portals → capabilities  │&lt;br&gt;
└────────────────────────────┬────────────────────────────┘&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                    │
                    ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;┌─────────────────────────────────────────────────────────┐&lt;br&gt;
│                    LIFE Evidence Layer                  │&lt;br&gt;
│                                                         │&lt;br&gt;
│ Pilot → provenance → evidence → KPI/MRV → visualization │&lt;br&gt;
└─────────────────────────────────────────────────────────┘&lt;br&gt;
The separation creates several important boundaries:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;The browser reports its capabilities.&lt;/li&gt;
&lt;li&gt;The server decides whether a room transition is valid.&lt;/li&gt;
&lt;li&gt;The manifest describes what the client may load.&lt;/li&gt;
&lt;li&gt;The evidence layer determines what real-world claims can be displayed.&lt;/li&gt;
&lt;li&gt;The 3D client is never the authority for authentication or environmental evidence.&lt;br&gt;
What Currently Works&lt;br&gt;
Neon Plaza can be entered through a normal browser without installing a native application or connecting a VR headset.&lt;br&gt;
In a production desktop smoke test, we verified:&lt;/li&gt;
&lt;li&gt;Authenticated access&lt;/li&gt;
&lt;li&gt;Character-associated entry&lt;/li&gt;
&lt;li&gt;Neon Plaza loading&lt;/li&gt;
&lt;li&gt;An active online session&lt;/li&gt;
&lt;li&gt;Movement controls&lt;/li&gt;
&lt;li&gt;Emotes&lt;/li&gt;
&lt;li&gt;Room chat&lt;/li&gt;
&lt;li&gt;Browser capability detection&lt;/li&gt;
&lt;li&gt;Non-blocking fallback when immersive WebXR is unavailable&lt;br&gt;
This was a desktop production verification. Real mobile devices and physical WebXR headsets still require a structured validation matrix.&lt;br&gt;
Part 1: Browser and WebXR Capability Detection&lt;br&gt;
The first milestone was implemented in PR #1597.&lt;br&gt;
Explicit WebXR States&lt;br&gt;
WebXR availability is not represented as a simple boolean.&lt;br&gt;
export const WEBXR_STATUS = Object.freeze({&lt;br&gt;
CHECKING: 'checking',&lt;br&gt;
SUPPORTED: 'supported',&lt;br&gt;
UNSUPPORTED: 'unsupported',&lt;br&gt;
ERROR: 'error'&lt;br&gt;
});&lt;br&gt;
This distinguishes between four different conditions:&lt;br&gt;
checking&lt;br&gt;
│&lt;br&gt;
├── supported&lt;br&gt;
├── unsupported&lt;br&gt;
└── error&lt;br&gt;
A browser that does not expose navigator.xr is different from a browser that exposes the API but fails during capability detection.&lt;br&gt;
That distinction is useful for both debugging and user communication.&lt;br&gt;
Browser Baseline&lt;br&gt;
The client checks a small browser baseline independently of WebXR:&lt;br&gt;
export function browserCapabilityBaseline(browser = window) {&lt;br&gt;
return [
 {
 label: 'JavaScript',
 ok: true
 },
 {
 label: 'Fetch API',
 ok: typeof browser.fetch === 'function'
 },
 {
 label: 'Local storage',
 ok: Boolean(browser.localStorage)
 },
 {
 label: 'CSS Grid',
 ok: Boolean(
   browser.CSS?.supports?.('display', 'grid')
 )
 },
 {
 label: 'Connection',
 ok: browser.navigator?.onLine !== false
 }
];&lt;br&gt;
}&lt;br&gt;
WebXR is checked separately because it is an enhancement rather than a baseline dependency.&lt;br&gt;
Detecting Immersive VR&lt;br&gt;
The detection function accepts a navigator-like dependency:&lt;br&gt;
export async function detectImmersiveVr(&lt;br&gt;
navigatorLike = navigator&lt;br&gt;
) {&lt;br&gt;
if (!navigatorLike?.xr?.isSessionSupported) {&lt;br&gt;
 return {&lt;br&gt;
 status: WEBXR_STATUS.UNSUPPORTED,&lt;br&gt;
 reason: 'api-unavailable'&lt;br&gt;
 };&lt;br&gt;
}&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;  try {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const supported =
  await navigatorLike.xr.isSessionSupported(
    'immersive-vr'
  );

return {
  status: supported
    ? WEBXR_STATUS.SUPPORTED
    : WEBXR_STATUS.UNSUPPORTED,

  reason: supported
    ? null
    : 'session-unsupported'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  } catch (_error) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  status: WEBXR_STATUS.ERROR,
  reason: 'capability-check-failed'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
}&lt;br&gt;
Passing navigatorLike as an argument makes the function easier to test.&lt;br&gt;
For example:&lt;br&gt;
const fakeNavigator = {&lt;br&gt;
  xr: {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;isSessionSupported: async (mode) =&amp;gt;
  mode === 'immersive-vr'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
};&lt;/p&gt;
&lt;p&gt;const result =&lt;br&gt;
  await detectImmersiveVr(fakeNavigator);&lt;/p&gt;
&lt;p&gt;expect(result.status).toBe('supported');&lt;br&gt;
The unsupported case can also be tested without a real headset:&lt;br&gt;
const result =&lt;br&gt;
  await detectImmersiveVr({});&lt;/p&gt;
&lt;p&gt;expect(result).toEqual({&lt;br&gt;
  status: 'unsupported',&lt;br&gt;
  reason: 'api-unavailable'&lt;br&gt;
});&lt;br&gt;
Non-Blocking Fallback&lt;br&gt;
The UI maps the capability state to a user-facing message:&lt;br&gt;
const XR_COPY = {&lt;br&gt;
  [WEBXR_STATUS.CHECKING]:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'Checking WebXR support…',
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  [WEBXR_STATUS.SUPPORTED]:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'Immersive WebXR is available',
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  [WEBXR_STATUS.UNSUPPORTED]:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'Browser mode active: a headset is not required',
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  [WEBXR_STATUS.ERROR]:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'WebXR could not be verified: continue in browser mode'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;};&lt;br&gt;
The important behavior is that an unsupported or failed WebXR check does not produce a fatal application state.&lt;br&gt;
{xr.status !== WEBXR_STATUS.SUPPORTED &amp;amp;&amp;amp; (&lt;br&gt;
  &lt;small&gt;&lt;/small&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Neon Plaza remains accessible from desktop and mobile.
The WebXR check never blocks entry.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  &lt;br&gt;
)}&lt;br&gt;
The capability model therefore follows progressive enhancement:&lt;br&gt;
Standard browser&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browser-based Neon Plaza&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Optional capabilities&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ├── WebGL enhancements
  ├── spatial audio
  ├── immersive WebXR
  └── headset controllers
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Part 2: Server-Authoritative Room State&lt;br&gt;
The metaverse room lifecycle is enforced by the backend rather than trusted to client-side state.&lt;br&gt;
Forward-Only State Machine&lt;br&gt;
The backend defines valid transitions:&lt;br&gt;
const ROOM_TRANSITIONS = Object.freeze({&lt;br&gt;
  draft: new Set(['published']),&lt;br&gt;
  published: new Set(['scheduled', 'live']),&lt;br&gt;
  scheduled: new Set(['live']),&lt;br&gt;
  live: new Set(['ended']),&lt;br&gt;
  ended: new Set(['archive']),&lt;br&gt;
  archive: new Set([])&lt;br&gt;
});&lt;br&gt;
The resulting lifecycle is:&lt;br&gt;
draft&lt;br&gt;
  │&lt;br&gt;
  ▼&lt;br&gt;
published&lt;br&gt;
  │&lt;br&gt;
  ├──────────────┐&lt;br&gt;
  ▼              ▼&lt;br&gt;
scheduled       live&lt;br&gt;
  │              │&lt;br&gt;
  └──────►───────┘&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;             ▼
           ended
             │
             ▼
          archive
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The backend rejects invalid transitions:&lt;br&gt;
if (&lt;br&gt;
  patch.state &amp;amp;&amp;amp;&lt;br&gt;
  patch.state !== room.state&lt;br&gt;
) {&lt;br&gt;
  const allowed =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ROOM_TRANSITIONS[room.state]?.has(patch.state);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  if (!allowed) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 409,
  error:
    `Invalid room transition ` +
    `${room.state} -&amp;gt; ${patch.state}`
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  room.state = patch.state;&lt;br&gt;
}&lt;br&gt;
A modified browser therefore cannot return an ended room to the live state simply by changing its local representation.&lt;br&gt;
Access Policies&lt;br&gt;
Rooms support three access policies:&lt;br&gt;
accessPolicy: {&lt;br&gt;
  type: String,&lt;br&gt;
  enum: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'public',
'authenticated',
'private'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ],&lt;br&gt;
  default: 'authenticated'&lt;br&gt;
}&lt;br&gt;
The room model also includes bounded capacity:&lt;br&gt;
capacity: {&lt;br&gt;
  type: Number,&lt;br&gt;
  min: 1,&lt;br&gt;
  max: 500,&lt;br&gt;
  default: 100&lt;br&gt;
}&lt;br&gt;
Join Validation&lt;br&gt;
Before joining, the backend checks session state, blocklists, private-room access, and capacity:&lt;br&gt;
async function validateJoin({&lt;br&gt;
  session,&lt;br&gt;
  room,&lt;br&gt;
  actorUserId&lt;br&gt;
}) {&lt;br&gt;
  if (session.state !== 'live') {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 409,
  error: 'Session is not live'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  const actor = String(actorUserId);&lt;/p&gt;
&lt;p&gt;  if ((room.blockedUserIds || []).includes(actor)) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 403,
  error: 'Access blocked'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  const privateAccessDenied =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;room.accessPolicy === 'private' &amp;amp;&amp;amp;
!(room.allowedUserIds || []).includes(actor) &amp;amp;&amp;amp;
actor !== String(room.hostUserId);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  if (privateAccessDenied) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 403,
  error: 'Private room access denied'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  const current =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;new Set(session.participantUserIds || []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  const capacityReached =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;!current.has(actor) &amp;amp;&amp;amp;
current.size &amp;gt;= session.capacity;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  if (capacityReached) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 409,
  error: 'Session is at capacity'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  return { valid: true };&lt;br&gt;
}&lt;br&gt;
This is important because client-side room membership cannot be considered authoritative.&lt;br&gt;
Part 3: Realtime Session Tokens&lt;br&gt;
After a successful join, the backend issues a short-lived token scoped to the metaverse session.&lt;br&gt;
function mintRealtimeToken(&lt;br&gt;
  session,&lt;br&gt;
  actorUserId&lt;br&gt;
) {&lt;br&gt;
  const secret =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;process.env.REALTIME_TOKEN_SECRET ||
process.env.JWT_SECRET;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  if (!secret) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;throw new Error(
  'Realtime token secret is not configured'
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  return jwt.sign({&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sub: String(actorUserId),
purpose: 'metaverse-realtime',
sessionId: session.sessionId,
roomId: session.roomId,
sceneManifestVersion:
  session.sceneManifestVersion
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }, secret, {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;expiresIn: '5m'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  });&lt;br&gt;
}&lt;br&gt;
The token binds the connection to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A user&lt;/li&gt;
&lt;li&gt;A specific purpose&lt;/li&gt;
&lt;li&gt;A session&lt;/li&gt;
&lt;li&gt;A room&lt;/li&gt;
&lt;li&gt;A scene-manifest version&lt;br&gt;
Using a dedicated purpose value reduces the risk of using a generic application token in the wrong context.&lt;br&gt;
The short expiration also limits the useful lifetime of a captured realtime credential.&lt;br&gt;
Future work will include:&lt;/li&gt;
&lt;li&gt;Token refresh&lt;/li&gt;
&lt;li&gt;Explicit revocation&lt;/li&gt;
&lt;li&gt;Reconnect behavior&lt;/li&gt;
&lt;li&gt;Redis-backed realtime coordination&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;li&gt;Multi-region latency handling&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replay-resistance analysis&lt;br&gt;
Part 4: Privacy-Aware Moderation References&lt;br&gt;
Moderation interfaces do not need to expose raw account IDs.&lt;br&gt;
The backend generates opaque session-scoped participant references:&lt;br&gt;
function moderationParticipantRef(&lt;br&gt;
sessionId,&lt;br&gt;
actorUserId&lt;br&gt;
) {&lt;br&gt;
return hashRoomInviteCode(&lt;br&gt;
  &lt;code&gt;${sessionId}:${actorUserId}&lt;/code&gt;&lt;br&gt;
).slice(0, 24);&lt;br&gt;
}&lt;br&gt;
Room blocklist references are scoped separately:&lt;br&gt;
function blockedParticipantRef(&lt;br&gt;
roomId,&lt;br&gt;
actorUserId&lt;br&gt;
) {&lt;br&gt;
return hashRoomInviteCode(&lt;br&gt;
  &lt;code&gt;blocklist:${roomId}:${actorUserId}&lt;/code&gt;&lt;br&gt;
).slice(0, 24);&lt;br&gt;
}&lt;br&gt;
The public session response returns a count rather than the participant-ID array:&lt;br&gt;
function publicSession(session) {&lt;br&gt;
return {&lt;br&gt;
  id: session.sessionId,&lt;br&gt;
  roomId: session.roomId,&lt;br&gt;
  state: session.state,&lt;br&gt;
  capacity: session.capacity,&lt;/p&gt;
&lt;p&gt;  participantCount:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(session.participantUserIds || []).length,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  sceneManifestVersion:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;session.sceneManifestVersion,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  lifecycleVersion:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;session.lifecycleVersion,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  startedAt: session.startedAt || null,&lt;br&gt;
  endedAt: session.endedAt || null&lt;br&gt;
};&lt;br&gt;
}&lt;br&gt;
This does not provide anonymity by itself, but it limits unnecessary identifier exposure.&lt;br&gt;
Part 5: Versioned Scene Manifest v1&lt;br&gt;
The next milestone was delivered in PR #1601.&lt;br&gt;
The manifest is the contract between:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Room configuration&lt;/li&gt;
&lt;li&gt;Backend validation&lt;/li&gt;
&lt;li&gt;Client runtime&lt;/li&gt;
&lt;li&gt;Asset delivery&lt;/li&gt;
&lt;li&gt;Capability requirements&lt;/li&gt;
&lt;li&gt;Future rollback behavior&lt;br&gt;
Supported Contract Values&lt;br&gt;
const SCENE_MANIFEST_SCHEMA_VERSION = '1';&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;const ASSET_TYPES = new Set([
  'gltf',
  'glb',
  'image',
  'audio',
  'video'
]);&lt;/p&gt;
&lt;p&gt;const ZONE_TYPES = new Set([
  'portal',
  'stage',
  'link'
]);&lt;/p&gt;
&lt;p&gt;const LIGHTING_PRESETS = new Set([
  'day',
  'sunset',
  'night',
  'studio'
]);&lt;/p&gt;
&lt;p&gt;const CAPABILITIES = new Set([
  'webgl2',
  'webxr-immersive-vr',
  'audio',
  'video'
]);&lt;br&gt;
The schema is deliberately constrained.&lt;br&gt;
An unrestricted JSON document would make compatibility, validation, migration, and rollback increasingly difficult.&lt;br&gt;
Safe Default Manifest&lt;br&gt;
New rooms receive a minimal valid scene definition:&lt;br&gt;
function defaultSceneManifest() {&lt;br&gt;
  return {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;schemaVersion:
  SCENE_MANIFEST_SCHEMA_VERSION,

assetBundleVersion: '1',

assets: [],

spawnPoints: [
  {
    id: 'default',
    position: [0, 0, 0]
  }
],

interactionZones: [],

stage: {
  position: [0, 0, 0],
  capacity: 1
},

lighting: {
  preset: 'day'
},

capabilities: []
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  };&lt;br&gt;
}&lt;br&gt;
The room creation service applies it automatically:&lt;br&gt;
const room = await VirtualRoom.create({&lt;br&gt;
  roomId: crypto.randomUUID(),&lt;br&gt;
  slug: safeSlug,&lt;br&gt;
  name: safeName,&lt;br&gt;
  hostUserId: String(actorUserId),&lt;br&gt;
  accessPolicy,&lt;br&gt;
  capacity: numericCapacity,&lt;br&gt;
  stagePolicy,&lt;br&gt;
  sceneManifest: defaultSceneManifest()&lt;br&gt;
});&lt;br&gt;
This avoids creating rooms with an undefined scene state.&lt;br&gt;
Example Scene Manifest&lt;br&gt;
A more complete manifest could look like this:&lt;br&gt;
{&lt;br&gt;
  &quot;schemaVersion&quot;: &quot;1&quot;,&lt;br&gt;
  &quot;assetBundleVersion&quot;: &quot;42&quot;,&lt;br&gt;
  &quot;assets&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;neon-plaza&quot;,
  &quot;type&quot;: &quot;glb&quot;,
  &quot;url&quot;: &quot;https://cdn.myzubster.com/scenes/neon-plaza.42.glb&quot;
},
{
  &quot;id&quot;: &quot;ambient-audio&quot;,
  &quot;type&quot;: &quot;audio&quot;,
  &quot;url&quot;: &quot;https://cdn.myzubster.com/audio/neon-plaza.7.ogg&quot;
},
{
  &quot;id&quot;: &quot;life-dashboard&quot;,
  &quot;type&quot;: &quot;image&quot;,
  &quot;url&quot;: &quot;https://cdn.myzubster.com/life/dashboard.12.webp&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ],&lt;br&gt;
  &quot;spawnPoints&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;main-entrance&quot;,
  &quot;position&quot;: [0, 1.6, 4]
},
{
  &quot;id&quot;: &quot;life-hub&quot;,
  &quot;position&quot;: [12, 1.6, -3]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ],&lt;br&gt;
  &quot;interactionZones&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;id&quot;: &quot;life-portal&quot;,
  &quot;type&quot;: &quot;portal&quot;,
  &quot;position&quot;: [10, 0, -3],
  &quot;radius&quot;: 1.5,
  &quot;destination&quot;: &quot;life-hub&quot;
},
{
  &quot;id&quot;: &quot;pilot-details&quot;,
  &quot;type&quot;: &quot;link&quot;,
  &quot;position&quot;: [14, 1, -4],
  &quot;radius&quot;: 1,
  &quot;destination&quot;: &quot;https://www.myzubster.com/life-pilot&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ],&lt;br&gt;
  &quot;stage&quot;: {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;position&quot;: [0, 0, -8],
&quot;capacity&quot;: 30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  &quot;lighting&quot;: {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;preset&quot;: &quot;sunset&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  &quot;capabilities&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;webgl2&quot;,
&quot;audio&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ]&lt;br&gt;
}&lt;br&gt;
The manifest contains only declarative scene information. It does not grant permissions or override room authority.&lt;br&gt;
Part 6: Manifest Validation&lt;br&gt;
Identifier Validation&lt;br&gt;
Identifiers use a restricted character set:&lt;br&gt;
function validId(value) {&lt;br&gt;
  return (&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typeof value === 'string' &amp;amp;&amp;amp;
/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(value)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
This avoids IDs containing markup, control characters, or unexpected path syntax.&lt;br&gt;
Vector Validation&lt;br&gt;
Positions must contain exactly three finite values:&lt;br&gt;
function validVector(value) {&lt;br&gt;
  return (&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Array.isArray(value) &amp;amp;&amp;amp;
value.length === 3 &amp;amp;&amp;amp;
value.every(Number.isFinite)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
These values are invalid:&lt;br&gt;
[0, 1]
[0, 1, null]&lt;br&gt;
[0, 1, NaN]
[0, 1, Infinity]&lt;br&gt;
HTTPS-Only URLs&lt;br&gt;
External resources must use HTTPS:&lt;br&gt;
function validHttpsUrl(value) {&lt;br&gt;
  if (&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typeof value !== 'string' ||
value.length &amp;gt; 2048
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return false;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  try {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return new URL(value).protocol === 'https:';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  } catch {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return false;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
}&lt;br&gt;
This rejects examples such as:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;http://example.com/scene.glb&quot;&gt;http://example.com/scene.glb&lt;/a&gt;&lt;br&gt;
javascript:alert(1)&lt;br&gt;
invalid-url&lt;br&gt;
HTTPS is only the first boundary. Future validation should also enforce:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Approved asset origins&lt;/li&gt;
&lt;li&gt;Content-Type checks&lt;/li&gt;
&lt;li&gt;Download timeouts&lt;/li&gt;
&lt;li&gt;File-size limits&lt;/li&gt;
&lt;li&gt;Redirect restrictions&lt;/li&gt;
&lt;li&gt;Content hashes&lt;/li&gt;
&lt;li&gt;glTF structural validation&lt;/li&gt;
&lt;li&gt;Geometry budgets&lt;/li&gt;
&lt;li&gt;Texture budgets&lt;/li&gt;
&lt;li&gt;CORS requirements&lt;br&gt;
Bounded Collections&lt;br&gt;
Manifest collections are explicitly bounded:&lt;br&gt;
if (&lt;br&gt;
!Array.isArray(input.assets) ||&lt;br&gt;
input.assets.length &amp;gt; 100&lt;br&gt;
) {&lt;br&gt;
errors.push(&lt;br&gt;
  'assets must be an array with at most 100 entries'&lt;br&gt;
);&lt;br&gt;
}&lt;br&gt;
Spawn points require at least one entry and allow a maximum of 32:&lt;br&gt;
if (&lt;br&gt;
!Array.isArray(input.spawnPoints) ||&lt;br&gt;
input.spawnPoints.length &amp;lt; 1 ||&lt;br&gt;
input.spawnPoints.length &amp;gt; 32&lt;br&gt;
) {&lt;br&gt;
errors.push(&lt;br&gt;
  'spawnPoints must contain between 1 and 32 entries'&lt;br&gt;
);&lt;br&gt;
}&lt;br&gt;
These limits reduce accidental or malicious resource amplification before the runtime even begins downloading scene assets.&lt;br&gt;
Part 7: Publication Gate&lt;br&gt;
A scene is validated when its manifest is updated and again when the room is published.&lt;br&gt;
const manifestCandidate =&lt;br&gt;
patch.sceneManifest !== undefined&lt;br&gt;
  ? patch.sceneManifest&lt;br&gt;
  : room.sceneManifest;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;if (&lt;br&gt;
  patch.sceneManifest !== undefined ||&lt;br&gt;
  patch.state === 'published'&lt;br&gt;
) {&lt;br&gt;
  const validation =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;validateSceneManifest(manifestCandidate);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  if (!validation.valid) {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;return {
  valid: false,
  status: 400,
  error: 'Invalid scene manifest',
  details: validation.errors
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;/p&gt;
&lt;p&gt;  room.sceneManifest =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;validation.manifest;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;br&gt;
This establishes an important invariant:&lt;br&gt;
Invalid scene manifest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;      │
      ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Backend validation failure&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;      │
      ▼
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Publication rejected&lt;br&gt;
The frontend may eventually provide immediate validation feedback, but frontend checks are not authoritative.&lt;br&gt;
An API consumer could bypass the official interface. The backend must enforce the contract independently.&lt;br&gt;
Part 8: Persistence Model&lt;br&gt;
The room currently stores:&lt;br&gt;
sceneManifestVersion: {&lt;br&gt;
  type: String,&lt;br&gt;
  default: '1'&lt;br&gt;
},&lt;/p&gt;
&lt;p&gt;sceneManifest: {&lt;br&gt;
  type: mongoose.Schema.Types.Mixed,&lt;br&gt;
  default: null&lt;br&gt;
}&lt;br&gt;
The public room response includes both fields:&lt;br&gt;
function publicRoom(room) {&lt;br&gt;
  return {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;id: room.roomId,
slug: room.slug,
name: room.name,
state: room.state,
accessPolicy: room.accessPolicy,
capacity: room.capacity,
stagePolicy: room.stagePolicy,
sceneManifestVersion:
  room.sceneManifestVersion,
sceneManifest:
  room.sceneManifest || null,
scheduledFor:
  room.scheduledFor || null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  };&lt;br&gt;
}&lt;br&gt;
This is sufficient for the current validation milestone, but the next persistence model should introduce immutable historical versions.&lt;br&gt;
Part 9: Automated Tests&lt;br&gt;
The manifest tests cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The safe default manifest&lt;/li&gt;
&lt;li&gt;Versioned asset bundles&lt;/li&gt;
&lt;li&gt;HTTPS asset references&lt;/li&gt;
&lt;li&gt;Valid spawn points&lt;/li&gt;
&lt;li&gt;Valid interaction zones&lt;/li&gt;
&lt;li&gt;Portal destinations&lt;/li&gt;
&lt;li&gt;Unsupported schema versions&lt;/li&gt;
&lt;li&gt;Insecure URLs&lt;/li&gt;
&lt;li&gt;Malformed vectors&lt;/li&gt;
&lt;li&gt;Duplicate IDs&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unsupported capabilities&lt;br&gt;
Example:&lt;br&gt;
test(&lt;br&gt;
'rejects unsupported schema versions and insecure asset URLs',&lt;br&gt;
() =&amp;gt; {&lt;br&gt;
  const manifest = {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...defaultSceneManifest(),

schemaVersion: '2',

assets: [{
  id: 'plaza',
  type: 'glb',
  url: 'http://cdn.example.com/plaza.glb'
}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  };&lt;/p&gt;
&lt;p&gt;  const result =&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;validateSceneManifest(manifest);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  expect(result.valid).toBe(false);&lt;/p&gt;
&lt;p&gt;  expect(result.errors).toEqual(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;expect.arrayContaining([
  'schemaVersion must be 1',
  'assets[0].url must use https'
])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
);&lt;br&gt;
The implementation passed:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Backend lint&lt;/li&gt;
&lt;li&gt;Backend unit tests&lt;/li&gt;
&lt;li&gt;Frontend unit tests&lt;/li&gt;
&lt;li&gt;Backend build&lt;/li&gt;
&lt;li&gt;Frontend build&lt;/li&gt;
&lt;li&gt;Security audit&lt;/li&gt;
&lt;li&gt;Continuous evidence checks&lt;br&gt;
Production Evidence and Current Limits&lt;br&gt;
The following behavior was verified against the production desktop experience:&lt;/li&gt;
&lt;li&gt;Authentication was active&lt;/li&gt;
&lt;li&gt;Neon Plaza loaded&lt;/li&gt;
&lt;li&gt;The session appeared online&lt;/li&gt;
&lt;li&gt;Movement controls were visible&lt;/li&gt;
&lt;li&gt;Emotes were available&lt;/li&gt;
&lt;li&gt;Chat was available&lt;/li&gt;
&lt;li&gt;The capability panel rendered&lt;/li&gt;
&lt;li&gt;Browser baseline checks passed&lt;/li&gt;
&lt;li&gt;WebXR fallback messaging appeared&lt;/li&gt;
&lt;li&gt;The browser experience remained available without immersive WebXR&lt;br&gt;
The following items remain unverified or incomplete:&lt;/li&gt;
&lt;li&gt;Real-device Android testing&lt;/li&gt;
&lt;li&gt;Real-device iOS testing&lt;/li&gt;
&lt;li&gt;Physical WebXR headset entry and exit&lt;/li&gt;
&lt;li&gt;Controller compatibility&lt;/li&gt;
&lt;li&gt;Long-running realtime reliability&lt;/li&gt;
&lt;li&gt;High-concurrency room testing&lt;/li&gt;
&lt;li&gt;Versioned CDN asset loading&lt;/li&gt;
&lt;li&gt;Manifest rollback&lt;/li&gt;
&lt;li&gt;Full accessibility verification&lt;/li&gt;
&lt;li&gt;Complete LIFE evidence integration&lt;br&gt;
This separation is intentional. A roadmap entry is not evidence that a capability is complete.&lt;br&gt;
Connecting the Metaverse to LIFE&lt;br&gt;
MyZubster is also exploring LIFE-oriented environmental and circular-economy workflows.&lt;br&gt;
The metaverse can provide a public and educational interface for those projects, but it must not replace the underlying evidence system.&lt;br&gt;
The proposed flow is:&lt;br&gt;
Real-world pilot&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Measurement or observation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Data provenance&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evidence classification&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;KPI / MRV calculation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MyZubster project record&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Metaverse representation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Educational mission&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Community feedback&lt;br&gt;
A scene might contain:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;A portal to a pilot&lt;/li&gt;
&lt;li&gt;A visualization of measurements&lt;/li&gt;
&lt;li&gt;A description of the methodology&lt;/li&gt;
&lt;li&gt;A list of missing evidence&lt;/li&gt;
&lt;li&gt;A contribution mission&lt;/li&gt;
&lt;li&gt;Replication instructions&lt;/li&gt;
&lt;li&gt;KPI and MRV status&lt;br&gt;
However:&lt;br&gt;
3D visualization ≠ verified measurement&lt;br&gt;
simulation ≠ field result&lt;br&gt;
self-declaration ≠ independent validation&lt;br&gt;
project goal ≠ achieved environmental impact&lt;br&gt;
These distinctions should be visible in the interface.&lt;br&gt;
Possible Evidence Contract&lt;br&gt;
A future scene object could include an evidence reference:&lt;br&gt;
{&lt;br&gt;
&quot;id&quot;: &quot;water-savings-display&quot;,&lt;br&gt;
&quot;type&quot;: &quot;evidence-panel&quot;,&lt;br&gt;
&quot;position&quot;: [4, 1.5, -2],&lt;br&gt;
&quot;evidence&quot;: {&lt;br&gt;
  &quot;status&quot;: &quot;measured&quot;,&lt;br&gt;
  &quot;source&quot;: &quot;pilot-observation-2026-10&quot;,&lt;br&gt;
  &quot;methodologyVersion&quot;: &quot;0.2&quot;,&lt;br&gt;
  &quot;independentVerification&quot;: false&lt;br&gt;
}&lt;br&gt;
}&lt;br&gt;
Possible evidence states might include:&lt;br&gt;
planned&lt;br&gt;
self-declared&lt;br&gt;
observed&lt;br&gt;
measured&lt;br&gt;
methodology-reviewed&lt;br&gt;
independently-verified&lt;br&gt;
disputed&lt;br&gt;
superseded&lt;br&gt;
The client could render these states differently without misrepresenting their confidence level.&lt;br&gt;
Remaining Engineering Work&lt;br&gt;
Immutable Manifest History&lt;br&gt;
The current active manifest should eventually become a pointer to an immutable history.&lt;br&gt;
{&lt;br&gt;
roomId: 'room-123',&lt;br&gt;
version: '7',&lt;br&gt;
schemaVersion: '1',&lt;br&gt;
assetBundleVersion: '42',&lt;br&gt;
checksum: 'sha256:...',&lt;br&gt;
manifest: {},&lt;br&gt;
createdBy: 'account-reference',&lt;br&gt;
createdAt: '2026-10-12T00:00:00Z'&lt;br&gt;
}&lt;br&gt;
The structure should become:&lt;br&gt;
VirtualRoom&lt;br&gt;
  │&lt;br&gt;
  └── activeManifestVersion: 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SceneManifestVersion&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;├── version 5
├── version 6
└── version 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Safe Rollback&lt;br&gt;
Rollback should create a new version based on a previous snapshot:&lt;br&gt;
v5 → v6 → v7&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;      │
      └── rollback to v6
                ↓
               v8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Version 7 should not be deleted or overwritten. This preserves auditability.&lt;br&gt;
CDN Asset Pipeline&lt;br&gt;
A future pipeline should follow:&lt;br&gt;
upload&lt;br&gt;
  ↓&lt;br&gt;
validate&lt;br&gt;
  ↓&lt;br&gt;
scan&lt;br&gt;
  ↓&lt;br&gt;
optimize&lt;br&gt;
  ↓&lt;br&gt;
calculate hash&lt;br&gt;
  ↓&lt;br&gt;
assign immutable version&lt;br&gt;
  ↓&lt;br&gt;
publish to CDN&lt;br&gt;
  ↓&lt;br&gt;
reference from manifest&lt;br&gt;
Asset URLs should be immutable:&lt;br&gt;
/scenes/neon-plaza.42.glb&lt;br&gt;
/textures/neon-floor.18.webp&lt;br&gt;
/audio/neon-ambient.7.ogg&lt;br&gt;
Client-Side Scene Loader&lt;br&gt;
The client will eventually need a structured loading pipeline:&lt;br&gt;
fetch room&lt;br&gt;
   ↓&lt;br&gt;
fetch active manifest&lt;br&gt;
   ↓&lt;br&gt;
validate schema version&lt;br&gt;
   ↓&lt;br&gt;
compare required capabilities&lt;br&gt;
   ↓&lt;br&gt;
load critical assets&lt;br&gt;
   ↓&lt;br&gt;
load optional assets&lt;br&gt;
   ↓&lt;br&gt;
report failures&lt;br&gt;
   ↓&lt;br&gt;
enter scene&lt;br&gt;
Graceful Asset Failure&lt;br&gt;
Not every asset failure should destroy the whole scene.&lt;br&gt;
critical asset missing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;→ load fallback scene
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;important asset missing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;→ continue with visible warning
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;optional asset missing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;→ omit it and continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A future asset entry could declare this:&lt;br&gt;
{&lt;br&gt;
  &quot;id&quot;: &quot;neon-plaza&quot;,&lt;br&gt;
  &quot;type&quot;: &quot;glb&quot;,&lt;br&gt;
  &quot;url&quot;: &quot;&lt;a rel=&quot;nofollow&quot; href=&quot;https://cdn.myzubster.com/scenes/neon-plaza.42.glb&quot;&gt;https://cdn.myzubster.com/scenes/neon-plaza.42.glb&lt;/a&gt;&quot;,&lt;br&gt;
  &quot;criticality&quot;: &quot;critical&quot;,&lt;br&gt;
  &quot;fallbackAssetId&quot;: &quot;basic-plaza&quot;&lt;br&gt;
}&lt;br&gt;
Runtime Resource Budgets&lt;br&gt;
Valid JSON does not guarantee safe runtime performance.&lt;br&gt;
We still need budgets for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File size&lt;/li&gt;
&lt;li&gt;Polygon count&lt;/li&gt;
&lt;li&gt;Texture dimensions&lt;/li&gt;
&lt;li&gt;Texture memory&lt;/li&gt;
&lt;li&gt;Draw calls&lt;/li&gt;
&lt;li&gt;Animation count&lt;/li&gt;
&lt;li&gt;Shader complexity&lt;/li&gt;
&lt;li&gt;Audio duration&lt;/li&gt;
&lt;li&gt;Video resolution&lt;/li&gt;
&lt;li&gt;Concurrent requests&lt;/li&gt;
&lt;li&gt;Scene initialization time&lt;br&gt;
Mobile Validation&lt;br&gt;
A real-device test matrix should include:&lt;/li&gt;
&lt;li&gt;Android Chrome&lt;/li&gt;
&lt;li&gt;Android Firefox&lt;/li&gt;
&lt;li&gt;iOS Safari&lt;/li&gt;
&lt;li&gt;iPadOS Safari&lt;/li&gt;
&lt;li&gt;Low-memory devices&lt;/li&gt;
&lt;li&gt;Slow networks&lt;/li&gt;
&lt;li&gt;Small screens&lt;/li&gt;
&lt;li&gt;Touch-only interaction&lt;/li&gt;
&lt;li&gt;Screen rotation&lt;/li&gt;
&lt;li&gt;Background and resume behavior&lt;br&gt;
WebXR Device Validation&lt;br&gt;
Physical-headset testing should cover:&lt;/li&gt;
&lt;li&gt;Entering immersive mode&lt;/li&gt;
&lt;li&gt;Exiting immersive mode&lt;/li&gt;
&lt;li&gt;Session interruption&lt;/li&gt;
&lt;li&gt;Controller input&lt;/li&gt;
&lt;li&gt;Focus loss&lt;/li&gt;
&lt;li&gt;Boundary changes&lt;/li&gt;
&lt;li&gt;Sleep and resume&lt;/li&gt;
&lt;li&gt;Spatial audio&lt;/li&gt;
&lt;li&gt;Motion comfort&lt;/li&gt;
&lt;li&gt;Performance degradation&lt;br&gt;
Realtime Reliability&lt;br&gt;
Load tests should cover:&lt;/li&gt;
&lt;li&gt;Concurrent joins&lt;/li&gt;
&lt;li&gt;Concurrent leaves&lt;/li&gt;
&lt;li&gt;Chat bursts&lt;/li&gt;
&lt;li&gt;Stage requests&lt;/li&gt;
&lt;li&gt;Moderation operations&lt;/li&gt;
&lt;li&gt;Reconnect storms&lt;/li&gt;
&lt;li&gt;Token refresh&lt;/li&gt;
&lt;li&gt;Database latency&lt;/li&gt;
&lt;li&gt;Redis degradation&lt;/li&gt;
&lt;li&gt;Server restart&lt;/li&gt;
&lt;li&gt;Network partitions&lt;br&gt;
Accessibility&lt;br&gt;
Browser-first also means accessible-first.&lt;br&gt;
The remaining accessibility work includes:&lt;/li&gt;
&lt;li&gt;Keyboard navigation&lt;/li&gt;
&lt;li&gt;Screen-reader semantics&lt;/li&gt;
&lt;li&gt;Focus management&lt;/li&gt;
&lt;li&gt;Reduced motion&lt;/li&gt;
&lt;li&gt;Colour contrast&lt;/li&gt;
&lt;li&gt;Text scaling&lt;/li&gt;
&lt;li&gt;Captions&lt;/li&gt;
&lt;li&gt;Touch-target sizing&lt;/li&gt;
&lt;li&gt;Non-spatial alternatives&lt;/li&gt;
&lt;li&gt;Cognitive-load review&lt;br&gt;
Important project information must never be available only through an immersive 3D interaction.&lt;br&gt;
Proposed Roadmap&lt;br&gt;
C2.1 — Immutable Manifest Versions&lt;br&gt;
create version model&lt;br&gt;
→ validate manifest&lt;br&gt;
→ calculate checksum&lt;br&gt;
→ store immutable snapshot&lt;br&gt;
→ update active pointer&lt;br&gt;
C2.2 — Rollback&lt;br&gt;
select previous version&lt;br&gt;
→ validate snapshot&lt;br&gt;
→ create a new version&lt;br&gt;
→ update active pointer&lt;br&gt;
→ preserve audit history&lt;br&gt;
C2.3 — Asset Pipeline&lt;br&gt;
upload&lt;br&gt;
→ validate&lt;br&gt;
→ optimize&lt;br&gt;
→ hash&lt;br&gt;
→ version&lt;br&gt;
→ publish&lt;br&gt;
→ reference&lt;br&gt;
C2.4 — Client Scene Loader&lt;br&gt;
fetch&lt;br&gt;
→ validate&lt;br&gt;
→ negotiate capabilities&lt;br&gt;
→ load&lt;br&gt;
→ apply fallbacks&lt;br&gt;
→ expose status&lt;br&gt;
C2.5 — First LIFE Scene&lt;br&gt;
select pilot&lt;br&gt;
→ define evidence contract&lt;br&gt;
→ define KPI/MRV boundaries&lt;br&gt;
→ generate manifest&lt;br&gt;
→ implement scene&lt;br&gt;
→ run public test&lt;br&gt;
How to Contribute&lt;br&gt;
The most useful contributions currently include:&lt;/li&gt;
&lt;li&gt;Mobile browser test reports&lt;/li&gt;
&lt;li&gt;Real-headset WebXR test reports&lt;/li&gt;
&lt;li&gt;Scene-manifest reviews&lt;/li&gt;
&lt;li&gt;glTF and GLB validation&lt;/li&gt;
&lt;li&gt;Asset optimization&lt;/li&gt;
&lt;li&gt;Accessibility testing&lt;/li&gt;
&lt;li&gt;Realtime load tests&lt;/li&gt;
&lt;li&gt;Security reviews&lt;/li&gt;
&lt;li&gt;CDN design&lt;/li&gt;
&lt;li&gt;Rollback implementation&lt;/li&gt;
&lt;li&gt;LIFE evidence modelling&lt;/li&gt;
&lt;li&gt;KPI/MRV data contracts&lt;/li&gt;
&lt;li&gt;Technical documentation&lt;br&gt;
A useful test report should contain:&lt;br&gt;
device&lt;br&gt;
operating system&lt;br&gt;
browser&lt;br&gt;
exact version&lt;br&gt;
network conditions&lt;br&gt;
steps performed&lt;br&gt;
expected result&lt;br&gt;
observed result&lt;br&gt;
logs or screenshots when safe&lt;br&gt;
related issue or pull request&lt;br&gt;
Do not include:&lt;/li&gt;
&lt;li&gt;Passwords&lt;/li&gt;
&lt;li&gt;Authentication tokens&lt;/li&gt;
&lt;li&gt;Private keys&lt;/li&gt;
&lt;li&gt;Wallet seed phrases&lt;/li&gt;
&lt;li&gt;Unredacted personal information&lt;/li&gt;
&lt;li&gt;Sensitive participant details&lt;/li&gt;
&lt;li&gt;Precise private locations&lt;br&gt;
Conclusion&lt;br&gt;
The MyZubster Metaverse now has two important engineering foundations:&lt;ol&gt;
&lt;li&gt;A browser-first capability layer where WebXR is progressive enhancement&lt;/li&gt;
&lt;li&gt;A server-validated scene contract that blocks invalid manifests from publication&lt;br&gt;
The completed work is publicly traceable:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;PR #1597 — Browser and WebXR fallback&lt;/li&gt;
&lt;li&gt;PR #1601 — Versioned scene-manifest validation&lt;br&gt;
The next phase is not simply about adding more 3D content.&lt;br&gt;
It is about creating a reliable technical chain:&lt;br&gt;
code&lt;br&gt;
→ validated contract&lt;br&gt;
→ immutable version&lt;br&gt;
→ versioned asset&lt;br&gt;
→ reliable session&lt;br&gt;
→ real-world pilot&lt;br&gt;
→ evidence&lt;br&gt;
→ understandable visualization&lt;br&gt;
→ community contribution&lt;br&gt;
That is the direction of the MyZubster Metaverse: an open, browser-first environment connecting virtual experiences to public code, documented projects, explicit evidence boundaries, and real-world collaboration.&lt;br&gt;
Status verified: October 12, 2026.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;15:21&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30813/engineering-browser-first-metaverse-webxr-fallbacks-server-authoritative-rooms-versioned</guid>
<pubDate>Mon, 12 Oct 2026 13:23:15 +0000</pubDate>
</item>
<item>
<title>How We Built Revocable Sessions and Refresh-Token Replay Protection for the MyZubster Metaverse</title>
<link>https://coderlegion.com/28847/how-built-revocable-sessions-and-refresh-token-replay-protection-for-myzubster-metaverse</link>
<description>&lt;p&gt;Ecco la versione in inglese pronta per CoderLegion.&lt;br&gt;
How We Built Revocable Sessions and Refresh-Token Replay Protection for the MyZubster Metaverse&lt;br&gt;
Authentication in a Metaverse platform is more than a login form.&lt;br&gt;
An authenticated identity may control characters, social relationships, private spaces, Marketplace activity and, eventually, payment-related operations. For MyZubster, relying only on long-lived JSON Web Tokens was no longer a sufficient security model.&lt;br&gt;
Under MYZ-71 — Authentication, Sessions &amp;amp; Account Security, we started replacing stateless browser authentication with persistent, revocable and observable server-side sessions.&lt;br&gt;
This article describes what we implemented, how refresh-token rotation works, how we detect token replay, what we tested and what still needs to be completed before production deployment.&lt;br&gt;
The implementation is currently in a Draft pull request. It has not been merged or declared production-ready.&lt;/p&gt;
&lt;p&gt;Why stateless JWT authentication was not enough&lt;br&gt;
JWTs are useful because a server can validate them without loading a database record for every request.&lt;br&gt;
However, a completely stateless model creates important limitations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;logout cannot reliably invalidate an existing token;&lt;/li&gt;
&lt;li&gt;users cannot see which devices are authenticated;&lt;/li&gt;
&lt;li&gt;administrators cannot revoke one compromised device;&lt;/li&gt;
&lt;li&gt;a stolen token remains valid until expiration;&lt;/li&gt;
&lt;li&gt;password changes do not automatically terminate sessions;&lt;/li&gt;
&lt;li&gt;long-lived tokens increase the potential impact of credential theft;&lt;/li&gt;
&lt;li&gt;tokens stored in localStorage can be accessed by malicious JavaScript after an XSS compromise.&lt;br&gt;
We therefore introduced a hybrid architecture:&lt;br&gt;
Authentication&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Persistent server-side session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Short-lived JWT access token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rotating opaque refresh token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replay detection and session revocation&lt;br&gt;
JWTs are still used for request authentication, but the server-side session is now the final source of authority.&lt;br&gt;
Persistent server-side sessions&lt;br&gt;
We added a MongoDB AuthSession model.&lt;br&gt;
A separate session is created for each authenticated device. The record contains:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;a unique session identifier;&lt;/li&gt;
&lt;li&gt;the user who owns the session;&lt;/li&gt;
&lt;li&gt;creation and expiration timestamps;&lt;/li&gt;
&lt;li&gt;the last activity timestamp;&lt;/li&gt;
&lt;li&gt;revocation state and reason;&lt;/li&gt;
&lt;li&gt;limited device metadata;&lt;/li&gt;
&lt;li&gt;a privacy-preserving client-IP digest;&lt;/li&gt;
&lt;li&gt;the current refresh-token hash;&lt;/li&gt;
&lt;li&gt;a bounded history of consumed refresh-token hashes;&lt;/li&gt;
&lt;li&gt;refresh-token rotation metadata.&lt;br&gt;
MongoDB TTL indexing is used to remove expired session records automatically.&lt;br&gt;
This enables real session lifecycle management. A valid JWT is rejected whenever its associated session is expired, missing or revoked.&lt;br&gt;
Session-bound access tokens&lt;br&gt;
New JWT access tokens include a server-generated sid claim.&lt;br&gt;
A simplified payload looks like this:&lt;br&gt;
{&lt;br&gt;
&quot;sub&quot;: &quot;user-id&quot;,&lt;br&gt;
&quot;sid&quot;: &quot;session-uuid&quot;,&lt;br&gt;
&quot;jti&quot;: &quot;access-token-uuid&quot;,&lt;br&gt;
&quot;iat&quot;: 1790540000,&lt;br&gt;
&quot;exp&quot;: 1790540900&lt;br&gt;
}&lt;br&gt;
Authentication now involves two checks:&lt;ol&gt;
&lt;li&gt;Verify the JWT signature and expiration&lt;/li&gt;
&lt;li&gt;Validate the persistent session referenced by sid&lt;br&gt;
This architecture preserves the advantages of JWTs while restoring the ability to revoke access immediately.&lt;br&gt;
If the user removes a device from the account-security page, the session becomes invalid even if its most recent JWT has not expired.&lt;br&gt;
Opaque refresh tokens&lt;br&gt;
The refresh token is not a JWT and does not contain trusted user data.&lt;br&gt;
Its conceptual format is:&lt;br&gt;
myzr.&amp;lt;session-id&amp;gt;.&amp;lt;cryptographically-random-secret&amp;gt;&lt;br&gt;
The random section is produced using a cryptographically secure random-number generator.&lt;br&gt;
The complete refresh token is sent to the authenticated browser, but it is never stored directly in MongoDB.&lt;br&gt;
Instead, the backend calculates:&lt;br&gt;
HMAC-SHA256(server secret, raw refresh token)&lt;br&gt;
Only the resulting digest is saved.&lt;br&gt;
This prevents a database leak from immediately exposing usable refresh credentials.&lt;br&gt;
Protected authentication cookies&lt;br&gt;
Refresh tokens are stored in cookies configured with:&lt;br&gt;
HttpOnly&lt;br&gt;
SameSite=Lax&lt;br&gt;
Secure in production&lt;br&gt;
Path=/api/auth&lt;br&gt;
HttpOnly prevents frontend JavaScript from reading the credential.&lt;br&gt;
The restricted path reduces the number of requests carrying the refresh cookie.&lt;br&gt;
Access tokens can also be received through an HttpOnly cookie. Bearer-token authentication remains temporarily supported to avoid breaking clients during the migration.&lt;br&gt;
Atomic refresh-token rotation&lt;br&gt;
A refresh token is single-use.&lt;br&gt;
When the browser calls:&lt;br&gt;
POST /api/auth/refresh&lt;br&gt;
the backend:&lt;/li&gt;
&lt;li&gt;reads the refresh cookie;&lt;/li&gt;
&lt;li&gt;extracts the session identifier;&lt;/li&gt;
&lt;li&gt;calculates the HMAC digest of the submitted token;&lt;/li&gt;
&lt;li&gt;generates a new opaque token;&lt;/li&gt;
&lt;li&gt;atomically compares the submitted hash with the current stored hash;&lt;/li&gt;
&lt;li&gt;replaces the stored hash;&lt;/li&gt;
&lt;li&gt;records the consumed hash;&lt;/li&gt;
&lt;li&gt;issues a new access token;&lt;/li&gt;
&lt;li&gt;sends new access and refresh cookies.&lt;br&gt;
The database update only succeeds if:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;the session exists;&lt;/li&gt;
&lt;li&gt;the session has not expired;&lt;/li&gt;
&lt;li&gt;the session has not been revoked;&lt;/li&gt;
&lt;li&gt;the submitted hash is still the current refresh-token hash.&lt;br&gt;
This is effectively a compare-and-swap operation.&lt;br&gt;
If two requests try to use the same refresh token simultaneously, only one can rotate it successfully.&lt;br&gt;
Refresh-token replay detection&lt;br&gt;
Rotation prevents normal reuse, but the system must also detect when an old token appears again.&lt;br&gt;
After every successful rotation, the consumed token hash is placed in a bounded history.&lt;br&gt;
If a token from that history is submitted again, the server treats it as a possible credential compromise.&lt;br&gt;
Previously consumed token submitted&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replay detected&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Entire server-side session revoked&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Authentication cookies cleared&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A new login is required&lt;br&gt;
The session receives the revocation reason:&lt;br&gt;
refresh-token-replay&lt;br&gt;
The history is limited to the latest 50 hashes so the MongoDB document cannot grow indefinitely.&lt;br&gt;
Replay does not necessarily prove malicious activity. It could also indicate an outdated client or an unusual concurrency condition. Revoking the session is nevertheless the safest response.&lt;br&gt;
New authentication endpoints&lt;br&gt;
The current implementation provides the following endpoints.&lt;br&gt;
Refresh the session&lt;br&gt;
POST /api/auth/refresh&lt;br&gt;
This endpoint rotates the refresh token and issues a new access token.&lt;br&gt;
The raw refresh token is never included in the JSON response.&lt;br&gt;
Log out&lt;br&gt;
POST /api/auth/logout&lt;br&gt;
Logout is idempotent.&lt;br&gt;
Authentication cookies are cleared even when the access token is missing, malformed, expired or already revoked.&lt;br&gt;
When possible, the refresh token is used to find and revoke the persistent session.&lt;br&gt;
Retrieve the authenticated account&lt;br&gt;
GET /api/auth/me&lt;br&gt;
Returns the authenticated user and safe session metadata.&lt;br&gt;
List active devices&lt;br&gt;
GET /api/auth/me/sessions&lt;br&gt;
Returns the user’s active sessions and indicates the current device.&lt;br&gt;
Revoke a device&lt;br&gt;
DELETE /api/auth/me/sessions/:sessionId&lt;br&gt;
Allows users to terminate another session remotely.&lt;br&gt;
Revoking the current session also clears local authentication state and returns the user to the login flow.&lt;br&gt;
Password and social authentication&lt;br&gt;
Password registration and login now create persistent sessions and issue both access and refresh cookies.&lt;br&gt;
Verified social-login flows use the same architecture.&lt;br&gt;
The raw refresh token is not placed inside:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;redirect URLs;&lt;/li&gt;
&lt;li&gt;OAuth query parameters;&lt;/li&gt;
&lt;li&gt;signed callback tickets;&lt;/li&gt;
&lt;li&gt;public API responses.&lt;br&gt;
This reduces the risk of credentials leaking through browser history, analytics systems, proxy logs or referrer headers.&lt;br&gt;
Account-security interface&lt;br&gt;
The React frontend now includes:&lt;br&gt;
/account/security&lt;br&gt;
The page displays:&lt;/li&gt;
&lt;li&gt;active sessions;&lt;/li&gt;
&lt;li&gt;the current device;&lt;/li&gt;
&lt;li&gt;session creation time;&lt;/li&gt;
&lt;li&gt;last activity;&lt;/li&gt;
&lt;li&gt;expiration time;&lt;/li&gt;
&lt;li&gt;limited device information.&lt;br&gt;
Users can remotely revoke another device or terminate the current session.&lt;br&gt;
The page is linked from the authenticated account panel and Neon Plaza.&lt;br&gt;
The deployment configuration also supports the route as a single-page application path and applies:&lt;br&gt;
X-Robots-Tag: noindex, nofollow&lt;br&gt;
Account-security pages should not be indexed by search engines.&lt;br&gt;
Privacy-preserving session metadata&lt;br&gt;
The system does not store raw client IP addresses.&lt;br&gt;
Instead, it saves an HMAC-derived digest. This provides a limited correlation signal for security purposes without retaining the original IP address as normal application data.&lt;br&gt;
Device metadata is also intentionally limited.&lt;br&gt;
Session security should help users recognize their devices without becoming an invasive tracking mechanism.&lt;br&gt;
Legacy migration support&lt;br&gt;
The existing frontend still contains API clients that expect a token in localStorage or use:&lt;br&gt;
Authorization: Bearer &lt;br&gt;
Removing this immediately would break existing routes and clients.&lt;br&gt;
The migration is therefore divided into stages:&lt;br&gt;
Persistent sessions and cookie support&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rotating refresh tokens&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Centralized access-token renewal&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CSRF protection&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cookie-only authentication&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Expiration of legacy browser tokens&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Strict server-session enforcement&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;          ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Removal of localStorage and bearer migration&lt;br&gt;
An environment option is available for strict enforcement:&lt;br&gt;
REQUIRE_SERVER_SESSION=true&lt;br&gt;
It should only be activated after existing clients and legacy credentials have been migrated.&lt;br&gt;
Testing the implementation&lt;br&gt;
The focused authentication implementation currently passes:&lt;br&gt;
Backend:  30/30 tests&lt;br&gt;
Frontend: 12/12 tests&lt;br&gt;
The React production build also completes successfully.&lt;br&gt;
Real MongoDB integration coverage verifies the complete replay lifecycle:&lt;br&gt;
Create persistent session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use current refresh token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rotate successfully&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Submit the old token again&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reject the replay&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Revoke the server-side session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Persist refresh-token-replay as the reason&lt;br&gt;
The following authentication suites also pass in GitHub Actions:&lt;br&gt;
tests/authSessionService.test.js&lt;br&gt;
tests/authSessionController.test.js&lt;br&gt;
tests/socialIdentityService.test.js&lt;br&gt;
Repository-wide CI status&lt;br&gt;
The complete repository pipeline is not yet green.&lt;br&gt;
The latest full backend execution reported:&lt;br&gt;
141 test suites passed&lt;br&gt;
42 test suites failed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;738 tests passed&lt;br&gt;
44 tests failed&lt;br&gt;
The failing tests mainly concern pre-existing behavior in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zorgax payments and payment intents;&lt;/li&gt;
&lt;li&gt;Marketplace flows;&lt;/li&gt;
&lt;li&gt;seller-membership policies;&lt;/li&gt;
&lt;li&gt;older Metaverse authentication expectations;&lt;/li&gt;
&lt;li&gt;Metaverse observability;&lt;/li&gt;
&lt;li&gt;legacy source-code assertion tests.&lt;br&gt;
The Security Audit and MYZ-164 policy workflows also remain red because of previously identified repository-wide conditions.&lt;br&gt;
The new MYZ-71 session and refresh-token suites are green, but the pull request must remain a Draft until the wider baseline and the remaining authentication work are addressed.&lt;br&gt;
What still needs to be implemented&lt;br&gt;
Centralized access-token renewal&lt;br&gt;
The frontend needs a shared API layer that can:&lt;ol&gt;
&lt;li&gt;identify an expired access token;&lt;/li&gt;
&lt;li&gt;call /api/auth/refresh;&lt;/li&gt;
&lt;li&gt;retry the original request;&lt;/li&gt;
&lt;li&gt;prevent simultaneous refresh calls;&lt;/li&gt;
&lt;li&gt;redirect to login when renewal fails.&lt;br&gt;
Without a centralized implementation, individual pages may respond differently when the access token expires.&lt;br&gt;
CSRF protection&lt;br&gt;
Cookie-based authentication requires explicit protection for state-changing operations.&lt;br&gt;
The final design should combine appropriate controls such as:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;origin validation;&lt;/li&gt;
&lt;li&gt;CSRF tokens;&lt;/li&gt;
&lt;li&gt;double-submit cookies;&lt;/li&gt;
&lt;li&gt;carefully selected SameSite policies;&lt;/li&gt;
&lt;li&gt;rejection of unsafe cross-origin requests.&lt;br&gt;
SameSite=Lax should not be considered the only defence.&lt;br&gt;
Removal of browser-stored tokens&lt;br&gt;
The current frontend still updates the legacy localStorage token as a temporary compatibility bridge.&lt;br&gt;
The final architecture should not expose reusable authentication credentials to frontend JavaScript.&lt;br&gt;
Before removing localStorage, we must migrate:&lt;/li&gt;
&lt;li&gt;every authenticated API client;&lt;/li&gt;
&lt;li&gt;protected React routes;&lt;/li&gt;
&lt;li&gt;realtime and websocket authentication;&lt;/li&gt;
&lt;li&gt;mobile or embedded clients;&lt;/li&gt;
&lt;li&gt;old sessions and legacy JWTs.&lt;br&gt;
Passkeys and magic links&lt;br&gt;
The MYZ-71 roadmap includes passwordless authentication based on flows such as:&lt;br&gt;
/auth/start&lt;br&gt;
/auth/verify&lt;br&gt;
Passkey support will require correct WebAuthn management for:&lt;/li&gt;
&lt;li&gt;relying-party configuration;&lt;/li&gt;
&lt;li&gt;allowed origins;&lt;/li&gt;
&lt;li&gt;challenge creation and expiration;&lt;/li&gt;
&lt;li&gt;credential counters;&lt;/li&gt;
&lt;li&gt;credential revocation;&lt;/li&gt;
&lt;li&gt;account recovery.&lt;br&gt;
Magic links will require short-lived, single-use verification tokens and replay protection.&lt;br&gt;
Step-up authentication&lt;br&gt;
Sensitive operations should require recent stronger verification.&lt;br&gt;
Examples include:&lt;/li&gt;
&lt;li&gt;changing the primary email;&lt;/li&gt;
&lt;li&gt;changing a password;&lt;/li&gt;
&lt;li&gt;registering or deleting passkeys;&lt;/li&gt;
&lt;li&gt;deleting the account;&lt;/li&gt;
&lt;li&gt;accessing wallet or payment functionality;&lt;/li&gt;
&lt;li&gt;modifying high-impact Marketplace settings.&lt;br&gt;
A valid session should not automatically authorize every sensitive action indefinitely.&lt;br&gt;
Password-change session policy&lt;br&gt;
The application must define what happens after a password change:&lt;/li&gt;
&lt;li&gt;revoke every session;&lt;/li&gt;
&lt;li&gt;keep only the current session;&lt;/li&gt;
&lt;li&gt;allow the user to choose;&lt;/li&gt;
&lt;li&gt;require step-up authentication.&lt;br&gt;
This policy must be enforced on the server and tested with real session records.&lt;br&gt;
Production OAuth validation&lt;br&gt;
Google, GitHub and Facebook login still need production verification for:&lt;/li&gt;
&lt;li&gt;exact callback URLs;&lt;/li&gt;
&lt;li&gt;public frontend and API origins;&lt;/li&gt;
&lt;li&gt;provider secrets;&lt;/li&gt;
&lt;li&gt;redirect allowlists;&lt;/li&gt;
&lt;li&gt;account-linking behavior;&lt;/li&gt;
&lt;li&gt;missing-email cases;&lt;/li&gt;
&lt;li&gt;cookie behavior across domains.&lt;br&gt;
MongoDB Atlas validation&lt;br&gt;
The production deployment must verify:&lt;/li&gt;
&lt;li&gt;TTL-index creation;&lt;/li&gt;
&lt;li&gt;refresh-token indexes;&lt;/li&gt;
&lt;li&gt;cleanup of expired sessions;&lt;/li&gt;
&lt;li&gt;document growth;&lt;/li&gt;
&lt;li&gt;rolling-deployment compatibility;&lt;/li&gt;
&lt;li&gt;session behavior under concurrent refresh requests.&lt;br&gt;
Rate limiting&lt;br&gt;
Authentication endpoints need dedicated abuse protection.&lt;br&gt;
This includes limits for:&lt;/li&gt;
&lt;li&gt;password login;&lt;/li&gt;
&lt;li&gt;refresh requests;&lt;/li&gt;
&lt;li&gt;password recovery;&lt;/li&gt;
&lt;li&gt;magic-link generation;&lt;/li&gt;
&lt;li&gt;WebAuthn challenge creation;&lt;/li&gt;
&lt;li&gt;social-auth callbacks.&lt;br&gt;
Security monitoring&lt;br&gt;
Structured security events should be produced for:&lt;/li&gt;
&lt;li&gt;login success and failure;&lt;/li&gt;
&lt;li&gt;session creation;&lt;/li&gt;
&lt;li&gt;session revocation;&lt;/li&gt;
&lt;li&gt;remote device removal;&lt;/li&gt;
&lt;li&gt;refresh-token replay;&lt;/li&gt;
&lt;li&gt;password changes;&lt;/li&gt;
&lt;li&gt;passkey registration;&lt;/li&gt;
&lt;li&gt;suspicious authentication activity.&lt;br&gt;
Logs must never contain passwords, raw access tokens, raw refresh tokens, OAuth authorization codes or provider secrets.&lt;br&gt;
Recommended deployment sequence&lt;br&gt;
The safest rollout order is:&lt;ol&gt;
&lt;li&gt;review the Draft pull request;&lt;/li&gt;
&lt;li&gt;deploy with legacy compatibility enabled;&lt;/li&gt;
&lt;li&gt;verify MongoDB indexes;&lt;/li&gt;
&lt;li&gt;validate cookies using the real public domains;&lt;/li&gt;
&lt;li&gt;test login, refresh, logout and remote revocation;&lt;/li&gt;
&lt;li&gt;execute a controlled refresh-token replay test;&lt;/li&gt;
&lt;li&gt;implement centralized frontend renewal;&lt;/li&gt;
&lt;li&gt;add and validate CSRF protection;&lt;/li&gt;
&lt;li&gt;monitor session and replay events;&lt;/li&gt;
&lt;li&gt;allow legacy credentials to expire;&lt;/li&gt;
&lt;li&gt;activate strict server-session enforcement;&lt;/li&gt;
&lt;li&gt;remove localStorage and legacy bearer authentication;&lt;/li&gt;
&lt;li&gt;introduce passkeys, magic links and step-up authentication.&lt;br&gt;
Current progress&lt;br&gt;
Persistent server-side sessions             DONE&lt;br&gt;
Session-bound JWT access tokens              DONE&lt;br&gt;
Real logout                                  DONE&lt;br&gt;
Active-device listing                        DONE&lt;br&gt;
Remote session revocation                    DONE&lt;br&gt;
Opaque rotating refresh tokens               DONE&lt;br&gt;
Refresh-token replay detection               DONE&lt;br&gt;
Password and social-login integration        DONE&lt;br&gt;
Account-security interface                   DONE&lt;br&gt;
Focused backend and frontend testing         DONE&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Centralized access-token renewal             PENDING&lt;br&gt;
CSRF hardening                               PENDING&lt;br&gt;
Cookie-only migration                        PENDING&lt;br&gt;
Removal of localStorage authentication       PENDING&lt;br&gt;
Passkeys and magic links                     PENDING&lt;br&gt;
Step-up authentication                       PENDING&lt;br&gt;
Production OAuth validation                  PENDING&lt;br&gt;
MongoDB Atlas production validation          PENDING&lt;br&gt;
Repository-wide green CI                     PENDING&lt;br&gt;
Final thoughts&lt;br&gt;
Secure authentication is not just about generating a token.&lt;br&gt;
It requires a complete lifecycle:&lt;br&gt;
Issue&lt;br&gt;
Verify&lt;br&gt;
Renew&lt;br&gt;
Observe&lt;br&gt;
Revoke&lt;br&gt;
Recover&lt;br&gt;
Monitor&lt;br&gt;
MyZubster now has the foundation for persistent multi-device sessions, secure refresh-token rotation and automatic replay response.&lt;br&gt;
The next major objective is completing the browser migration safely through centralized renewal, CSRF protection and the removal of JavaScript-accessible authentication credentials.&lt;br&gt;
Only after those controls are validated should strict session enforcement be activated in production.&lt;br&gt;
The current implementation can be reviewed in the Draft pull request:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/danieldirimini-myzubster/myzubster/pull/10&quot;&gt;https://github.com/danieldirimini-myzubster/myzubster/pull/10&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28847/how-built-revocable-sessions-and-refresh-token-replay-protection-for-myzubster-metaverse</guid>
<pubDate>Mon, 28 Sep 2026 01:35:52 +0000</pubDate>
</item>
<item>
<title>Building MyZubster as a Verifiable AI Development Ecosystem</title>
<link>https://coderlegion.com/28184/building-myzubster-as-a-verifiable-ai-development-ecosystem</link>
<description>&lt;p&gt;uilding MyZubster as a Verifiable AI Development Ecosystem: Metaverse, GitHub Evidence, Zorgax Knowledge, and DevelopmentRequest&lt;br&gt;
Today we had the opportunity to present and demonstrate part of the MyZubster ecosystem during an institutional hearing.&lt;br&gt;
Instead of presenting only slides or a conceptual roadmap, we showed the system directly. We opened the MyZubster metaverse, explained a real pilot involving an actual user, discussed how GitHub activity can become technical evidence, and described the architecture we are building around Zorgax, verified knowledge, software development, wallets, and human review.&lt;br&gt;
The most important outcome for us was not the meeting itself.&lt;br&gt;
It was realizing that the different components we have been building are starting to form a coherent technical system.&lt;br&gt;
The architecture is moving toward this loop:&lt;br&gt;
Real Person&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Real Activity&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Data / Evidence&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MyZubster&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified Knowledge&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zorgax AI&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DevelopmentRequest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Developer&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Code / GitHub&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tests&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Independent Verification&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;New Knowledge&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Identity / Wallet&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Metaverse Interaction&lt;br&gt;
The goal is not simply to build another AI assistant, another marketplace, or another metaverse.&lt;br&gt;
The goal is to connect all of these components around one principle:&lt;br&gt;
AI can assist the process, but evidence and verification should remain inspectable.&lt;/p&gt;
&lt;p&gt;The Metaverse Is Only the Interface&lt;br&gt;
One of the things we demonstrated was the MyZubster metaverse.&lt;br&gt;
For us, the metaverse is not the entire product.&lt;br&gt;
It is one possible user interface for a much larger system.&lt;br&gt;
The long-term idea is that a user should eventually be able to enter the environment with a digital identity, connect a wallet, interact with people or services, and have access to a history of technical contributions and activities.&lt;br&gt;
That means the visible environment may look like a metaverse, but behind it we want something closer to a verifiable contribution graph.&lt;br&gt;
A person may have:&lt;br&gt;
Identity&lt;br&gt;
  ↓&lt;br&gt;
Wallet&lt;br&gt;
  ↓&lt;br&gt;
GitHub Account&lt;br&gt;
  ↓&lt;br&gt;
Issues&lt;br&gt;
  ↓&lt;br&gt;
Pull Requests&lt;br&gt;
  ↓&lt;br&gt;
Commits&lt;br&gt;
  ↓&lt;br&gt;
Tests&lt;br&gt;
  ↓&lt;br&gt;
Reviews&lt;br&gt;
  ↓&lt;br&gt;
Verified Contributions&lt;br&gt;
The important distinction is that a wallet alone does not prove contribution.&lt;br&gt;
A GitHub account alone does not prove contribution either.&lt;br&gt;
What matters is the history of actions and the evidence attached to them.&lt;br&gt;
A commit may be evidence.&lt;br&gt;
A passing test may be evidence.&lt;br&gt;
A reviewed pull request may be evidence.&lt;br&gt;
A reproducible result may be evidence.&lt;br&gt;
But none of these should automatically be interpreted as proof of everything.&lt;br&gt;
That distinction becomes very important once AI is involved.&lt;br&gt;
A Real Pilot: Nicola&lt;br&gt;
We also presented a real pilot involving Nicola, one of the people testing and contributing to the ecosystem.&lt;br&gt;
The first experiment was intentionally simple.&lt;br&gt;
A physical kefir handover was performed and digitally recorded through MyZubster.&lt;br&gt;
The workflow represented something like:&lt;br&gt;
HAND_DELIVERY&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Receiver confirms receipt&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Status updated&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;RECORDED&lt;br&gt;
There was no payment involved.&lt;br&gt;
The specific transaction was also not recorded as an on-chain blockchain transaction.&lt;br&gt;
That is important because we do not want to describe the experiment as something it was not.&lt;br&gt;
The purpose was not to scientifically validate kefir.&lt;br&gt;
The purpose was to answer a much more technical question:&lt;br&gt;
Can a real-world event be represented digitally in a way that produces useful evidence?&lt;/p&gt;
&lt;p&gt;The answer was yes.&lt;br&gt;
From there, Nicola also tested other parts of MyZubster, reported problems, and worked on his own software.&lt;br&gt;
That gave us a more interesting participation model.&lt;br&gt;
Instead of thinking about users as static roles, we can model participation as a progression:&lt;br&gt;
User&lt;br&gt;
  ↓&lt;br&gt;
Tester&lt;br&gt;
  ↓&lt;br&gt;
Contributor&lt;br&gt;
  ↓&lt;br&gt;
Developer&lt;br&gt;
  ↓&lt;br&gt;
Evidence Producer&lt;br&gt;
  ↓&lt;br&gt;
Knowledge Contributor&lt;br&gt;
This is one of the ideas that could eventually connect the metaverse, GitHub, wallets, community reputation, and Zorgax.&lt;br&gt;
Zorgax: Chat Is Not Knowledge&lt;br&gt;
One of the most important architectural decisions we have made recently concerns Zorgax.&lt;br&gt;
We do not want to treat an AI-generated answer as verified knowledge.&lt;br&gt;
That sounds obvious, but many systems effectively do exactly that.&lt;br&gt;
A language model generates a response.&lt;br&gt;
The response is stored.&lt;br&gt;
Later the system retrieves that response as if it were truth.&lt;br&gt;
That is dangerous.&lt;br&gt;
So our architecture starts from a different assumption:&lt;br&gt;
A message is not knowledge.&lt;/p&gt;
&lt;p&gt;A message may contain useful information.&lt;br&gt;
It may become a candidate for knowledge.&lt;br&gt;
But it must go through additional stages.&lt;br&gt;
Our conceptual flow looks like this:&lt;br&gt;
User Question&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AI Response&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Candidate Information&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sources&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evidence&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Human / System Review&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified Knowledge&lt;br&gt;
Only after that should the information become part of a trusted knowledge layer.&lt;br&gt;
The Zorgax Knowledge Layer&lt;br&gt;
We have been building a dedicated Knowledge Layer for Zorgax.&lt;br&gt;
The knowledge model is designed to preserve more than just text.&lt;br&gt;
A useful knowledge object needs context.&lt;br&gt;
It may include concepts such as:&lt;br&gt;
Knowledge&lt;br&gt;
 ├── contributionId&lt;br&gt;
 ├── title&lt;br&gt;
 ├── content&lt;br&gt;
 ├── contentHash&lt;br&gt;
 ├── version&lt;br&gt;
 ├── status&lt;br&gt;
 ├── visibility&lt;br&gt;
 ├── provenance&lt;br&gt;
 ├── source&lt;br&gt;
 ├── evidence&lt;br&gt;
 └── lineage&lt;br&gt;
The contentHash is particularly important.&lt;br&gt;
It gives us a deterministic identity for the canonical content.&lt;br&gt;
If the content changes, the hash changes.&lt;br&gt;
This allows downstream systems to know exactly which version of knowledge they are using.&lt;br&gt;
For example, a development task may reference:&lt;br&gt;
{&lt;br&gt;
  &quot;contributionId&quot;: &quot;ZK-123&quot;,&lt;br&gt;
  &quot;contentHash&quot;: &quot;f30c...&quot;,&lt;br&gt;
  &quot;version&quot;: 3,&lt;br&gt;
  &quot;title&quot;: &quot;Metaverse Identity Architecture&quot;&lt;br&gt;
}&lt;br&gt;
Later, the knowledge may evolve to version 4.&lt;br&gt;
The development task should still be able to show:&lt;br&gt;
This implementation was based on version 3.&lt;/p&gt;
&lt;p&gt;That creates much better provenance.&lt;br&gt;
Preview Before Persistent Writes&lt;br&gt;
Another principle we implemented is:&lt;br&gt;
The AI should not silently perform consequential writes.&lt;/p&gt;
&lt;p&gt;For operations such as creating a DevelopmentRequest, the system first produces a preview.&lt;br&gt;
Conceptually:&lt;br&gt;
User Intent&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Normalized Input&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Knowledge Snapshot&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Preview&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Digest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Explicit Confirmation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Persistent Write&lt;br&gt;
A digest is generated from the preview.&lt;br&gt;
Then the user must confirm using a value such as:&lt;br&gt;
CONFERMA DEV a1b2c3d4&lt;br&gt;
If the preview changes, the digest changes.&lt;br&gt;
If the digest does not match, the operation fails.&lt;br&gt;
This prevents a situation where the user approves one thing and the system writes something different.&lt;br&gt;
DevelopmentRequest: Turning Knowledge Into Work&lt;br&gt;
The next architecture problem was:&lt;br&gt;
How do we transform verified knowledge into software development?&lt;/p&gt;
&lt;p&gt;Our solution is a new neutral object called DevelopmentRequest.&lt;br&gt;
A DevelopmentRequest is not a bounty.&lt;br&gt;
It is not a GitHub issue.&lt;br&gt;
It is not a payment request.&lt;br&gt;
It represents the work that needs to be done.&lt;br&gt;
The current lifecycle is:&lt;br&gt;
DRAFT&lt;br&gt;
  ↓&lt;br&gt;
OPEN&lt;br&gt;
  ↓&lt;br&gt;
IN_PROGRESS&lt;br&gt;
  ↓&lt;br&gt;
SUBMITTED&lt;br&gt;
  ↓&lt;br&gt;
VERIFIED&lt;br&gt;
or:&lt;br&gt;
SUBMITTED&lt;br&gt;
  ↓&lt;br&gt;
REJECTED&lt;br&gt;
The model also supports cancellation.&lt;br&gt;
Conceptually, the object contains:&lt;br&gt;
DevelopmentRequest {&lt;br&gt;
  requestId&lt;br&gt;
  requestHash&lt;br&gt;
  createdBy&lt;/p&gt;
&lt;p&gt;  title&lt;br&gt;
  description&lt;/p&gt;
&lt;p&gt;  knowledgeRefs[]&lt;/p&gt;
&lt;p&gt;  requirements[]&lt;br&gt;
  acceptanceTests[]&lt;br&gt;
  evidenceRequired[]&lt;/p&gt;
&lt;p&gt;  status&lt;br&gt;
  assigneeId&lt;/p&gt;
&lt;p&gt;  submission&lt;br&gt;
  review&lt;/p&gt;
&lt;p&gt;  bountyReference // optional&lt;br&gt;
}&lt;br&gt;
The important part is that the development request is anchored to verified knowledge.&lt;br&gt;
Snapshotting Knowledge&lt;br&gt;
When a DevelopmentRequest is created, Zorgax does not simply store a knowledge ID.&lt;br&gt;
It stores a snapshot reference.&lt;br&gt;
For example:&lt;br&gt;
knowledgeRefs: [&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contributionId: &quot;ZK-123&quot;,
contentHash: &quot;abc123...&quot;,
version: 2,
title: &quot;Verified Architecture&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
]&lt;br&gt;
Before the request is actually committed, the system revalidates those knowledge references.&lt;br&gt;
If the underlying content has changed between preview and commit, the operation fails.&lt;br&gt;
Conceptually:&lt;br&gt;
if (&lt;br&gt;
  expected.contentHash !== current.contentHash ||&lt;br&gt;
  expected.version !== current.version&lt;br&gt;
) {&lt;br&gt;
  throw new Error(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;Knowledge changed after preview&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
This gives us something extremely useful:&lt;br&gt;
development provenance.&lt;br&gt;
We can eventually say:&lt;br&gt;
Feature X&lt;br&gt;
was implemented because of&lt;br&gt;
DevelopmentRequest Y&lt;br&gt;
which was based on&lt;br&gt;
Knowledge Z version 2&lt;br&gt;
which came from&lt;br&gt;
Evidence A + Evidence B&lt;br&gt;
That is much stronger than simply linking a GitHub issue to a random conversation.&lt;br&gt;
Submission Is Not Verification&lt;br&gt;
This is another important rule.&lt;br&gt;
A developer may submit something.&lt;br&gt;
That does not mean the work is verified.&lt;br&gt;
So the workflow separates:&lt;br&gt;
SUBMITTED&lt;br&gt;
from:&lt;br&gt;
VERIFIED&lt;br&gt;
The contributor submits evidence such as:&lt;br&gt;
{&lt;br&gt;
  &quot;evidenceRefs&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;test:integration:green&quot;,
&quot;demo:https://...&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ],&lt;br&gt;
  &quot;commitRefs&quot;: [&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;commit:abc123&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  ]&lt;br&gt;
}&lt;br&gt;
But a separate reviewer is responsible for verification.&lt;br&gt;
The reviewer cannot be the creator or the assigned developer.&lt;br&gt;
Conceptually:&lt;br&gt;
if (&lt;br&gt;
  reviewer === request.createdBy ||&lt;br&gt;
  reviewer === request.assigneeId&lt;br&gt;
) {&lt;br&gt;
  throw new Error(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;Review must be independent&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
This is one of the foundations for future contribution reputation.&lt;br&gt;
Strengthening the Evidence Model&lt;br&gt;
We are now tightening this further.&lt;br&gt;
The first implementation verified that evidence existed.&lt;br&gt;
But that is not enough.&lt;br&gt;
Imagine this DevelopmentRequest:&lt;br&gt;
Evidence required:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unit tests pass&lt;/li&gt;
&lt;li&gt;Security review completed&lt;/li&gt;
&lt;li&gt;Metaverse integration demonstrated&lt;br&gt;
And the developer submits only:&lt;br&gt;
commit:abc123&lt;br&gt;
Technically, evidence exists.&lt;br&gt;
But the required evidence is not actually satisfied.&lt;br&gt;
So the stronger model connects each requirement to a specific reference.&lt;br&gt;
For example:&lt;br&gt;
{&lt;br&gt;
  &quot;evidence&quot;: [
 {
   &quot;requirement&quot;: &quot;Unit tests pass&quot;,
   &quot;reference&quot;: &quot;ci:test-run:4821&quot;
 },
 {
   &quot;requirement&quot;: &quot;Security review completed&quot;,
   &quot;reference&quot;: &quot;review:security:913&quot;
 },
 {
   &quot;requirement&quot;: &quot;Metaverse integration demonstrated&quot;,
   &quot;reference&quot;: &quot;demo:metaverse:42&quot;
 }
  ]&lt;br&gt;
}&lt;br&gt;
Then the verification rule becomes:&lt;br&gt;
VERIFIED&lt;br&gt;
only if&lt;br&gt;
every evidenceRequired item&lt;br&gt;
has corresponding evidence&lt;br&gt;
Conceptually:&lt;br&gt;
const missingEvidence =&lt;br&gt;
  requiredEvidence.filter(&lt;br&gt;
 requirement =&amp;gt;&lt;br&gt;
   !coveredRequirements.has(requirement)&lt;br&gt;
  );&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;if (missingEvidence.length) {&lt;br&gt;
  throw new Error(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;`Missing required evidence: ${missingEvidence.join(&quot;, &quot;)}`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
This may look like a small implementation detail.&lt;br&gt;
It is not.&lt;br&gt;
It changes the meaning of VERIFIED.&lt;br&gt;
Without this rule:&lt;br&gt;
VERIFIED = someone attached something&lt;br&gt;
With this rule:&lt;br&gt;
VERIFIED = the declared evidence requirements were actually covered&lt;br&gt;
That is a much stronger guarantee.&lt;br&gt;
DevelopmentRequest Is Not a Bounty&lt;br&gt;
Another architectural decision we intentionally made was separating development from economics.&lt;br&gt;
A DevelopmentRequest can exist without any reward.&lt;br&gt;
That means:&lt;br&gt;
Knowledge&lt;br&gt;
   ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
   ↓&lt;br&gt;
Implementation&lt;br&gt;
   ↓&lt;br&gt;
Verification&lt;br&gt;
can operate independently.&lt;br&gt;
Then, optionally:&lt;br&gt;
DevelopmentRequest&lt;br&gt;
   ↓&lt;br&gt;
Bounty&lt;br&gt;
   ↓&lt;br&gt;
Reward&lt;br&gt;
   ↓&lt;br&gt;
Settlement&lt;br&gt;
may be attached later.&lt;br&gt;
This distinction matters.&lt;br&gt;
A university research project may not use bounties.&lt;br&gt;
An open-source volunteer may contribute without payment.&lt;br&gt;
A company may use fixed contracts.&lt;br&gt;
A decentralized community may use tokens.&lt;br&gt;
A marketplace may use fiat.&lt;br&gt;
The technical work object should not care.&lt;br&gt;
That is why the model contains only:&lt;br&gt;
bountyReference: null&lt;br&gt;
as an optional link.&lt;br&gt;
The economics remain a separate subsystem.&lt;br&gt;
GitHub as Evidence, Not Truth&lt;br&gt;
GitHub is also important in the architecture, but we do not want to make the mistake of treating GitHub itself as truth.&lt;br&gt;
A commit proves that a commit exists.&lt;br&gt;
It does not automatically prove:&lt;br&gt;
the feature works&lt;br&gt;
the requirement is satisfied&lt;br&gt;
the code is secure&lt;br&gt;
the architecture is correct&lt;br&gt;
the scientific result is valid&lt;br&gt;
So GitHub becomes one evidence source among others.&lt;br&gt;
Future DevelopmentRequest verification could combine:&lt;br&gt;
GitHub commit&lt;br&gt;
+&lt;br&gt;
CI test result&lt;br&gt;
+&lt;br&gt;
integration test&lt;br&gt;
+&lt;br&gt;
human review&lt;br&gt;
+&lt;br&gt;
external evidence&lt;br&gt;
This is also why we are working toward a Contribution Graph.&lt;br&gt;
The graph can connect:&lt;br&gt;
Developer&lt;br&gt;
   ↓&lt;br&gt;
Issue&lt;br&gt;
   ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
   ↓&lt;br&gt;
Commit&lt;br&gt;
   ↓&lt;br&gt;
Pull Request&lt;br&gt;
   ↓&lt;br&gt;
Test&lt;br&gt;
   ↓&lt;br&gt;
Review&lt;br&gt;
   ↓&lt;br&gt;
Verified Contribution&lt;br&gt;
That provides a much richer representation of technical reputation.&lt;br&gt;
Where the Metaverse Fits Back In&lt;br&gt;
At first glance, the metaverse and DevelopmentRequest may seem unrelated.&lt;br&gt;
But they are actually part of the same architecture.&lt;br&gt;
Imagine a person entering MyZubster.&lt;br&gt;
The environment could eventually know:&lt;br&gt;
Identity&lt;br&gt;
Wallet&lt;br&gt;
GitHub History&lt;br&gt;
Verified Contributions&lt;br&gt;
Knowledge Contributions&lt;br&gt;
Development Activity&lt;br&gt;
Community Activity&lt;br&gt;
The user does not need to see all of this as raw database records.&lt;br&gt;
The metaverse can become an interface for it.&lt;br&gt;
For example, someone could enter a virtual lab or development room and interact with a project.&lt;br&gt;
Behind the scene:&lt;br&gt;
Metaverse Project&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DevelopmentRequest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified Knowledge&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GitHub Repository&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contributors&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evidence&lt;br&gt;
The virtual environment therefore becomes a way to navigate a real technical graph.&lt;br&gt;
What We Demonstrated Today&lt;br&gt;
During the hearing, we were able to connect several of these concepts in one presentation.&lt;br&gt;
We demonstrated the MyZubster metaverse directly.&lt;br&gt;
We explained Nicola's real-world pilot.&lt;br&gt;
We discussed his AI-related development work.&lt;br&gt;
We explained how user activity can evolve into testing and software contribution.&lt;br&gt;
We described the role of GitHub history.&lt;br&gt;
We explained Zorgax.&lt;br&gt;
We described the difference between AI conversation and verified knowledge.&lt;br&gt;
We presented our university outreach and the idea that scientific pilots require scientific methodology.&lt;br&gt;
And we explained the broader direction:&lt;br&gt;
People perform real activities, software records evidence, AI assists the process, developers build solutions, and independent verification creates new trusted knowledge.&lt;/p&gt;
&lt;p&gt;Universities and Scientific Validation&lt;br&gt;
We also discussed the academic side of the project.&lt;br&gt;
We have started conversations with several universities and research groups around areas including AI, food science, fermentation, circular economy, environmental measurement, LCA/LCSA, and water reuse.&lt;br&gt;
We are intentionally keeping the wording precise.&lt;br&gt;
These are exploratory discussions.&lt;br&gt;
They are not formal partnerships unless and until they are formally established.&lt;br&gt;
The reason universities matter is structural.&lt;br&gt;
MyZubster can build:&lt;br&gt;
software&lt;br&gt;
traceability&lt;br&gt;
data collection&lt;br&gt;
knowledge infrastructure&lt;br&gt;
AI assistance&lt;br&gt;
development workflows&lt;br&gt;
evidence systems&lt;br&gt;
But scientific validation requires additional layers:&lt;br&gt;
scientific protocol&lt;br&gt;
experimental design&lt;br&gt;
control groups&lt;br&gt;
measurement methodology&lt;br&gt;
ethical assessment&lt;br&gt;
statistical analysis&lt;br&gt;
domain expertise&lt;br&gt;
An AI system should not pretend to replace those responsibilities.&lt;br&gt;
LIFE 2027 as a Possible Pilot Framework&lt;br&gt;
We are also exploring whether some of these ideas could eventually fit into a LIFE 2027 project.&lt;br&gt;
Again, this is an exploratory direction.&lt;br&gt;
There is no approved or funded MyZubster LIFE project at this stage.&lt;br&gt;
The interesting part for us is the possibility of connecting environmental pilots with the same verifiable architecture.&lt;br&gt;
For example:&lt;br&gt;
Circular Water Pilot&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sensors / Data&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Evidence&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;University Protocol&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified Knowledge&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zorgax&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DevelopmentRequest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Software Improvement&lt;br&gt;
The same architecture could theoretically apply to fermentation, environmental monitoring, circular economy, Living Labs, or other pilot domains.&lt;br&gt;
That is one reason we are trying to keep the core infrastructure domain-neutral.&lt;br&gt;
The Broader Architecture&lt;br&gt;
If we compress the whole system, the current direction looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;                ┌──────────────────┐
                │    Real World    │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ Data / Evidence  │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ MyZubster        │
                │ Knowledge Layer  │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │      Zorgax      │
                │   AI Assistant   │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │DevelopmentRequest│
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │    Developer     │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ GitHub / CI      │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ Evidence Review  │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ Verified Result  │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │  New Knowledge   │
                └────────┬─────────┘
                         │
                         ▼
                ┌──────────────────┐
                │ Identity/Wallet  │
                │ Metaverse Layer  │
                └──────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a feedback loop.&lt;br&gt;
The output of development can become new knowledge.&lt;br&gt;
That knowledge can generate new development requests.&lt;br&gt;
Those development requests create more evidence.&lt;br&gt;
The evidence can improve the knowledge layer.&lt;br&gt;
What We Have Implemented So Far&lt;br&gt;
At the technical level, the recent work includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Zorgax Knowledge Layer with provenance, content hashing, versioning, visibility and evidence metadata;&lt;/li&gt;
&lt;li&gt;explicit distinction between conversation, candidate information and verified knowledge;&lt;/li&gt;
&lt;li&gt;fail-closed behavior for sensitive knowledge operations;&lt;/li&gt;
&lt;li&gt;preview + digest + explicit human confirmation before persistent DevelopmentRequest creation;&lt;/li&gt;
&lt;li&gt;snapshotting of Knowledge references using contentHash and version;&lt;/li&gt;
&lt;li&gt;idempotent DevelopmentRequest creation;&lt;/li&gt;
&lt;li&gt;a lifecycle covering DRAFT, OPEN, IN_PROGRESS, SUBMITTED, VERIFIED, REJECTED and CANCELLED;&lt;/li&gt;
&lt;li&gt;contributor assignment;&lt;/li&gt;
&lt;li&gt;submission of commit and evidence references;&lt;/li&gt;
&lt;li&gt;independent review rules;&lt;/li&gt;
&lt;li&gt;strict separation between DevelopmentRequest and bounty/payment systems;&lt;/li&gt;
&lt;li&gt;integration points for future GitHub contribution tracking;&lt;/li&gt;
&lt;li&gt;an evidence model being strengthened so every required evidence item must be satisfied before VERIFIED.&lt;br&gt;
This is still evolving.&lt;br&gt;
There are important areas we still want to improve, including stronger revision models, more precise evidence objects, route-level tests, better contribution graph integration, and stronger lineage across Knowledge revisions.&lt;br&gt;
The Principle Behind the Architecture&lt;br&gt;
The most important idea is probably this:&lt;br&gt;
We are not trying to automate trust.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are trying to make trust more inspectable.&lt;br&gt;
AI can help generate code.&lt;br&gt;
AI can help search.&lt;br&gt;
AI can help organize knowledge.&lt;br&gt;
AI can help transform requirements into development tasks.&lt;br&gt;
AI can help developers.&lt;br&gt;
But an AI response should not automatically become truth.&lt;br&gt;
A commit should not automatically become proof.&lt;br&gt;
A wallet should not automatically become reputation.&lt;br&gt;
A submission should not automatically become verification.&lt;br&gt;
The architecture should preserve the difference.&lt;br&gt;
That is what we are trying to encode in the system itself.&lt;br&gt;
What Comes Next&lt;br&gt;
The next engineering steps are straightforward.&lt;br&gt;
We want to finish the stronger DevelopmentRequest evidence invariant, integrate the workflow into the operational branch, and then continue toward the GitHub and Contribution Graph bridge.&lt;br&gt;
After that, we want Zorgax to be able to move through a much richer development loop:&lt;br&gt;
Question&lt;br&gt;
   ↓&lt;br&gt;
Verified Knowledge&lt;br&gt;
   ↓&lt;br&gt;
Architecture&lt;br&gt;
   ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
   ↓&lt;br&gt;
Implementation&lt;br&gt;
   ↓&lt;br&gt;
Tests&lt;br&gt;
   ↓&lt;br&gt;
Independent Verification&lt;br&gt;
   ↓&lt;br&gt;
Delivery&lt;br&gt;
   ↓&lt;br&gt;
Optional Reward&lt;br&gt;
   ↓&lt;br&gt;
New Knowledge&lt;br&gt;
At the same time, we will keep exploring how this architecture can work with real users, academic research, environmental pilots, and the MyZubster metaverse.&lt;br&gt;
The meeting today was useful because we did not have to describe this only as an abstract roadmap.&lt;br&gt;
We were able to show pieces of it working.&lt;br&gt;
There is still a lot to build.&lt;br&gt;
But the architecture is becoming increasingly clear.&lt;br&gt;
Real people create activity. Activity creates evidence. Evidence can become verified knowledge. Knowledge can generate development. Development creates new evidence. AI assists the entire loop without becoming the sole authority.&lt;/p&gt;
&lt;p&gt;That is the direction we are building toward with MyZubster and Zorgax.&lt;br&gt;
MyZubster&lt;br&gt;
Open Source • Verified Knowledge • AI-Assisted Development • GitHub Evidence • Metaverse • Digital Identity • Community&lt;/p&gt;
&lt;h2 id=&quot;ai-opensource-softwarearchitecture-softwaredevelopment-github-metaverse-web3-knowledgegraph-artificialintelligence-nodejs-developers-myzubster-zorgax&quot;&gt;AI #OpenSource #SoftwareArchitecture #SoftwareDevelopment #GitHub #Metaverse #Web3 #KnowledgeGraph #ArtificialIntelligence #NodeJS #Developers #MyZubster #Zorgax&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28184/building-myzubster-as-a-verifiable-ai-development-ecosystem</guid>
<pubDate>Tue, 22 Sep 2026 15:42:36 +0000</pubDate>
</item>
<item>
<title># MyZubster Is Becoming an Identity and Interaction Layer: Authentication → Zorgax → GitHub → Metave</title>
<link>https://coderlegion.com/27596/myzubster-becoming-identity-and-interaction-layer-authentication-zorgax-github-metave</link>
<description>&lt;h2 id=&quot;myzubster-is-becoming-an-identity-and-interaction-layer-authentication-zorgax-github-metaverse-nfts&quot;&gt;MyZubster Is Becoming an Identity and Interaction Layer: Authentication → Zorgax → GitHub → Metaverse → NFTs&lt;/h2&gt;
&lt;p&gt;Over the last few months, MyZubster has changed significantly.&lt;/p&gt;
&lt;p&gt;What started as an open-source ecosystem of experiments is beginning to converge around a much simpler entry point:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authentication → Zorgax → Profile → GitHub → Interactions → Metaverse → Digital Assets&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The interesting part isn't any single technology in that chain.&lt;/p&gt;
&lt;p&gt;It's what happens when they share the same identity and evidence layer.&lt;/p&gt;
&lt;h3 id=&quot;authentication-is-the-starting-point&quot;&gt;Authentication Is the Starting Point&lt;/h3&gt;
&lt;p&gt;When someone authenticates with MyZubster, we don't want the result to be just another empty account.&lt;/p&gt;
&lt;p&gt;Authentication should become the beginning of a persistent ecosystem identity.&lt;/p&gt;
&lt;p&gt;From there, the user can progressively connect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a MyZubster profile;&lt;/li&gt;
&lt;li&gt;interests and skills;&lt;/li&gt;
&lt;li&gt;projects;&lt;/li&gt;
&lt;li&gt;GitHub activity;&lt;/li&gt;
&lt;li&gt;Marketplace activity;&lt;/li&gt;
&lt;li&gt;knowledge and experiments;&lt;/li&gt;
&lt;li&gt;Metaverse identity;&lt;/li&gt;
&lt;li&gt;and, eventually, qualifying digital assets or NFTs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This distinction matters:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authentication proves access to an account.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It does not automatically prove every claim that appears in a profile.&lt;/p&gt;
&lt;h3 id=&quot;zorgax-helps-build-the-profile&quot;&gt;Zorgax Helps Build the Profile&lt;/h3&gt;
&lt;p&gt;This is where Zorgax becomes useful.&lt;/p&gt;
&lt;p&gt;Instead of presenting a new user with a huge registration form, Zorgax can help progressively construct the profile.&lt;/p&gt;
&lt;p&gt;The conversation can start with simple questions:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who are you?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are you building?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What do you know?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What would you like to learn?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What can you contribute?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The architecture becomes:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;USER → AUTH → ZORGAX → PROFILE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Zorgax can help organize the information, improve descriptions, identify missing information and connect the user to relevant parts of MyZubster.&lt;/p&gt;
&lt;p&gt;But the human remains the source of the identity.&lt;/p&gt;
&lt;p&gt;That's why we keep an important boundary:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;HUMAN WORK ≠ AI ASSISTANCE ≠ VERIFIED EVIDENCE&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;then-github-makes-the-profile-inspectable&quot;&gt;Then GitHub Makes the Profile Inspectable&lt;/h3&gt;
&lt;p&gt;For developers and open-source participants, GitHub adds another dimension.&lt;/p&gt;
&lt;p&gt;A person can move from saying:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I build software.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to linking actual public work:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PROFILE → REPOSITORY → ISSUE → COMMIT → PULL REQUEST → PROJECT&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is important for MyZubster because we don't want Zorgax to simply generate impressive biographies.&lt;/p&gt;
&lt;p&gt;Where evidence exists, the profile should be able to point to it.&lt;/p&gt;
&lt;p&gt;GitHub becomes part of the interaction graph.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MYZUBSTER IDENTITY ↔ GITHUB WORK ↔ ZORGAX&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A project can then become discoverable through the person's profile and potentially through other MyZubster experiences.&lt;/p&gt;
&lt;h3 id=&quot;the-same-identity-can-enter-the-metaverse&quot;&gt;The Same Identity Can Enter the Metaverse&lt;/h3&gt;
&lt;p&gt;Now things become more interesting.&lt;/p&gt;
&lt;p&gt;The MyZubster identity doesn't have to stop at a web profile.&lt;/p&gt;
&lt;p&gt;It can also represent the person inside the MyZubster Metaverse.&lt;/p&gt;
&lt;p&gt;Imagine entering a digital space and meeting another avatar.&lt;/p&gt;
&lt;p&gt;That avatar could connect back to:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PERSON&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MYZUBSTER PROFILE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;PROJECTS&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;GITHUB&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;KNOWLEDGE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;DOCUMENTED ACTIVITY&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The Metaverse then stops being only a graphical chat environment.&lt;/p&gt;
&lt;p&gt;It becomes another interface for discovering people, projects, communities and interactions.&lt;/p&gt;
&lt;h3 id=&quot;github-metaverse-creates-a-new-kind-of-interaction&quot;&gt;GitHub + Metaverse Creates a New Kind of Interaction&lt;/h3&gt;
&lt;p&gt;This is one of the directions we're interested in exploring.&lt;/p&gt;
&lt;p&gt;A developer contributes to an open-source project.&lt;/p&gt;
&lt;p&gt;The contribution exists on GitHub.&lt;/p&gt;
&lt;p&gt;The MyZubster profile references that work.&lt;/p&gt;
&lt;p&gt;The same identity enters the Metaverse.&lt;/p&gt;
&lt;p&gt;Other participants can discover the project.&lt;/p&gt;
&lt;p&gt;That can lead to another contribution, collaboration, mission or community interaction.&lt;/p&gt;
&lt;p&gt;The loop becomes:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GITHUB&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MYZUBSTER PROFILE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;METAVERSE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;HUMAN INTERACTION&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;NEW PROJECT / CONTRIBUTION&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;GITHUB&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now GitHub isn't isolated from the social environment around the project.&lt;/p&gt;
&lt;h3 id=&quot;where-nfts-become-interesting&quot;&gt;Where NFTs Become Interesting&lt;/h3&gt;
&lt;p&gt;This also changes how we think about NFTs.&lt;/p&gt;
&lt;p&gt;Instead of starting with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MINT NFT → TRY TO CREATE UTILITY&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;we can explore the opposite direction:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PARTICIPATE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;BUILD&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;INTERACT&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;DOCUMENT&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;VERIFY WHEN POSSIBLE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;QUALIFY&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;OPTIONAL NFT / DIGITAL ASSET&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In that model, the NFT isn't necessarily the product.&lt;/p&gt;
&lt;p&gt;It can become a digital artifact produced by an interaction.&lt;/p&gt;
&lt;p&gt;For example, future assets could reference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an open-source contribution;&lt;/li&gt;
&lt;li&gt;a Metaverse event;&lt;/li&gt;
&lt;li&gt;a creator collectible;&lt;/li&gt;
&lt;li&gt;a completed mission;&lt;/li&gt;
&lt;li&gt;a community artifact;&lt;/li&gt;
&lt;li&gt;a documented project milestone;&lt;/li&gt;
&lt;li&gt;or another qualifying MyZubster interaction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That creates a potential distribution network for digital assets.&lt;/p&gt;
&lt;h3 id=&quot;myzubster-becomes-the-connector&quot;&gt;MyZubster Becomes the Connector&lt;/h3&gt;
&lt;p&gt;The architecture we're moving toward can be represented like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PERSON&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;AUTHENTICATION&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MYZUBSTER IDENTITY&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ZORGAX&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;PROFILE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;GITHUB + PROJECTS + KNOWLEDGE + MARKETPLACE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;INTERACTIONS&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;EVIDENCE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;METAVERSE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;OPTIONAL NFT / DIGITAL ASSET&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And then it loops.&lt;/p&gt;
&lt;p&gt;A GitHub repository can bring somebody into MyZubster.&lt;/p&gt;
&lt;p&gt;A MyZubster profile can bring somebody into the Metaverse.&lt;/p&gt;
&lt;p&gt;A Metaverse interaction can create a new collaboration.&lt;/p&gt;
&lt;p&gt;That collaboration can produce GitHub activity.&lt;/p&gt;
&lt;p&gt;And a qualifying interaction could eventually generate a collectible or another digital asset.&lt;/p&gt;
&lt;h3 id=&quot;the-important-part-don-t-confuse-identity-with-evidence&quot;&gt;The Important Part: Don't Confuse Identity With Evidence&lt;/h3&gt;
&lt;p&gt;Connecting all these systems also creates an obvious risk.&lt;/p&gt;
&lt;p&gt;If we're not careful, a profile could appear to prove things that it doesn't actually prove.&lt;/p&gt;
&lt;p&gt;So we're keeping these concepts separate:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;IDENTITY ≠ CLAIM ≠ ACTIVITY ≠ EVIDENCE ≠ VERIFICATION ≠ NFT&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Authentication doesn't prove expertise.&lt;/p&gt;
&lt;p&gt;A GitHub account doesn't automatically prove that somebody authored everything connected to it.&lt;/p&gt;
&lt;p&gt;Zorgax-generated text doesn't prove a claim.&lt;/p&gt;
&lt;p&gt;A Metaverse interaction doesn't automatically prove a physical-world event.&lt;/p&gt;
&lt;p&gt;And an NFT doesn't magically make its metadata true.&lt;/p&gt;
&lt;p&gt;The architecture becomes more useful when those boundaries remain explicit.&lt;/p&gt;
&lt;h3 id=&quot;what-myzubster-is-becoming&quot;&gt;What MyZubster Is Becoming&lt;/h3&gt;
&lt;p&gt;I used to think mostly about what features MyZubster should contain.&lt;/p&gt;
&lt;p&gt;Now the more interesting question is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What happens when identity, AI assistance, open-source work, digital interaction and verifiable artifacts become connected?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That's the direction we're exploring.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AUTHENTICATE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MEET ZORGAX&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;BUILD YOUR PROFILE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;CONNECT YOUR WORK&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ENTER THE METAVERSE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;INTERACT&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;CREATE&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;DOCUMENT&lt;/code&gt;&lt;br&gt;
&lt;code&gt;↓&lt;/code&gt;&lt;br&gt;
&lt;code&gt;DISTRIBUTE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;MyZubster is gradually becoming less like a collection of separate applications and more like an &lt;strong&gt;identity and interaction layer connecting people, Zorgax, GitHub, the Metaverse and future digital assets&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And that's the next experiment we're building in public.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build → Connect → Interact → Document → Verify → Distribute → Repeat&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;myzubster-zorgax-opensource-github-metaverse-nft-digitalidentity-aiagents-buildinpublic&quot;&gt;MyZubster #Zorgax #OpenSource #GitHub #Metaverse #NFT #DigitalIdentity #AIAgents #BuildInPublic&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27596/myzubster-becoming-identity-and-interaction-layer-authentication-zorgax-github-metave</guid>
<pubDate>Fri, 18 Sep 2026 10:04:10 +0000</pubDate>
</item>
<item>
<title>Building MyZubster World: The Metaverse Infrastructure We Have Implemented</title>
<link>https://coderlegion.com/27311/building-myzubster-world-the-metaverse-infrastructure-we-have-implemented</link>
<description>&lt;p&gt;Building MyZubster World: The Metaverse Infrastructure We Have Implemented&lt;br&gt;
MyZubster is evolving from a marketplace into a circular digital ecosystem connecting verified identities, virtual communities, knowledge sharing, real-world projects, and privacy-conscious services.&lt;br&gt;
The virtual layer of this ecosystem is called MyZubster World.&lt;br&gt;
It is still experimental. We are not presenting it as a finished metaverse, but we have already implemented the technical foundations for identity, rooms, access control, invitations, scheduling, moderation, stage permissions, communication, and persistent progress.&lt;br&gt;
This article explains what currently works and what we want to build next.&lt;br&gt;
Explore MyZubster&lt;br&gt;
These links include readable UTM parameters that can be monitored through Vercel Analytics.&lt;br&gt;
Enter MyZubster World:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=enter_metaverse&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=enter_metaverse&lt;/a&gt;&lt;br&gt;
Explore the marketplace:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=explore_marketplace&quot;&gt;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=explore_marketplace&lt;/a&gt;&lt;br&gt;
Learn how MyZubster works:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/come-funziona?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=how_it_works&quot;&gt;https://www.myzubster.com/come-funziona?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=how_it_works&lt;/a&gt;&lt;br&gt;
Explore the source code:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=github_repository&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=github_repository&lt;/a&gt;&lt;br&gt;
The architecture&lt;br&gt;
MyZubster World currently uses:&lt;br&gt;
React frontend&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Express API&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Authentication and authorization&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Metaverse services&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MongoDB persistence&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vercel deployment and analytics&lt;br&gt;
The frontend handles rendering, interaction, room controls, movement, forms, chat presentation, and user feedback.&lt;br&gt;
The backend remains authoritative for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Character identity&lt;/li&gt;
&lt;li&gt;Room access&lt;/li&gt;
&lt;li&gt;Session lifecycle&lt;/li&gt;
&lt;li&gt;Private invitations&lt;/li&gt;
&lt;li&gt;Capacity&lt;/li&gt;
&lt;li&gt;Scheduling&lt;/li&gt;
&lt;li&gt;Participant moderation&lt;/li&gt;
&lt;li&gt;Stage permissions&lt;/li&gt;
&lt;li&gt;Room chat&lt;/li&gt;
&lt;li&gt;Message moderation&lt;br&gt;
The browser can request an operation, but only the server can approve it.&lt;br&gt;
Verified character identity&lt;br&gt;
A name stored in localStorage cannot be treated as a verified identity because it can be modified through browser developer tools.&lt;br&gt;
For authenticated users, the backend retrieves the canonical character from MongoDB:&lt;br&gt;
const character = await MetaverseCharacter.findOne({&lt;br&gt;
accountUserId: userId,&lt;br&gt;
worldId: WORLD.id,&lt;br&gt;
identityStatus: &quot;account-linked&quot;&lt;br&gt;
});&lt;br&gt;
The frontend replaces outdated local data with the server-provided identity.&lt;br&gt;
MyZubster distinguishes between:&lt;br&gt;
Guest character&lt;br&gt;
└── Temporary and unverified&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Account-linked character&lt;br&gt;
└── Persistent and verified&lt;br&gt;
A client-submitted character name, GitHub username, or MYZ-ID is never considered proof of identity.&lt;br&gt;
Expired-session recovery&lt;br&gt;
We implemented recovery for expired JWT sessions:&lt;br&gt;
if (error.status === 401) {&lt;br&gt;
  localStorage.removeItem(&quot;myzubster-token&quot;);&lt;br&gt;
  setAuthenticated(false);&lt;br&gt;
  setMessage(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;Session expired. Please sign in again.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
The interface can now recover from an invalid authentication state instead of repeatedly sending an expired token.&lt;br&gt;
The login system also preserves private-room invitation URLs, allowing users to authenticate and return to the original invitation.&lt;br&gt;
Persistent exploration progress&lt;br&gt;
Verified characters can discover landmarks inside MyZubster World.&lt;br&gt;
Progress is recorded server-side:&lt;br&gt;
await MetaverseCharacter.findOneAndUpdate(&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;accountUserId: userId,
worldId: WORLD.id,
identityStatus: &quot;account-linked&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$addToSet: {
  &quot;missionProgress.visitedLandmarks&quot;:
    landmarkId
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
);&lt;br&gt;
Using $addToSet prevents duplicate landmark records.&lt;br&gt;
Progress survives browser refreshes, local-storage deletion, new sessions, and device changes.&lt;br&gt;
Shared presence&lt;br&gt;
The current world supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Player entry and exit&lt;/li&gt;
&lt;li&gt;Online-character discovery&lt;/li&gt;
&lt;li&gt;Position synchronization&lt;/li&gt;
&lt;li&gt;Temporary chat&lt;/li&gt;
&lt;li&gt;Emotes&lt;/li&gt;
&lt;li&gt;Reconnection states&lt;/li&gt;
&lt;li&gt;Presence expiration&lt;br&gt;
The client retrieves shared state through an incremental synchronization request:&lt;br&gt;
const result = await syncMetaverse(&lt;br&gt;
sessionId,&lt;br&gt;
cursor&lt;br&gt;
);&lt;br&gt;
The cursor allows the server to return only data that appeared after the previous synchronization.&lt;br&gt;
Why polling is currently used&lt;br&gt;
MyZubster runs in a serverless environment.&lt;br&gt;
Long-lived in-memory connections can be unreliable when requests are distributed between stateless instances. A connection owned by one instance may not exist on another.&lt;br&gt;
The current model uses MongoDB as shared state:&lt;br&gt;
Client A ─┐&lt;pre&gt;&lt;code&gt;    ├── API instances ── MongoDB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Client B ─┘&lt;br&gt;
This is a pragmatic solution for the current stage. A dedicated realtime infrastructure remains on our roadmap.&lt;br&gt;
Server-authoritative rooms&lt;br&gt;
MyZubster World supports persistent virtual rooms with a controlled lifecycle:&lt;br&gt;
Draft&lt;br&gt;
↓&lt;br&gt;
Published&lt;br&gt;
↓&lt;br&gt;
Scheduled&lt;br&gt;
↓&lt;br&gt;
Live&lt;br&gt;
↓&lt;br&gt;
Ended&lt;br&gt;
↓&lt;br&gt;
Archived&lt;br&gt;
Allowed transitions are defined on the server:&lt;br&gt;
const ROOM_TRANSITIONS = {&lt;br&gt;
draft: new Set([&quot;published&quot;]),&lt;br&gt;
published: new Set([
  &quot;scheduled&quot;,
  &quot;live&quot;
]),&lt;br&gt;
scheduled: new Set([&quot;live&quot;]),&lt;br&gt;
live: new Set([&quot;ended&quot;]),&lt;br&gt;
ended: new Set([&quot;archive&quot;]),&lt;br&gt;
archive: new Set()&lt;br&gt;
};&lt;br&gt;
A modified client cannot move a completed room back into a live state.&lt;br&gt;
Room access policies&lt;br&gt;
Rooms support three access policies:&lt;br&gt;
Public&lt;br&gt;
Authenticated&lt;br&gt;
Private&lt;br&gt;
Public rooms can be discovered without authentication.&lt;br&gt;
Authenticated rooms require a valid MyZubster account.&lt;br&gt;
Private rooms require explicit authorization and are excluded from public room discovery.&lt;br&gt;
Unauthorized requests receive a generic 404 response. This limits the amount of information revealed about private spaces.&lt;br&gt;
Host controls&lt;br&gt;
Room hosts can currently:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Create a room draft&lt;/li&gt;
&lt;li&gt;Configure its access policy&lt;/li&gt;
&lt;li&gt;Set capacity&lt;/li&gt;
&lt;li&gt;Configure its stage policy&lt;/li&gt;
&lt;li&gt;Select an optional session date&lt;/li&gt;
&lt;li&gt;Publish the room&lt;/li&gt;
&lt;li&gt;Create a session&lt;/li&gt;
&lt;li&gt;Start the session&lt;/li&gt;
&lt;li&gt;Cancel a scheduled session&lt;/li&gt;
&lt;li&gt;End a live session&lt;/li&gt;
&lt;li&gt;Generate and revoke private invitations&lt;/li&gt;
&lt;li&gt;Remove or block participants&lt;/li&gt;
&lt;li&gt;Restore blocked participants&lt;/li&gt;
&lt;li&gt;Approve speaking requests&lt;/li&gt;
&lt;li&gt;Revoke stage access&lt;/li&gt;
&lt;li&gt;Delete room-chat messages&lt;br&gt;
Every operation is verified on the backend:&lt;br&gt;
function canManage(&lt;br&gt;
actorUserId,&lt;br&gt;
actorRole,&lt;br&gt;
hostUserId&lt;br&gt;
) {&lt;br&gt;
return Boolean(&lt;br&gt;
  actorUserId &amp;amp;&amp;amp;&lt;br&gt;
  (&lt;pre&gt;&lt;code&gt;actorRole === &quot;admin&quot; ||
String(actorUserId) ===
  String(hostUserId)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  )&lt;br&gt;
);&lt;br&gt;
}&lt;br&gt;
Frontend button visibility is used for usability, not authorization.&lt;br&gt;
Capacity controls&lt;br&gt;
Hosts can configure a room capacity between 1 and 500 participants.&lt;br&gt;
The server rejects values outside this range.&lt;br&gt;
A new participant cannot enter a full room, while someone already registered in the session can reconnect without being counted again.&lt;br&gt;
Capacity and other structural settings become locked once the session has been scheduled.&lt;br&gt;
Secure private-room invitations&lt;br&gt;
Private-room links are generated using cryptographically secure randomness:&lt;br&gt;
const code = crypto&lt;br&gt;
.randomBytes(24)&lt;br&gt;
.toString(&quot;base64url&quot;);&lt;br&gt;
The raw code is shown to the host only when created. The database stores its SHA-256 hash:&lt;br&gt;
const hash = crypto&lt;br&gt;
.createHash(&quot;sha256&quot;)&lt;br&gt;
.update(code)&lt;br&gt;
.digest(&quot;hex&quot;);&lt;br&gt;
An invitation:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Expires after 24 hours&lt;/li&gt;
&lt;li&gt;Can be redeemed once&lt;/li&gt;
&lt;li&gt;Can be revoked immediately&lt;/li&gt;
&lt;li&gt;Is replaced when a new invitation is created&lt;/li&gt;
&lt;li&gt;Cannot override the blocklist&lt;/li&gt;
&lt;li&gt;Survives the authentication redirect&lt;/li&gt;
&lt;li&gt;Is never stored in plain text&lt;br&gt;
Atomic invitation redemption&lt;br&gt;
One-time invitations must remain one-time even when multiple requests arrive together.&lt;br&gt;
The invitation is consumed through one conditional MongoDB operation:&lt;br&gt;
const claimedRoom =&lt;br&gt;
await VirtualRoom.findOneAndUpdate(&lt;br&gt;
  {&lt;pre&gt;&lt;code&gt;roomId,
accessPolicy: &quot;private&quot;,
inviteTokenHash: suppliedHash,
inviteExpiresAt: {
  $gt: new Date()
},
blockedUserIds: {
  $ne: actorUserId
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$addToSet: {
  allowedUserIds: actorUserId
},
$set: {
  inviteTokenHash: null,
  inviteExpiresAt: null
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;new: true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
);&lt;br&gt;
The same atomic operation checks the code, verifies expiration, checks the blocklist, authorizes the account, and destroys the invitation.&lt;br&gt;
Only one concurrent request can succeed.&lt;br&gt;
Privacy-conscious participant moderation&lt;br&gt;
Hosts receive a participant list containing an opaque session reference, character name, and archetype:&lt;br&gt;
{&lt;br&gt;
&quot;ref&quot;: &quot;8af39a3d42b781b821003c14&quot;,&lt;br&gt;
&quot;characterName&quot;: &quot;ExampleCharacter&quot;,&lt;br&gt;
&quot;archetype&quot;: &quot;explorer&quot;&lt;br&gt;
}&lt;br&gt;
Internal account IDs are not returned.&lt;br&gt;
The opaque reference is scoped to a specific session:&lt;br&gt;
function moderationParticipantRef(&lt;br&gt;
sessionId,&lt;br&gt;
userId&lt;br&gt;
) {&lt;br&gt;
return sha256(&lt;br&gt;
  &lt;code&gt;${sessionId}:${userId}&lt;/code&gt;&lt;br&gt;
).slice(0, 24);&lt;br&gt;
}&lt;br&gt;
Hosts can remove participants or remove and block them.&lt;br&gt;
When a private-room participant is blocked, their authorization is also removed so they cannot immediately re-enter.&lt;br&gt;
Blocklist management&lt;br&gt;
Hosts can inspect blocked characters without receiving their internal account IDs.&lt;br&gt;
Blocklist references are scoped to the room:&lt;br&gt;
function blockedParticipantRef(&lt;br&gt;
roomId,&lt;br&gt;
userId&lt;br&gt;
) {&lt;br&gt;
return sha256(&lt;br&gt;
  &lt;code&gt;blocklist:${roomId}:${userId}&lt;/code&gt;&lt;br&gt;
).slice(0, 24);&lt;br&gt;
}&lt;br&gt;
The host can restore access for a selected character.&lt;br&gt;
Unblocking does not automatically add the user back to a private room. The user must receive another valid invitation.&lt;br&gt;
Moderated stage&lt;br&gt;
Rooms can use two stage policies:&lt;br&gt;
Host only&lt;br&gt;
Host-approved speakers&lt;br&gt;
In a host-approved room, a joined participant can request permission to speak.&lt;br&gt;
The full workflow is:&lt;br&gt;
Request access&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Host review&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Approve or reject&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Participant receives updated status&lt;br&gt;
Participants can:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Request permission to speak&lt;/li&gt;
&lt;li&gt;Cancel a pending request&lt;/li&gt;
&lt;li&gt;Leave the stage voluntarily&lt;br&gt;
Hosts can:&lt;/li&gt;
&lt;li&gt;Inspect pending requests&lt;/li&gt;
&lt;li&gt;Approve or reject requests&lt;/li&gt;
&lt;li&gt;See current speakers&lt;/li&gt;
&lt;li&gt;Revoke stage permission&lt;br&gt;
Account IDs remain hidden throughout the process.&lt;br&gt;
Session scheduling&lt;br&gt;
Hosts can configure an optional date and time.&lt;br&gt;
The browser converts the local date into an ISO timestamp:&lt;br&gt;
const scheduledFor =&lt;br&gt;
new Date(localValue).toISOString();&lt;br&gt;
The server rejects invalid or past dates.&lt;br&gt;
A session cannot start before the configured date, even if someone manually calls the API.&lt;br&gt;
Rooms without a date can start immediately.&lt;br&gt;
Safe cancellation&lt;br&gt;
A scheduled session can be cancelled before starting.&lt;br&gt;
Cancellation:&lt;/li&gt;
&lt;li&gt;Archives the scheduled session&lt;/li&gt;
&lt;li&gt;Returns the room to the published state&lt;/li&gt;
&lt;li&gt;Restores access to its settings&lt;/li&gt;
&lt;li&gt;Allows the host to correct and reschedule&lt;/li&gt;
&lt;li&gt;Generates a lifecycle event&lt;br&gt;
Starting and cancelling use conditional database updates. If both commands arrive simultaneously, only one can claim the scheduled state.&lt;br&gt;
Automatic room synchronization&lt;br&gt;
Room pages retrieve authoritative state every five seconds.&lt;br&gt;
Without reloading, users can see:&lt;/li&gt;
&lt;li&gt;Session start&lt;/li&gt;
&lt;li&gt;Session cancellation&lt;/li&gt;
&lt;li&gt;Participant-count changes&lt;/li&gt;
&lt;li&gt;Their participation status&lt;/li&gt;
&lt;li&gt;Session completion&lt;/li&gt;
&lt;li&gt;Timeline updates&lt;br&gt;
Cancelled sessions are excluded from current-session results. The latest completed session remains visible for timeline inspection.&lt;br&gt;
Privacy-safe session history&lt;br&gt;
The operational timeline can contain events such as:&lt;br&gt;
session_created&lt;br&gt;
session_started&lt;br&gt;
participant_joined&lt;br&gt;
participant_left&lt;br&gt;
participant_removed&lt;br&gt;
participant_blocked&lt;br&gt;
stage_approved&lt;br&gt;
stage_rejected&lt;br&gt;
stage_left&lt;br&gt;
stage_revoked&lt;br&gt;
session_cancelled&lt;br&gt;
session_ended&lt;br&gt;
Public events contain aggregate data instead of participant IDs:&lt;br&gt;
{&lt;br&gt;
&quot;type&quot;: &quot;participant_joined&quot;,&lt;br&gt;
&quot;participantCount&quot;: 4,&lt;br&gt;
&quot;sequence&quot;: 12&lt;br&gt;
}&lt;br&gt;
Room-scoped chat&lt;br&gt;
Each virtual session now has an isolated chat.&lt;br&gt;
Chat access requires:&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Session membership or host capability&lt;/li&gt;
&lt;li&gt;Absence from the room blocklist&lt;br&gt;
Messages can be sent only while the session is live.&lt;br&gt;
A public message contains:&lt;br&gt;
{&lt;br&gt;
&quot;id&quot;: &quot;message-id&quot;,&lt;br&gt;
&quot;characterName&quot;: &quot;H4x0r&quot;,&lt;br&gt;
&quot;text&quot;: &quot;Hello room&quot;,&lt;br&gt;
&quot;createdAt&quot;:&lt;br&gt;
  &quot;2026-09-15T10:00:00.000Z&quot;&lt;br&gt;
}&lt;br&gt;
Account, room, and internal session identifiers are omitted.&lt;br&gt;
Messages are:&lt;/li&gt;
&lt;li&gt;Sanitized&lt;/li&gt;
&lt;li&gt;Limited to 280 characters&lt;/li&gt;
&lt;li&gt;Rate-controlled&lt;/li&gt;
&lt;li&gt;Retrieved incrementally&lt;/li&gt;
&lt;li&gt;Deduplicated by the client&lt;/li&gt;
&lt;li&gt;Rendered as text&lt;/li&gt;
&lt;li&gt;Automatically deleted after 24 hours&lt;br&gt;
Chat moderation&lt;br&gt;
Hosts and administrators can remove individual messages.&lt;br&gt;
Deletion is scoped to:&lt;br&gt;
Message ID&lt;ul&gt;
&lt;li&gt;Session ID&lt;/li&gt;
&lt;li&gt;Room namespace&lt;br&gt;
An ID from another room cannot be used to delete its message through the current session.&lt;br&gt;
The frontend does not need the sender’s account ID.&lt;br&gt;
Connecting the metaverse to the marketplace&lt;br&gt;
MyZubster World is not intended to remain an isolated virtual experiment.&lt;br&gt;
It will become a visual entry point into marketplace areas such as:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Underground and alternative cultures&lt;/li&gt;
&lt;li&gt;Kefir communities&lt;/li&gt;
&lt;li&gt;Plant cultivation and documentation&lt;/li&gt;
&lt;li&gt;University assistance&lt;/li&gt;
&lt;li&gt;Creative collaboration&lt;/li&gt;
&lt;li&gt;Privacy-conscious technology&lt;br&gt;
The proposed ecosystem is circular:&lt;br&gt;
Discover&lt;br&gt;
 ↓&lt;br&gt;
Learn&lt;br&gt;
 ↓&lt;br&gt;
Collaborate&lt;br&gt;
 ↓&lt;br&gt;
Exchange&lt;br&gt;
 ↓&lt;br&gt;
Document&lt;br&gt;
 ↓&lt;br&gt;
Share&lt;br&gt;
 ↓&lt;br&gt;
Discover again&lt;br&gt;
A user could discover a community in the virtual world, enter its room, exchange knowledge, request help through the marketplace, and share the result with the same community.&lt;br&gt;
What we still need to build&lt;br&gt;
Dedicated realtime infrastructure&lt;br&gt;
The current system uses polling. Future development should evaluate:&lt;/li&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;Managed realtime channels&lt;/li&gt;
&lt;li&gt;Room-scoped broadcasts&lt;/li&gt;
&lt;li&gt;Regional routing&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;li&gt;Reliable reconnection&lt;/li&gt;
&lt;li&gt;Abuse protection&lt;br&gt;
Immersive room scenes&lt;br&gt;
Room authorization and lifecycle management are implemented, but entering a room does not yet launch a complete dedicated immersive scene.&lt;br&gt;
The intended connection is:&lt;br&gt;
Authorized session&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Short-lived room token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Realtime room channel&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Immersive scene&lt;br&gt;
Audio and video&lt;br&gt;
Stage permissions are stored and enforced as application state, but they do not yet activate a production WebRTC transport.&lt;br&gt;
This will require device permissions, speaker enforcement, network recovery, media infrastructure, and privacy documentation.&lt;br&gt;
Message reporting&lt;br&gt;
Hosts can delete messages, but participant reporting still needs:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Reason categories&lt;/li&gt;
&lt;li&gt;Minimal evidence retention&lt;/li&gt;
&lt;li&gt;Abuse prevention&lt;/li&gt;
&lt;li&gt;Review procedures&lt;/li&gt;
&lt;li&gt;Appeal policies&lt;br&gt;
Stronger distributed rate limiting&lt;br&gt;
The current chat uses a basic recent-message check.&lt;br&gt;
Production hardening should introduce atomic distributed limits so concurrent requests cannot bypass the interval.&lt;br&gt;
Marketplace destinations&lt;br&gt;
The virtual world should eventually contain destinations connected to real marketplace information:&lt;br&gt;
Neon Plaza&lt;br&gt;
 ├── Underground Culture&lt;br&gt;
 ├── Kefir and Cultivation&lt;br&gt;
 ├── University Collaboration&lt;br&gt;
 ├── Creators&lt;br&gt;
 └── Privacy Technology&lt;br&gt;
Monero research&lt;br&gt;
We are evaluating Monero for appropriate marketplace transactions.&lt;br&gt;
A production integration still requires work on wallet architecture, payment verification, confirmations, refunds, exchange rates, accounting, security, and regulatory responsibilities.&lt;br&gt;
It remains a research and development objective rather than a completed payment feature.&lt;br&gt;
Monitoring this article with Vercel Analytics&lt;br&gt;
All public links in this article use:&lt;br&gt;
utm_source=coderlegion&lt;br&gt;
utm_medium=article&lt;br&gt;
utm_campaign=myzubster_metaverse_build&lt;br&gt;
Each link has a separate utm_content value so traffic from different calls to action can be distinguished.&lt;br&gt;
Authorized project members can inspect the results here:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://vercel.com/myzubster/my-zubster-app/analytics&quot;&gt;https://vercel.com/myzubster/my-zubster-app/analytics&lt;/a&gt;&lt;br&gt;
The Vercel dashboard is private. Readers should use the public MyZubster links.&lt;br&gt;
Follow the project&lt;br&gt;
Enter MyZubster World:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_metaverse_cta&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_metaverse_cta&lt;/a&gt;&lt;br&gt;
Explore the marketplace:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_marketplace_cta&quot;&gt;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_marketplace_cta&lt;/a&gt;&lt;br&gt;
Learn how the ecosystem works:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/come-funziona?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_how_it_works_cta&quot;&gt;https://www.myzubster.com/come-funziona?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_how_it_works_cta&lt;/a&gt;&lt;br&gt;
View the source code:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_github_cta&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_metaverse_build&amp;amp;utm_content=final_github_cta&lt;/a&gt;&lt;br&gt;
MyZubster World remains experimental, but it is becoming a server-authoritative platform with real identity, privacy, lifecycle, moderation, scheduling, and communication systems.&lt;br&gt;
We are building it publicly, one verifiable layer at a time.&lt;br&gt;
What should we implement next: immersive rooms, realtime infrastructure, participant reporting, or marketplace destinations?&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27311/building-myzubster-world-the-metaverse-infrastructure-we-have-implemented</guid>
<pubDate>Tue, 15 Sep 2026 16:59:49 +0000</pubDate>
</item>
<item>
<title>Building MyZubster World: The Architecture We Have Implemented and What Is Still Missing</title>
<link>https://coderlegion.com/27204/building-myzubster-world-the-architecture-we-have-implemented-and-what-is-still-missing</link>
<description>&lt;p&gt;Building MyZubster World: The Architecture We Have Implemented and What Is Still Missing&lt;br&gt;
MyZubster started as a marketplace, but our long-term vision is broader: we want to build a circular ecosystem connecting digital identity, virtual communities, knowledge sharing, real-world projects, and privacy-conscious transactions.&lt;br&gt;
That vision is becoming MyZubster World, an experimental metaverse connected directly to the MyZubster marketplace.&lt;br&gt;
This is not a post announcing a finished metaverse. It is a technical development log explaining what is already implemented, how the main components work, and what still needs to be built before the platform can offer a complete immersive experience.&lt;br&gt;
The architecture&lt;br&gt;
The current system is divided into several layers:&lt;br&gt;
React frontend&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Express API&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Authentication and authorization&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Metaverse services&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MongoDB persistence&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vercel deployment&lt;br&gt;
The frontend renders the world, room controls, character state, marketplace destinations, and user feedback.&lt;br&gt;
The backend remains authoritative for identity, access, room lifecycle, invitations, capacity, and session state. The browser can request an action, but it cannot declare that the action succeeded.&lt;br&gt;
This distinction is important. Client-side controls can improve usability, but they cannot provide real security.&lt;br&gt;
Verified character identity&lt;br&gt;
One of the first problems we addressed was identity.&lt;br&gt;
A character name stored only in localStorage is not a verified identity. Anyone can open the browser’s developer tools and change it.&lt;br&gt;
For authenticated users, the backend now retrieves the character linked to the account:&lt;br&gt;
const character = await MetaverseCharacter.findOne({&lt;br&gt;
  accountUserId: userId,&lt;br&gt;
  worldId: WORLD.id,&lt;br&gt;
  identityStatus: 'account-linked'&lt;br&gt;
});&lt;br&gt;
The server returns the canonical character profile:&lt;br&gt;
{&lt;br&gt;
  &quot;characterName&quot;: &quot;H4x0r&quot;,&lt;br&gt;
  &quot;identityStatus&quot;: &quot;account-linked&quot;,&lt;br&gt;
  &quot;archetype&quot;: &quot;explorer&quot;,&lt;br&gt;
  &quot;worldId&quot;: &quot;neon-plaza&quot;&lt;br&gt;
}&lt;br&gt;
The frontend replaces any stale local profile with this server-provided identity.&lt;br&gt;
Guest identities remain possible, but they are explicitly treated as unverified:&lt;br&gt;
const verified =&lt;br&gt;
  player.identityStatus === 'account-linked';&lt;br&gt;
This gives us two distinct modes:&lt;br&gt;
Guest → temporary and unverified&lt;br&gt;
Account-linked character → persistent and verified&lt;br&gt;
We do not treat a client-supplied name, GitHub username, or MYZ-ID as proof of identity.&lt;br&gt;
Authentication recovery&lt;br&gt;
We also implemented expired-session handling.&lt;br&gt;
A common failure occurred when the frontend still contained an old JWT. The interface appeared authenticated, but protected API calls returned 401 Unauthorized.&lt;br&gt;
The frontend now recognizes this state:&lt;br&gt;
if (profileError.status === 401) {&lt;br&gt;
  localStorage.removeItem('myzubster-token');&lt;br&gt;
  setAuthenticated(false);&lt;br&gt;
  setMessage('Session expired. Please sign in again.');&lt;br&gt;
}&lt;br&gt;
This prevents the application from remaining trapped between authenticated and unauthenticated states.&lt;br&gt;
The GitHub OAuth callback and production environment configuration were also reviewed so authenticated users can return to the metaverse after login.&lt;br&gt;
Persistent mission progress&lt;br&gt;
The metaverse includes landmarks that users can discover.&lt;br&gt;
For authenticated characters, visited landmarks are recorded server-side:&lt;br&gt;
await MetaverseCharacter.findOneAndUpdate(&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;accountUserId: userId,
worldId: WORLD.id,
identityStatus: 'account-linked'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$addToSet: {
  'missionProgress.visitedLandmarks': landmarkId
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
);&lt;br&gt;
Using $addToSet prevents duplicate landmark entries.&lt;br&gt;
This allows progress to persist across:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browser refreshes&lt;/li&gt;
&lt;li&gt;New sessions&lt;/li&gt;
&lt;li&gt;Different devices&lt;/li&gt;
&lt;li&gt;Local-storage deletion&lt;br&gt;
Local state is still used for responsiveness, but MongoDB is the durable source of truth for verified accounts.&lt;br&gt;
Shared presence&lt;br&gt;
MyZubster World currently uses database-backed synchronization rather than a permanent WebSocket connection.&lt;br&gt;
The frontend periodically sends the active session identifier:&lt;br&gt;
const result = await syncMetaverse(&lt;br&gt;
sessionId,&lt;br&gt;
cursor&lt;br&gt;
);&lt;br&gt;
The server returns:&lt;br&gt;
{&lt;br&gt;
&quot;players&quot;: [],&lt;br&gt;
&quot;messages&quot;: [],&lt;br&gt;
&quot;online&quot;: 0,&lt;br&gt;
&quot;cursor&quot;: &quot;2026-09-15T00:00:00.000Z&quot;,&lt;br&gt;
&quot;transport&quot;: &quot;shared-polling&quot;&lt;br&gt;
}&lt;br&gt;
The current shared state supports:&lt;/li&gt;
&lt;li&gt;Player presence&lt;/li&gt;
&lt;li&gt;Position updates&lt;/li&gt;
&lt;li&gt;Join and leave events&lt;/li&gt;
&lt;li&gt;Chat messages&lt;/li&gt;
&lt;li&gt;Emotes&lt;/li&gt;
&lt;li&gt;Online-player counts&lt;/li&gt;
&lt;li&gt;Reconnection states&lt;br&gt;
The synchronization cycle is intentionally predictable:&lt;br&gt;
const SYNC_INTERVAL_MS = 1800;&lt;br&gt;
If a request temporarily fails, the frontend enters a reconnecting state and tries again instead of immediately removing the player.&lt;br&gt;
Why we currently use polling&lt;br&gt;
MyZubster is deployed in a serverless environment.&lt;br&gt;
Long-lived connections can be unreliable when requests are distributed between stateless instances. An in-memory event stream on one server instance may not be visible to another instance.&lt;br&gt;
For this reason, the current architecture favors shared persistence:&lt;br&gt;
Client A ─┐&lt;pre&gt;&lt;code&gt;    ├── API instances ── MongoDB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Client B ─┘&lt;br&gt;
This is less immediate than a dedicated realtime server, but it provides a coherent shared state during the experimental phase.&lt;br&gt;
The older event-stream endpoint remains available for compatibility, but the current web client uses shared polling.&lt;br&gt;
Presence expiration&lt;br&gt;
Player presence must not remain online forever after a browser closes unexpectedly.&lt;br&gt;
Presence records therefore include expiration timestamps:&lt;br&gt;
{&lt;br&gt;
lastSeenAt: Date,&lt;br&gt;
expiresAt: Date&lt;br&gt;
}&lt;br&gt;
Each synchronization refreshes the expiration time. MongoDB’s expiration strategy removes abandoned presence records after their retention window.&lt;br&gt;
This handles cases such as:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Closing the browser without pressing “Leave”&lt;/li&gt;
&lt;li&gt;Losing the network connection&lt;/li&gt;
&lt;li&gt;Browser crashes&lt;/li&gt;
&lt;li&gt;Mobile operating systems suspending the tab&lt;br&gt;
Chat and emotes&lt;br&gt;
The current world includes temporary chat and emote actions.&lt;br&gt;
Chat input is cleaned and limited before persistence:&lt;br&gt;
const text = cleanText(req.body?.text, 280);&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;if (!text) {&lt;br&gt;
  return res.status(400).json({&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;success: false,
error: 'Message is empty'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  });&lt;br&gt;
}&lt;br&gt;
Actions also use rate limits to reduce spam:&lt;br&gt;
if (!allowAction(sessionId, 'chat', 700)) {&lt;br&gt;
  return res.status(429).json({&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;success: false,
error: 'Chat rate exceeded'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  });&lt;br&gt;
}&lt;br&gt;
Chat history is intentionally temporary. It is not designed as permanent public content.&lt;br&gt;
Production logging excludes message bodies, authorization headers, tokens, query strings, and session identifiers.&lt;br&gt;
Server-authoritative virtual rooms&lt;br&gt;
We have implemented persistent virtual rooms with an explicit lifecycle:&lt;br&gt;
Draft&lt;br&gt;
  ↓&lt;br&gt;
Published&lt;br&gt;
  ↓&lt;br&gt;
Scheduled&lt;br&gt;
  ↓&lt;br&gt;
Live&lt;br&gt;
  ↓&lt;br&gt;
Ended&lt;br&gt;
  ↓&lt;br&gt;
Archived&lt;br&gt;
The permitted transitions are represented on the backend:&lt;br&gt;
const ROOM_TRANSITIONS = {&lt;br&gt;
  draft: new Set(['published']),&lt;br&gt;
  published: new Set(['scheduled', 'live']),&lt;br&gt;
  scheduled: new Set(['live']),&lt;br&gt;
  live: new Set(['ended']),&lt;br&gt;
  ended: new Set(['archive']),&lt;br&gt;
  archive: new Set()&lt;br&gt;
};&lt;br&gt;
A request attempting an invalid transition is rejected:&lt;br&gt;
if (!ROOM_TRANSITIONS[room.state]?.has(nextState)) {&lt;br&gt;
  return {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;valid: false,
status: 409,
error: `Invalid room transition`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  };&lt;br&gt;
}&lt;br&gt;
The frontend cannot move a room from ended back to live, even if someone manually modifies the request.&lt;br&gt;
Host permissions&lt;br&gt;
Room-management actions verify the account on the server:&lt;br&gt;
function canManage(&lt;br&gt;
  actorUserId,&lt;br&gt;
  actorRole,&lt;br&gt;
  hostUserId&lt;br&gt;
) {&lt;br&gt;
  return Boolean(&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;actorUserId &amp;amp;&amp;amp;
(
  actorRole === 'admin' ||
  String(actorUserId) === String(hostUserId)
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  );&lt;br&gt;
}&lt;br&gt;
Only the room host or an administrator can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Update room settings&lt;/li&gt;
&lt;li&gt;Publish a room&lt;/li&gt;
&lt;li&gt;Create a session&lt;/li&gt;
&lt;li&gt;Start a session&lt;/li&gt;
&lt;li&gt;End a session&lt;/li&gt;
&lt;li&gt;Generate an invitation&lt;/li&gt;
&lt;li&gt;Inspect invitation status&lt;/li&gt;
&lt;li&gt;Revoke an invitation&lt;br&gt;
Showing or hiding a button in React is not the authorization mechanism. Every operation is validated again by the backend.&lt;br&gt;
Room access policies&lt;br&gt;
Rooms currently support three policies:&lt;br&gt;
accessPolicy: {&lt;br&gt;
type: String,&lt;br&gt;
enum: [
  'public',
  'authenticated',
  'private'
]&lt;br&gt;
}&lt;br&gt;
Public rooms&lt;br&gt;
Public rooms can be discovered without authentication.&lt;br&gt;
Authenticated rooms&lt;br&gt;
These rooms require a valid MyZubster account.&lt;br&gt;
Private rooms&lt;br&gt;
Private rooms require explicit authorization.&lt;br&gt;
Private rooms do not appear in the public discovery response:&lt;br&gt;
function roomDiscoveryQuery(authenticated) {&lt;br&gt;
return {&lt;br&gt;
  state: {&lt;pre&gt;&lt;code&gt;$in: ['published', 'scheduled', 'live']
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  accessPolicy: authenticated&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? { $in: ['public', 'authenticated'] }
: 'public'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;};&lt;br&gt;
}&lt;br&gt;
Even authenticated users cannot discover private rooms unless they have received access through the invitation system.&lt;br&gt;
Unauthorized requests return a generic 404 response. This reduces information leakage about the existence of private spaces.&lt;br&gt;
Room capacity&lt;br&gt;
Hosts can configure room capacity between 1 and 500 participants.&lt;br&gt;
The value is validated server-side:&lt;br&gt;
const capacity = Number(input.capacity);&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;if (&lt;br&gt;
  !Number.isInteger(capacity) ||&lt;br&gt;
  capacity &amp;lt; 1 ||&lt;br&gt;
  capacity &amp;gt; 500&lt;br&gt;
) {&lt;br&gt;
  return {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;valid: false,
status: 400,
error: 'Capacity must be between 1 and 500'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  };&lt;br&gt;
}&lt;br&gt;
When a session is full, new participants cannot join. An existing participant, however, can reconnect without being rejected as an additional person.&lt;br&gt;
Room access and capacity become locked after session scheduling. This avoids changing fundamental rules while a session is already underway.&lt;br&gt;
Session participation&lt;br&gt;
The platform now supports:&lt;br&gt;
Create session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start session&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Participant joins&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Participant leaves&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Host ends session&lt;br&gt;
When joining, the backend checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Session state&lt;/li&gt;
&lt;li&gt;Room blocklist&lt;/li&gt;
&lt;li&gt;Private-room authorization&lt;/li&gt;
&lt;li&gt;Capacity&lt;/li&gt;
&lt;li&gt;Existing participation&lt;br&gt;
A simplified version of the logic looks like this:&lt;br&gt;
if (session.state !== 'live') {&lt;br&gt;
return deny('Session is not live');&lt;br&gt;
}&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;if (room.blockedUserIds.includes(userId)) {&lt;br&gt;
  return deny('Access blocked');&lt;br&gt;
}&lt;/p&gt;
&lt;p&gt;if (&lt;br&gt;
  room.accessPolicy === 'private' &amp;amp;&amp;amp;&lt;br&gt;
  !room.allowedUserIds.includes(userId) &amp;amp;&amp;amp;&lt;br&gt;
  userId !== room.hostUserId&lt;br&gt;
) {&lt;br&gt;
  return deny('Private room access denied');&lt;br&gt;
}&lt;/p&gt;
&lt;p&gt;if (&lt;br&gt;
  !alreadyJoined &amp;amp;&amp;amp;&lt;br&gt;
  participantCount &amp;gt;= session.capacity&lt;br&gt;
) {&lt;br&gt;
  return deny('Session is at capacity');&lt;br&gt;
}&lt;br&gt;
Short-lived realtime tokens&lt;br&gt;
After authorization, the backend can generate a short-lived token for future room-scoped realtime connections:&lt;br&gt;
jwt.sign(&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sub: userId,
purpose: 'metaverse-realtime',
sessionId: session.sessionId,
roomId: session.roomId,
sceneManifestVersion:
  session.sceneManifestVersion
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  },&lt;br&gt;
  secret,&lt;br&gt;
  {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;expiresIn: '5m'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  }&lt;br&gt;
);&lt;br&gt;
These tokens expire after five minutes.&lt;br&gt;
The current room page does not pretend this token launches a complete immersive realtime client. That integration is still pending.&lt;br&gt;
Privacy-safe session history&lt;br&gt;
Room sessions produce technical events:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;session_created&lt;/li&gt;
&lt;li&gt;session_started&lt;/li&gt;
&lt;li&gt;participant_joined&lt;/li&gt;
&lt;li&gt;participant_left&lt;/li&gt;
&lt;li&gt;session_ended&lt;br&gt;
The frontend polls for new events using an incremental cursor.&lt;br&gt;
Public event representations contain aggregate information, such as participant count, but do not expose participant account IDs.&lt;br&gt;
{&lt;br&gt;
&quot;type&quot;: &quot;participant_joined&quot;,&lt;br&gt;
&quot;participantCount&quot;: 4,&lt;br&gt;
&quot;sequence&quot;: 12&lt;br&gt;
}&lt;br&gt;
Events are retained temporarily and are presented as operational history, not permanent user tracking.&lt;br&gt;
Private invitation links&lt;br&gt;
The latest implementation makes private rooms practically accessible.&lt;br&gt;
A host can generate an invitation code:&lt;br&gt;
const code = crypto&lt;br&gt;
.randomBytes(24)&lt;br&gt;
.toString('base64url');&lt;br&gt;
The raw code is returned once to the host. It is not stored in the database.&lt;br&gt;
Instead, the backend stores a SHA-256 hash:&lt;br&gt;
const hash = crypto&lt;br&gt;
.createHash('sha256')&lt;br&gt;
.update(code)&lt;br&gt;
.digest('hex');&lt;br&gt;
During redemption, the submitted code is hashed and compared using timingSafeEqual:&lt;br&gt;
const valid =&lt;br&gt;
expected.length === supplied.length &amp;amp;&amp;amp;&lt;br&gt;
crypto.timingSafeEqual(expected, supplied);&lt;br&gt;
The invitation:&lt;/li&gt;
&lt;li&gt;Expires after 24 hours&lt;/li&gt;
&lt;li&gt;Can be redeemed once&lt;/li&gt;
&lt;li&gt;Can be revoked immediately&lt;/li&gt;
&lt;li&gt;Is replaced when a new invitation is generated&lt;/li&gt;
&lt;li&gt;Cannot override a blocklist&lt;/li&gt;
&lt;li&gt;Survives the login redirect&lt;/li&gt;
&lt;li&gt;Never exposes its stored hash through the status API&lt;br&gt;
After successful redemption, the authenticated account is added to the room allowlist and the invitation is cleared.&lt;br&gt;
Invitation management&lt;br&gt;
An host can inspect only safe invitation metadata:&lt;br&gt;
{&lt;br&gt;
&quot;active&quot;: true,&lt;br&gt;
&quot;expiresAt&quot;: &quot;2026-09-16T00:00:00.000Z&quot;&lt;br&gt;
}&lt;br&gt;
The response never includes:&lt;/li&gt;
&lt;li&gt;The invitation code&lt;/li&gt;
&lt;li&gt;Its hash&lt;/li&gt;
&lt;li&gt;The invited user ID&lt;/li&gt;
&lt;li&gt;The room blocklist&lt;br&gt;
The host can revoke the invitation through an authenticated DELETE request:&lt;br&gt;
DELETE /api/metaverse/rooms/:room/invitations&lt;br&gt;
After revocation, the old link can no longer authorize a new account.&lt;br&gt;
The connection with the marketplace&lt;br&gt;
MyZubster World is not intended to remain separate from the marketplace.&lt;br&gt;
The marketplace explores areas such as:&lt;/li&gt;
&lt;li&gt;Underground and alternative subcultures&lt;/li&gt;
&lt;li&gt;Kefir communities&lt;/li&gt;
&lt;li&gt;Plant cultivation and documentation&lt;/li&gt;
&lt;li&gt;University assistance&lt;/li&gt;
&lt;li&gt;Creative and technical collaboration&lt;/li&gt;
&lt;li&gt;Privacy-conscious services&lt;br&gt;
Our proposed cycle is:&lt;br&gt;
Discover&lt;br&gt;
 ↓&lt;br&gt;
Learn&lt;br&gt;
 ↓&lt;br&gt;
Collaborate&lt;br&gt;
 ↓&lt;br&gt;
Exchange&lt;br&gt;
 ↓&lt;br&gt;
Document&lt;br&gt;
 ↓&lt;br&gt;
Share&lt;br&gt;
 ↓&lt;br&gt;
Discover again&lt;br&gt;
A user may discover a cultivation project inside the metaverse, join its community room, contribute knowledge, request assistance through the marketplace, and document the result for other members.&lt;br&gt;
This is what we mean by a circular ecosystem: the virtual environment should lead to useful activity rather than functioning only as decoration.&lt;br&gt;
What is still missing&lt;br&gt;
The foundations are growing, but several important systems are not complete.&lt;ol&gt;
&lt;li&gt;Immersive room connection&lt;br&gt;
The authorization and session layers exist, but entering a room does not yet launch a dedicated immersive scene.&lt;br&gt;
We still need to connect:&lt;br&gt;
Authorized room session&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Short-lived realtime token&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Room-specific transport&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Immersive scene&lt;br&gt;
The scene must preserve the same access, capacity, and moderation rules enforced by the API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Dedicated realtime transport&lt;br&gt;
Database polling is appropriate for the current prototype, but larger rooms will require a dedicated realtime service.&lt;br&gt;
We need to evaluate:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;Managed realtime infrastructure&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;li&gt;Reconnection strategies&lt;/li&gt;
&lt;li&gt;Presence consistency&lt;/li&gt;
&lt;li&gt;Regional latency&lt;/li&gt;
&lt;li&gt;Abuse protection&lt;br&gt;
The migration should be driven by measurements, not by the assumption that WebSockets are automatically better.&lt;ol&gt;
&lt;li&gt;Participant moderation&lt;br&gt;
Hosts need privacy-conscious moderation tools.&lt;br&gt;
The roadmap includes:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Removing a participant&lt;/li&gt;
&lt;li&gt;Blocking future access&lt;/li&gt;
&lt;li&gt;Restoring access&lt;/li&gt;
&lt;li&gt;Revoking private-room membership&lt;/li&gt;
&lt;li&gt;Recording moderation events&lt;/li&gt;
&lt;li&gt;Preventing immediate unauthorized re-entry&lt;br&gt;
We must provide these controls without publishing internal account identifiers.&lt;ol&gt;
&lt;li&gt;Stage requests&lt;br&gt;
Rooms already contain a stage policy:&lt;br&gt;
stagePolicy: {&lt;br&gt;
type: String,&lt;br&gt;
enum: [
  'host-only',
  'host-approved'
]&lt;br&gt;
}&lt;br&gt;
However, the complete interaction is not yet implemented.&lt;br&gt;
The intended flow is:&lt;br&gt;
Participant requests to speak&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Host reviews the request&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Host approves or rejects&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Server assigns stage capability&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Capability expires or is revoked&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Room-specific chat&lt;br&gt;
The global prototype supports chat, but room-scoped communication still needs stronger boundaries.&lt;br&gt;
Messages should be associated with:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;A room&lt;/li&gt;
&lt;li&gt;A session&lt;/li&gt;
&lt;li&gt;An authorized participant&lt;/li&gt;
&lt;li&gt;A defined retention policy&lt;/li&gt;
&lt;li&gt;Moderation state&lt;ol&gt;
&lt;li&gt;Marketplace destinations&lt;br&gt;
Marketplace categories currently need a deeper connection with the virtual world.&lt;br&gt;
Our plan is to turn categories into interactive destinations:&lt;br&gt;
Neon Plaza&lt;br&gt;
 ├── Underground Culture&lt;br&gt;
 ├── Kefir and Cultivation&lt;br&gt;
 ├── University Collaboration&lt;br&gt;
 ├── Creators&lt;br&gt;
 └── Privacy Technology&lt;br&gt;
Each destination should load real marketplace information rather than static decorative content.&lt;/li&gt;
&lt;li&gt;Collaborative activities&lt;br&gt;
The long-term experience should support useful interaction:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Workshops&lt;/li&gt;
&lt;li&gt;Study sessions&lt;/li&gt;
&lt;li&gt;Community presentations&lt;/li&gt;
&lt;li&gt;Cultivation journals&lt;/li&gt;
&lt;li&gt;Project showcases&lt;/li&gt;
&lt;li&gt;Mentoring&lt;/li&gt;
&lt;li&gt;Marketplace demonstrations&lt;br&gt;
These activities still require data models, permissions, interfaces, and moderation rules.&lt;ol&gt;
&lt;li&gt;Automated testing&lt;br&gt;
We have policy and interface-wiring tests, but the project still needs broader coverage:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Integration tests with MongoDB&lt;/li&gt;
&lt;li&gt;Authentication tests&lt;/li&gt;
&lt;li&gt;Invitation race-condition tests&lt;/li&gt;
&lt;li&gt;Capacity concurrency tests&lt;/li&gt;
&lt;li&gt;OAuth callback tests&lt;/li&gt;
&lt;li&gt;Browser end-to-end tests&lt;/li&gt;
&lt;li&gt;Accessibility tests&lt;/li&gt;
&lt;li&gt;Load testing&lt;br&gt;
One particularly important case is simultaneous redemption of a monouso invitation. The final production implementation should use an atomic database update so two requests cannot consume the same code at nearly the same time.&lt;ol&gt;
&lt;li&gt;Monitoring&lt;br&gt;
The application uses Vercel Analytics and deployment observability, but product-specific monitoring needs to improve.&lt;br&gt;
We want to measure:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Metaverse entry funnel&lt;/li&gt;
&lt;li&gt;Successful authenticated joins&lt;/li&gt;
&lt;li&gt;Room creation&lt;/li&gt;
&lt;li&gt;Session starts&lt;/li&gt;
&lt;li&gt;Invitation redemption&lt;/li&gt;
&lt;li&gt;Marketplace transitions&lt;/li&gt;
&lt;li&gt;Reconnection frequency&lt;/li&gt;
&lt;li&gt;API errors and latency&lt;br&gt;
Analytics events must remain privacy-conscious and avoid collecting unnecessary identity or message data.&lt;ol&gt;
&lt;li&gt;Accessibility and mobile interaction&lt;br&gt;
The metaverse must remain usable outside a desktop keyboard environment.&lt;br&gt;
We still need:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Touch controls&lt;/li&gt;
&lt;li&gt;Keyboard navigation&lt;/li&gt;
&lt;li&gt;Reduced-motion support&lt;/li&gt;
&lt;li&gt;Screen-reader labels&lt;/li&gt;
&lt;li&gt;High-contrast states&lt;/li&gt;
&lt;li&gt;Responsive room controls&lt;/li&gt;
&lt;li&gt;Accessible chat&lt;/li&gt;
&lt;li&gt;Performance testing on low-end devices&lt;ol&gt;
&lt;li&gt;Monero research&lt;br&gt;
We are evaluating Monero as a possible payment option for appropriate marketplace transactions.&lt;br&gt;
A production integration still needs research and implementation for:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Wallet architecture&lt;/li&gt;
&lt;li&gt;Payment verification&lt;/li&gt;
&lt;li&gt;Unique payment identification&lt;/li&gt;
&lt;li&gt;Confirmation policies&lt;/li&gt;
&lt;li&gt;Refunds&lt;/li&gt;
&lt;li&gt;Disputes&lt;/li&gt;
&lt;li&gt;Exchange-rate handling&lt;/li&gt;
&lt;li&gt;Accounting&lt;/li&gt;
&lt;li&gt;Regulatory responsibilities&lt;/li&gt;
&lt;li&gt;Secret management&lt;/li&gt;
&lt;li&gt;Operational security&lt;br&gt;
Monero payment support should therefore be considered a roadmap item, not a finished production feature.&lt;br&gt;
How we are building&lt;br&gt;
We are developing MyZubster through small, reviewable increments.&lt;br&gt;
Recent pull requests introduced:&lt;/li&gt;
&lt;li&gt;Persistent mission progress&lt;/li&gt;
&lt;li&gt;Canonical character identity&lt;/li&gt;
&lt;li&gt;Expired-JWT recovery&lt;/li&gt;
&lt;li&gt;Filtered room discovery&lt;/li&gt;
&lt;li&gt;Authoritative room details&lt;/li&gt;
&lt;li&gt;Room lifecycle management&lt;/li&gt;
&lt;li&gt;Join and leave controls&lt;/li&gt;
&lt;li&gt;Private-room authorization&lt;/li&gt;
&lt;li&gt;Privacy-safe session events&lt;/li&gt;
&lt;li&gt;Host room settings&lt;/li&gt;
&lt;li&gt;Secure invitation links&lt;/li&gt;
&lt;li&gt;Invitation status and revocation&lt;br&gt;
This approach lets us review each security and privacy boundary before adding more visual complexity.&lt;br&gt;
The infrastructure underneath the world may be less visible than a 3D animation, but it determines whether the final experience can be trusted.&lt;br&gt;
Explore MyZubster&lt;/li&gt;
&lt;li&gt;Enter MyZubster World&lt;/li&gt;
&lt;li&gt;Explore the Marketplace&lt;/li&gt;
&lt;li&gt;Learn how MyZubster works&lt;/li&gt;
&lt;li&gt;View the source code&lt;br&gt;
MyZubster World is still experimental, but its identity, access, lifecycle, invitation, persistence, and privacy foundations are now taking shape.&lt;br&gt;
We are building it publicly, one verifiable layer at a time.&lt;br&gt;
What would you implement next: immersive rooms, realtime transport, marketplace destinations, or host moderation?&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27204/building-myzubster-world-the-architecture-we-have-implemented-and-what-is-still-missing</guid>
<pubDate>Tue, 15 Sep 2026 00:18:22 +0000</pubDate>
</item>
<item>
<title>Building MyZubster: A Circular Marketplace Connected to a Social Metaverse</title>
<link>https://coderlegion.com/27164/building-myzubster-a-circular-marketplace-connected-to-a-social-metaverse</link>
<description>&lt;p&gt;Building MyZubster: A Circular Marketplace Connected to a Social Metaverse&lt;br&gt;
MyZubster is an open-source ecosystem that connects a circular marketplace, local communities, educational support, underground culture, visual storytelling and an experimental social metaverse.&lt;br&gt;
The project is based on a cyclical model:&lt;br&gt;
Discover → Connect → Exchange → Use → Learn → Repair → Reuse → Recover → Contribute&lt;br&gt;
Instead of building another isolated marketplace or virtual world, MyZubster connects these activities through shared navigation, account-linked characters and measurable user journeys.&lt;br&gt;
The MyZubster Marketplace&lt;br&gt;
The Marketplace is the operational discovery layer of the ecosystem. It organizes products, services, skills and community activities into accessible categories and subcategories.&lt;br&gt;
The current demo explores areas including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;local food and independent producers;&lt;/li&gt;
&lt;li&gt;kefir and fermented products;&lt;/li&gt;
&lt;li&gt;underground music and alternative culture;&lt;/li&gt;
&lt;li&gt;sound-system equipment;&lt;/li&gt;
&lt;li&gt;event and creative services;&lt;/li&gt;
&lt;li&gt;university and educational assistance;&lt;/li&gt;
&lt;li&gt;programming and digital services;&lt;/li&gt;
&lt;li&gt;repair and reuse;&lt;/li&gt;
&lt;li&gt;recycling and material recovery;&lt;/li&gt;
&lt;li&gt;sustainable everyday products.&lt;br&gt;
Explore the Marketplace:&lt;br&gt;
🛒 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=marketplace_overview&quot;&gt;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=marketplace_overview&lt;/a&gt;&lt;br&gt;
Why Kefir Is Part of the Ecosystem&lt;br&gt;
Kefir is a useful example of how a small local product can become part of a larger circular process.&lt;br&gt;
A visitor can discover a producer, learn about the production process, contact the seller and understand what happens to the packaging after consumption.&lt;br&gt;
Local production&lt;br&gt;
  ↓&lt;br&gt;
Marketplace discovery&lt;br&gt;
  ↓&lt;br&gt;
Informed purchase&lt;br&gt;
  ↓&lt;br&gt;
Consumption&lt;br&gt;
  ↓&lt;br&gt;
Container reuse&lt;br&gt;
  ↓&lt;br&gt;
Recycling or material recovery&lt;br&gt;
MyZubster does not automatically certify food safety, production standards or health benefits. Those claims require evidence and compliance from the responsible producer.&lt;br&gt;
The platform’s role is to make sellers, information and provenance easier to discover and inspect.&lt;br&gt;
Open the local-products Marketplace funnel:&lt;br&gt;
🌱 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?category=food&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=kefir_local_producers&quot;&gt;https://www.myzubster.com/marketplace?category=food&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=kefir_local_producers&lt;/a&gt;&lt;br&gt;
Supporting Underground and Independent Culture&lt;br&gt;
Underground communities often depend on informal networks connecting musicians, artists, technicians, venues and equipment owners.&lt;br&gt;
MyZubster can provide optional infrastructure for discovering:&lt;/li&gt;
&lt;li&gt;DJs, musicians and independent performers;&lt;/li&gt;
&lt;li&gt;sound-system equipment;&lt;/li&gt;
&lt;li&gt;audio repair specialists;&lt;/li&gt;
&lt;li&gt;rehearsal and event services;&lt;/li&gt;
&lt;li&gt;visual artists and graphic designers;&lt;/li&gt;
&lt;li&gt;alternative clothing and records;&lt;/li&gt;
&lt;li&gt;independent venues and cultural initiatives;&lt;/li&gt;
&lt;li&gt;reusable creative materials.&lt;br&gt;
A sound system can move through a complete circular lifecycle:&lt;br&gt;
Equipment discovery&lt;br&gt;
  ↓&lt;br&gt;
Purchase or rental&lt;br&gt;
  ↓&lt;br&gt;
Event use&lt;br&gt;
  ↓&lt;br&gt;
Maintenance&lt;br&gt;
  ↓&lt;br&gt;
Repair&lt;br&gt;
  ↓&lt;br&gt;
Resale and reuse&lt;br&gt;
  ↓&lt;br&gt;
Component recovery&lt;br&gt;
The objective is not to control underground culture. It is to give independent communities tools they can use on their own terms.&lt;br&gt;
Explore the underground and sound-system funnel:&lt;br&gt;
🔊 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?category=sound-system&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=underground_sound_system&quot;&gt;https://www.myzubster.com/marketplace?category=sound-system&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=underground_sound_system&lt;/a&gt;&lt;br&gt;
University and Educational Assistance&lt;br&gt;
Education is another important part of the MyZubster cycle.&lt;br&gt;
Students can discover legitimate support such as:&lt;/li&gt;
&lt;li&gt;tutoring;&lt;/li&gt;
&lt;li&gt;programming guidance;&lt;/li&gt;
&lt;li&gt;language practice;&lt;/li&gt;
&lt;li&gt;research-method explanations;&lt;/li&gt;
&lt;li&gt;document and presentation formatting;&lt;/li&gt;
&lt;li&gt;portfolio support;&lt;/li&gt;
&lt;li&gt;study groups;&lt;/li&gt;
&lt;li&gt;guidance toward internships;&lt;/li&gt;
&lt;li&gt;open-source contribution opportunities.&lt;br&gt;
Educational support should help students learn. It must not be used to impersonate students, complete prohibited examinations or submit deceptive academic work.&lt;br&gt;
The educational cycle is:&lt;br&gt;
Ask for support&lt;br&gt;
  ↓&lt;br&gt;
Learn&lt;br&gt;
  ↓&lt;br&gt;
Practise&lt;br&gt;
  ↓&lt;br&gt;
Build a project&lt;br&gt;
  ↓&lt;br&gt;
Document the work&lt;br&gt;
  ↓&lt;br&gt;
Contribute&lt;br&gt;
  ↓&lt;br&gt;
Help another learner&lt;br&gt;
Explore the educational Marketplace funnel:&lt;br&gt;
🎓 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?category=education&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=university_help&quot;&gt;https://www.myzubster.com/marketplace?category=education&amp;amp;utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=university_help&lt;/a&gt;&lt;br&gt;
Entering the MyZubster Metaverse&lt;br&gt;
The MyZubster Metaverse is the visual and social navigation layer of the ecosystem.&lt;br&gt;
Its current environment, Neon Plaza, allows visitors to:&lt;/li&gt;
&lt;li&gt;enter as guests or authenticated users;&lt;/li&gt;
&lt;li&gt;use account-linked characters;&lt;/li&gt;
&lt;li&gt;move around a shared environment;&lt;/li&gt;
&lt;li&gt;see other active visitors;&lt;/li&gt;
&lt;li&gt;communicate through chat and emotes;&lt;/li&gt;
&lt;li&gt;discover nearby participants;&lt;/li&gt;
&lt;li&gt;visit ecosystem portals;&lt;/li&gt;
&lt;li&gt;complete an exploration mission;&lt;/li&gt;
&lt;li&gt;preserve visited-zone progress;&lt;/li&gt;
&lt;li&gt;discover experimental virtual rooms.&lt;br&gt;
Enter Neon Plaza:&lt;br&gt;
🪐 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=metaverse_entry&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=metaverse_entry&lt;/a&gt;&lt;br&gt;
Account-Linked Characters&lt;br&gt;
A visitor can explore without creating a verified identity claim.&lt;br&gt;
Authenticated users can use persistent account-linked characters. The server determines which character belongs to the authenticated account instead of trusting a name supplied by the browser.&lt;br&gt;
The current system includes:&lt;/li&gt;
&lt;li&gt;canonical server-side character profiles;&lt;/li&gt;
&lt;li&gt;account-linked character ownership;&lt;/li&gt;
&lt;li&gt;authenticated profile retrieval;&lt;/li&gt;
&lt;li&gt;server-backed mission progress;&lt;/li&gt;
&lt;li&gt;visited-zone persistence;&lt;/li&gt;
&lt;li&gt;live player presence;&lt;/li&gt;
&lt;li&gt;session recovery;&lt;/li&gt;
&lt;li&gt;expired-JWT handling;&lt;/li&gt;
&lt;li&gt;protected character-progress updates.&lt;br&gt;
A display name is not considered legal identity evidence. The MYZ VERIFIED label indicates that the character is linked to a MyZubster account, not that a person’s legal identity, professional skills or qualifications have been certified.&lt;br&gt;
Mission Progress&lt;br&gt;
Visitors receive an initial mission: move through Neon Plaza and reach one of its portals.&lt;br&gt;
For guests, progress remains local to the browser. For authenticated characters, visited zones can be stored on the account-linked server profile.&lt;br&gt;
The server accepts only known landmark identifiers. It derives character ownership from the verified authentication token and does not trust a character name submitted by the client.&lt;br&gt;
This creates a safer progression model:&lt;br&gt;
Authenticated account&lt;br&gt;
  ↓&lt;br&gt;
Canonical character&lt;br&gt;
  ↓&lt;br&gt;
Visit a valid landmark&lt;br&gt;
  ↓&lt;br&gt;
Server validates the landmark&lt;br&gt;
  ↓&lt;br&gt;
Progress is attached to the account-owned character&lt;br&gt;
Try the mission funnel:&lt;br&gt;
🧭 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=first_mission&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=first_mission&lt;/a&gt;&lt;br&gt;
Experimental Virtual Rooms&lt;br&gt;
MyZubster is beginning to connect Neon Plaza with persistent virtual rooms.&lt;br&gt;
The discovery system applies access rules on the server:&lt;/li&gt;
&lt;li&gt;guests can discover public rooms;&lt;/li&gt;
&lt;li&gt;authenticated users can also discover account-only rooms;&lt;/li&gt;
&lt;li&gt;private rooms remain hidden;&lt;/li&gt;
&lt;li&gt;drafts and archived rooms are excluded;&lt;/li&gt;
&lt;li&gt;only published, scheduled or live spaces are discoverable.&lt;br&gt;
These rooms are still experimental. A dedicated room experience will be introduced only after navigation, access control, moderation and lifecycle handling are ready.&lt;br&gt;
Follow the virtual-room funnel:&lt;br&gt;
🏛️ &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=virtual_rooms&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=virtual_rooms&lt;/a&gt;&lt;br&gt;
MyZubster Visual&lt;br&gt;
MyZubster Visual provides the storytelling layer.&lt;br&gt;
Illustrations, interactive popups and visual narratives can explain connections between:&lt;/li&gt;
&lt;li&gt;physical products;&lt;/li&gt;
&lt;li&gt;circular lifecycles;&lt;/li&gt;
&lt;li&gt;environmental projects;&lt;/li&gt;
&lt;li&gt;characters;&lt;/li&gt;
&lt;li&gt;community contributions;&lt;/li&gt;
&lt;li&gt;Marketplace categories;&lt;/li&gt;
&lt;li&gt;Metaverse destinations.&lt;br&gt;
A popup can introduce a story, provide additional context and direct a visitor toward the next relevant part of the ecosystem.&lt;br&gt;
The intended funnel is:&lt;br&gt;
Visual story&lt;br&gt;
  ↓&lt;br&gt;
Interactive popup&lt;br&gt;
  ↓&lt;br&gt;
Context and explanation&lt;br&gt;
  ↓&lt;br&gt;
Marketplace category or project&lt;br&gt;
  ↓&lt;br&gt;
Metaverse exploration&lt;br&gt;
  ↓&lt;br&gt;
Community participation&lt;br&gt;
Explore the visual-story funnel:&lt;br&gt;
🎨 &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/fumetto?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=visual_popups&quot;&gt;https://www.myzubster.com/fumetto?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=visual_popups&lt;/a&gt;&lt;br&gt;
How the Complete Circular Funnel Works&lt;br&gt;
Consider a visitor interested in locally produced kefir:&lt;ol&gt;
&lt;li&gt;They discover MyZubster through this article.&lt;/li&gt;
&lt;li&gt;They open the Marketplace.&lt;/li&gt;
&lt;li&gt;They explore local food and producer listings.&lt;/li&gt;
&lt;li&gt;They learn about the product and its provenance.&lt;/li&gt;
&lt;li&gt;They contact or purchase from an authorized seller.&lt;/li&gt;
&lt;li&gt;They reuse or correctly recycle the packaging.&lt;/li&gt;
&lt;li&gt;They enter the Metaverse.&lt;/li&gt;
&lt;li&gt;They visit the Marketplace or LIFE Projects portal.&lt;/li&gt;
&lt;li&gt;They document or share a useful contribution.&lt;/li&gt;
&lt;li&gt;That contribution helps another visitor discover the circular pathway.&lt;br&gt;
The same model can apply to underground sound equipment:&lt;/li&gt;
&lt;li&gt;Discover equipment.&lt;/li&gt;
&lt;li&gt;Use it for an event.&lt;/li&gt;
&lt;li&gt;Maintain and repair it.&lt;/li&gt;
&lt;li&gt;Resell or reuse it.&lt;/li&gt;
&lt;li&gt;Recover components at the end of its usable life.&lt;/li&gt;
&lt;li&gt;Share repair knowledge with the community.&lt;br&gt;
It can also apply to educational support:&lt;/li&gt;
&lt;li&gt;Request tutoring.&lt;/li&gt;
&lt;li&gt;Learn a skill.&lt;/li&gt;
&lt;li&gt;Build a project.&lt;/li&gt;
&lt;li&gt;Publish the code.&lt;/li&gt;
&lt;li&gt;Contribute to MyZubster.&lt;/li&gt;
&lt;li&gt;Help another learner.&lt;br&gt;
Technical Architecture&lt;br&gt;
The current implementation combines:&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;React for the user interface;&lt;/li&gt;
&lt;li&gt;Node.js and Express for backend services;&lt;/li&gt;
&lt;li&gt;MongoDB for persistent characters, progress and room records;&lt;/li&gt;
&lt;li&gt;authenticated API routes;&lt;/li&gt;
&lt;li&gt;server-authoritative access rules;&lt;/li&gt;
&lt;li&gt;short-lived presence and chat records;&lt;/li&gt;
&lt;li&gt;GitHub for open-source development;&lt;/li&gt;
&lt;li&gt;Vercel for deployment and web analytics.&lt;br&gt;
The architecture maintains an important boundary:&lt;br&gt;
The client presents the experience, but the server controls identity, ownership, persistence and access decisions.&lt;br&gt;
Measuring the Funnel&lt;br&gt;
Each link in this article contains UTM parameters designed to distinguish traffic from Coder Legion.&lt;br&gt;
The campaign uses:&lt;br&gt;
utm_source=coderlegion&lt;br&gt;
utm_medium=article&lt;br&gt;
utm_campaign=myzubster_circular_funnel&lt;br&gt;
The utm_content value identifies the selected journey:&lt;/li&gt;
&lt;li&gt;marketplace_overview&lt;/li&gt;
&lt;li&gt;kefir_local_producers&lt;/li&gt;
&lt;li&gt;underground_sound_system&lt;/li&gt;
&lt;li&gt;university_help&lt;/li&gt;
&lt;li&gt;metaverse_entry&lt;/li&gt;
&lt;li&gt;first_mission&lt;/li&gt;
&lt;li&gt;virtual_rooms&lt;/li&gt;
&lt;li&gt;visual_popups&lt;/li&gt;
&lt;li&gt;github_repository&lt;br&gt;
This makes it possible to compare which concepts attract attention and which destinations visitors choose next.&lt;br&gt;
Build With Us&lt;br&gt;
MyZubster is being developed openly. Developers can inspect the implementation, review the architecture, propose improvements and contribute code.&lt;br&gt;
💻 &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=github_repository&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=github_repository&lt;/a&gt;&lt;br&gt;
The project remains an evolving prototype. Experimental functionality, verified evidence and operational services are kept clearly distinguishable.&lt;br&gt;
The objective is not simply to create another marketplace or virtual environment. It is to build a connected system in which software helps communities discover opportunities, learn, exchange value, extend product lifecycles and create new contributions.&lt;br&gt;
Explore the Ecosystem&lt;br&gt;
🛒 Marketplace Demo&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=marketplace_overview&quot;&gt;https://www.myzubster.com/marketplace?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=marketplace_overview&lt;/a&gt;&lt;br&gt;
🪐 MyZubster Metaverse&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=metaverse_entry&quot;&gt;https://www.myzubster.com/metaverse?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=metaverse_entry&lt;/a&gt;&lt;br&gt;
🎨 MyZubster Visual&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/fumetto?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=visual_popups&quot;&gt;https://www.myzubster.com/fumetto?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=visual_popups&lt;/a&gt;&lt;br&gt;
💻 Open-source Repository&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=github_repository&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster?utm_source=coderlegion&amp;amp;utm_medium=article&amp;amp;utm_campaign=myzubster_circular_funnel&amp;amp;utm_content=github_repository&lt;/a&gt;&lt;h2 id=&quot;myzubster-opensource-webdevelopment-metaverse-marketplace-circulareconomy-reactjs-nodejs-mongodb-buildinpublic&quot;&gt;MyZubster #OpenSource #WebDevelopment #Metaverse #Marketplace #CircularEconomy #ReactJS #NodeJS #MongoDB #BuildInPublic&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27164/building-myzubster-a-circular-marketplace-connected-to-a-social-metaverse</guid>
<pubDate>Mon, 14 Sep 2026 12:43:38 +0000</pubDate>
</item>
<item>
<title>Building MyZubster in Public: From Visual Storytelling to an Interactive Metaverse</title>
<link>https://coderlegion.com/27012/building-myzubster-in-public-from-visual-storytelling-to-an-interactive-metaverse</link>
<description>&lt;h2 id=&quot;building-myzubster-in-public-from-visual-storytelling-to-an-interactive-metaverse&quot;&gt;Building MyZubster in Public: From Visual Storytelling to an Interactive Metaverse&lt;/h2&gt;
&lt;p&gt;MyZubster has recently evolved from a collection of open-source repositories and visual concepts into a more connected, interactive, and measurable ecosystem.&lt;/p&gt;
&lt;p&gt;Our latest development cycle focused on five areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;visual content and videos;&lt;/li&gt;
&lt;li&gt;the MyZubster comic;&lt;/li&gt;
&lt;li&gt;the Darkode historical page;&lt;/li&gt;
&lt;li&gt;Neon Plaza and character onboarding;&lt;/li&gt;
&lt;li&gt;the collaboration with Nicola and his N4K48 character.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a technical overview of what we built, what is live, and what still remains experimental.&lt;/p&gt;
&lt;h3 id=&quot;visuals-as-part-of-the-product&quot;&gt;Visuals as part of the product&lt;/h3&gt;
&lt;p&gt;We created and organized new images, comic panels, and videos related to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MyZubster;&lt;/li&gt;
&lt;li&gt;Zorgax;&lt;/li&gt;
&lt;li&gt;Neon Plaza;&lt;/li&gt;
&lt;li&gt;the Space Station;&lt;/li&gt;
&lt;li&gt;circular economy;&lt;/li&gt;
&lt;li&gt;environmental pilot concepts;&lt;/li&gt;
&lt;li&gt;characters and community contributors;&lt;/li&gt;
&lt;li&gt;the cultural history represented by Darkode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These assets are not treated only as marketing material. They help us describe the ecosystem, explain future product directions, and connect technical components with a shared narrative.&lt;/p&gt;
&lt;p&gt;However, we maintain a strict distinction between:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;narrative representation;&lt;/li&gt;
&lt;li&gt;prototype;&lt;/li&gt;
&lt;li&gt;implemented feature;&lt;/li&gt;
&lt;li&gt;production deployment;&lt;/li&gt;
&lt;li&gt;verified result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A visual may describe a future interface or environment without implying that every depicted feature is already available.&lt;/p&gt;
&lt;h3 id=&quot;the-myzubster-comic&quot;&gt;The MyZubster comic&lt;/h3&gt;
&lt;p&gt;The comic has become one of the main narrative interfaces of the project.&lt;/p&gt;
&lt;p&gt;It connects characters, software components, environmental projects, digital culture, and MyZubster’s broader vision.&lt;/p&gt;
&lt;p&gt;The public comic gallery is available at:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/fumetto&quot;&gt;https://www.myzubster.com/fumetto&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The comic currently includes themes such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the city as a living organism;&lt;/li&gt;
&lt;li&gt;Zorgax as an ecosystem guide;&lt;/li&gt;
&lt;li&gt;Neon Plaza;&lt;/li&gt;
&lt;li&gt;the Space Station;&lt;/li&gt;
&lt;li&gt;community and bot networks;&lt;/li&gt;
&lt;li&gt;circular economy;&lt;/li&gt;
&lt;li&gt;digital identity;&lt;/li&gt;
&lt;li&gt;early online-community culture.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The comic is narrative content, not technical evidence. Claims about features, deployments, contributors, or results must still be supported by source code, commits, documentation, or other verifiable evidence.&lt;/p&gt;
&lt;h3 id=&quot;darkode-as-a-digital-memory-layer&quot;&gt;Darkode as a digital memory layer&lt;/h3&gt;
&lt;p&gt;We also created a public Darkode page:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/darkode&quot;&gt;https://www.myzubster.com/darkode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Darkode documents part of the cultural and personal history behind MyZubster.&lt;/p&gt;
&lt;p&gt;Instead of presenting every historical element as a verified fact, the page separates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;documented information;&lt;/li&gt;
&lt;li&gt;personal recollections;&lt;/li&gt;
&lt;li&gt;archived material;&lt;/li&gt;
&lt;li&gt;narrative interpretation;&lt;/li&gt;
&lt;li&gt;details still requiring verification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gives MyZubster a digital memory layer without turning incomplete evidence into definitive claims.&lt;/p&gt;
&lt;p&gt;The page has also been connected to the main website navigation, making it discoverable from the homepage.&lt;/p&gt;
&lt;h3 id=&quot;neon-plaza-guest-access-before-registration&quot;&gt;Neon Plaza: guest access before registration&lt;/h3&gt;
&lt;p&gt;A major problem with many Metaverse experiences is onboarding friction.&lt;/p&gt;
&lt;p&gt;Users are often asked to create an account, connect a wallet, or install software before they understand what the experience provides.&lt;/p&gt;
&lt;p&gt;We changed that flow.&lt;/p&gt;
&lt;p&gt;Neon Plaza is now accessible as a guest:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A visitor can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;select a public display name;&lt;/li&gt;
&lt;li&gt;automatically create a guest character;&lt;/li&gt;
&lt;li&gt;enter without registering;&lt;/li&gt;
&lt;li&gt;enter without connecting a wallet;&lt;/li&gt;
&lt;li&gt;use the experience without a VR headset;&lt;/li&gt;
&lt;li&gt;move with the arrow keys or WASD;&lt;/li&gt;
&lt;li&gt;use chat and emotes;&lt;/li&gt;
&lt;li&gt;encounter other active characters;&lt;/li&gt;
&lt;li&gt;reach portals connected to MyZubster services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The homepage now uses a more direct call to action:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Enter Neon Plaza — try it without registering&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The goal is to let users experience the product before asking them to create an account.&lt;/p&gt;
&lt;h3 id=&quot;introducing-a-first-mission&quot;&gt;Introducing a first mission&lt;/h3&gt;
&lt;p&gt;A digital world without an immediate objective can feel empty, even when several features are available.&lt;/p&gt;
&lt;p&gt;We therefore added a simple onboarding mission:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Move your character and reach one of Neon Plaza’s glowing portals.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This provides an immediate interaction and helps users understand how the environment works.&lt;/p&gt;
&lt;p&gt;The current journey is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;visit the homepage;&lt;/li&gt;
&lt;li&gt;enter Neon Plaza as a guest;&lt;/li&gt;
&lt;li&gt;create a character;&lt;/li&gt;
&lt;li&gt;start the first mission;&lt;/li&gt;
&lt;li&gt;reach a portal;&lt;/li&gt;
&lt;li&gt;complete the mission;&lt;/li&gt;
&lt;li&gt;receive an invitation to verify the character;&lt;/li&gt;
&lt;li&gt;register to preserve progress.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first mission converts passive traffic into a measurable product interaction.&lt;/p&gt;
&lt;h3 id=&quot;character-verification&quot;&gt;Character verification&lt;/h3&gt;
&lt;p&gt;After completing the mission, guest users see a new action:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Verify your character&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In MyZubster, a verified character is a character connected to a recognized account.&lt;/p&gt;
&lt;p&gt;This does not mean:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;legally verified identity;&lt;/li&gt;
&lt;li&gt;certified professional skills;&lt;/li&gt;
&lt;li&gt;automatic rewards;&lt;/li&gt;
&lt;li&gt;ownership of third-party materials;&lt;/li&gt;
&lt;li&gt;authorization to publish personal information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Additional public information requires separate consent.&lt;/p&gt;
&lt;p&gt;An account-linked character can provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;persistent progress;&lt;/li&gt;
&lt;li&gt;a reusable public character name;&lt;/li&gt;
&lt;li&gt;personal missions;&lt;/li&gt;
&lt;li&gt;links to authorized contributions;&lt;/li&gt;
&lt;li&gt;recognizable participation in the ecosystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach allows us to increase trust without overstating what technical account verification proves.&lt;/p&gt;
&lt;h3 id=&quot;nicola-and-n4k48&quot;&gt;Nicola and N4K48&lt;/h3&gt;
&lt;p&gt;One of our current experiments involves Nicola and his character, N4K48.&lt;/p&gt;
&lt;p&gt;Using AI-assisted creative tools, Nicola produced three new comic panels:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;“From a Software Idea to the Metaverse”;&lt;/li&gt;
&lt;li&gt;“The Software Takes Shape”;&lt;/li&gt;
&lt;li&gt;“Towards Neon Plaza.”&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The panels describe his journey from a software idea to a possible presence inside the MyZubster Metaverse.&lt;/p&gt;
&lt;p&gt;They are available in Nicola’s public repository:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/tree/main/docs/n4k48-comics&quot;&gt;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/tree/main/docs/n4k48-comics&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The panels have been connected to his N4K48 profile and project documentation.&lt;/p&gt;
&lt;p&gt;Previously existing MyZubster comics remain external references. They are not attributed to Nicola.&lt;/p&gt;
&lt;p&gt;This distinction helps keep authorship, provenance, and project context separate.&lt;/p&gt;
&lt;h3 id=&quot;preparing-an-nft-candidate-without-pretending-it-has-been-minted&quot;&gt;Preparing an NFT candidate without pretending it has been minted&lt;/h3&gt;
&lt;p&gt;Nicola proposed the first panel, “From a Software Idea to the Metaverse,” as a potential NFT candidate.&lt;/p&gt;
&lt;p&gt;No mint has been executed.&lt;/p&gt;
&lt;p&gt;At the moment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no blockchain has been selected;&lt;/li&gt;
&lt;li&gt;no wallet has been registered for the operation;&lt;/li&gt;
&lt;li&gt;no smart contract has been selected or deployed;&lt;/li&gt;
&lt;li&gt;no token ID exists;&lt;/li&gt;
&lt;li&gt;no transaction hash exists.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of immediately minting the image, we created a preliminary provenance and rights-review document.&lt;/p&gt;
&lt;p&gt;The draft pull request is available here:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/pull/14&quot;&gt;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/pull/14&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The review process covers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;authorship confirmation;&lt;/li&gt;
&lt;li&gt;the AI tool and creative process used;&lt;/li&gt;
&lt;li&gt;the original source file;&lt;/li&gt;
&lt;li&gt;manual modifications;&lt;/li&gt;
&lt;li&gt;third-party assets and fonts;&lt;/li&gt;
&lt;li&gt;applicable licenses;&lt;/li&gt;
&lt;li&gt;authorization to use MyZubster elements;&lt;/li&gt;
&lt;li&gt;commercial terms and royalties;&lt;/li&gt;
&lt;li&gt;Nicola’s explicit final authorization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current status is:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Ready for rights review — not ready to mint.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This evidence-first approach prevents documentation from presenting a planned blockchain operation as an already completed result.&lt;/p&gt;
&lt;h3 id=&quot;measuring-the-conversion-funnel&quot;&gt;Measuring the conversion funnel&lt;/h3&gt;
&lt;p&gt;We also introduced product analytics for the new user journey.&lt;/p&gt;
&lt;p&gt;Facebook is currently an important discovery source, so we are measuring this funnel:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Facebook → homepage → Neon Plaza → mission → character verification → registration&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The events include:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;metaverse_cta_clicked
metaverse_loaded
first_interaction
mission_started
mission_completed
character_verification_started
character_verification_completed
signup_start
signup_completed
contact_request
pilot_interest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These events let us distinguish between visitors who:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only view the homepage;&lt;/li&gt;
&lt;li&gt;open Neon Plaza;&lt;/li&gt;
&lt;li&gt;interact with the experience;&lt;/li&gt;
&lt;li&gt;begin a mission;&lt;/li&gt;
&lt;li&gt;complete a mission;&lt;/li&gt;
&lt;li&gt;begin character verification;&lt;/li&gt;
&lt;li&gt;complete registration;&lt;/li&gt;
&lt;li&gt;express interest in a pilot;&lt;/li&gt;
&lt;li&gt;request contact.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Traffic alone does not tell us whether the product is producing meaningful engagement.&lt;/p&gt;
&lt;p&gt;The objective is to identify where users abandon the journey and improve each transition independently.&lt;/p&gt;
&lt;h3 id=&quot;what-we-learned&quot;&gt;What we learned&lt;/h3&gt;
&lt;p&gt;The main lesson from this iteration is that adding more features does not automatically create a stronger ecosystem.&lt;/p&gt;
&lt;p&gt;The different layers need to reinforce one another:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;videos generate discovery;&lt;/li&gt;
&lt;li&gt;comics provide narrative context;&lt;/li&gt;
&lt;li&gt;Darkode preserves cultural memory;&lt;/li&gt;
&lt;li&gt;Neon Plaza creates an interactive experience;&lt;/li&gt;
&lt;li&gt;Zorgax guides the user;&lt;/li&gt;
&lt;li&gt;missions provide immediate objectives;&lt;/li&gt;
&lt;li&gt;character verification supports continuity;&lt;/li&gt;
&lt;li&gt;analytics measures actual behavior;&lt;/li&gt;
&lt;li&gt;documentation protects provenance and accuracy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The collaboration with Nicola and N4K48 also demonstrates the importance of working with real contributors while keeping authorship, consent, implementation status, and evidence clearly separated.&lt;/p&gt;
&lt;h3 id=&quot;next-steps&quot;&gt;Next steps&lt;/h3&gt;
&lt;p&gt;Our next priorities are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;complete the provenance and rights review for the N4K48 NFT candidate;&lt;/li&gt;
&lt;li&gt;improve character onboarding;&lt;/li&gt;
&lt;li&gt;reduce abandonment between mission completion and registration;&lt;/li&gt;
&lt;li&gt;make active characters and missions more visible;&lt;/li&gt;
&lt;li&gt;connect the comic, Metaverse, Marketplace, and environmental pilots;&lt;/li&gt;
&lt;li&gt;use analytics to validate changes;&lt;/li&gt;
&lt;li&gt;publish only results supported by evidence.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MyZubster remains an open-source ecosystem built in public.&lt;/p&gt;
&lt;p&gt;The goal is not to present a future vision as a finished product. The goal is to document each experiment, verify each result, and progressively transform ideas, visits, and community contributions into usable technology.&lt;/p&gt;
&lt;h3 id=&quot;project-links&quot;&gt;Project links&lt;/h3&gt;
&lt;p&gt;MyZubster:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com&quot;&gt;https://www.myzubster.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neon Plaza:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Darkode:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/darkode&quot;&gt;https://www.myzubster.com/darkode&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Comic:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/fumetto&quot;&gt;https://www.myzubster.com/fumetto&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;N4K48 comic gallery:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/tree/main/docs/n4k48-comics&quot;&gt;https://github.com/nicolaususnicola-lgtm/myzubster-mvp/tree/main/docs/n4k48-comics&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27012/building-myzubster-in-public-from-visual-storytelling-to-an-interactive-metaverse</guid>
<pubDate>Sun, 13 Sep 2026 00:23:59 +0000</pubDate>
</item>
<item>
<title>Building the Realtime Foundation of the MyZubster Metaverse</title>
<link>https://coderlegion.com/26533/building-the-realtime-foundation-of-the-myzubster-metaverse</link>
<description>&lt;h2 id=&quot;building-the-realtime-foundation-of-the-myzubster-metaverse&quot;&gt;Building the Realtime Foundation of the MyZubster Metaverse&lt;/h2&gt;
&lt;p&gt;We are upgrading the MyZubster Metaverse from a REST-synchronized experience into an authenticated realtime multiplayer environment.&lt;/p&gt;
&lt;p&gt;Before continuing with the next development phase, here is a transparent update on what is already working and what we are implementing next.&lt;/p&gt;
&lt;h3 id=&quot;from-polling-to-realtime-communication&quot;&gt;From polling to realtime communication&lt;/h3&gt;
&lt;p&gt;The first version of the Metaverse uses REST endpoints to manage:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;player sessions;&lt;/li&gt;
&lt;li&gt;character movement;&lt;/li&gt;
&lt;li&gt;shared presence;&lt;/li&gt;
&lt;li&gt;chat messages;&lt;/li&gt;
&lt;li&gt;emotes;&lt;/li&gt;
&lt;li&gt;verified identities;&lt;/li&gt;
&lt;li&gt;world synchronization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gave us a reliable starting point, but periodic polling is not the final architecture we want for a persistent shared world.&lt;/p&gt;
&lt;p&gt;We have now introduced a Socket.IO gateway mounted at:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;/realtime
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It supports WebSocket communication with HTTP polling available as a compatibility fallback.&lt;/p&gt;
&lt;h3 id=&quot;the-preview-runtime-is-online&quot;&gt;The preview runtime is online&lt;/h3&gt;
&lt;p&gt;The realtime infrastructure has been deployed to an isolated Vercel preview environment.&lt;/p&gt;
&lt;p&gt;We verified it using the public health endpoint:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;GET /api/realtime/health
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The current response is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;success&quot;: true,
  &quot;status&quot;: &quot;ok&quot;,
  &quot;transport&quot;: &quot;socket.io&quot;,
  &quot;socketPath&quot;: &quot;/realtime&quot;,
  &quot;presence&quot;: &quot;local-fallback&quot;,
  &quot;privacy&quot;: &quot;aggregate-only&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This confirms that the application is running, Socket.IO is attached correctly, the preview database is reachable, and observability is configured to avoid exposing private user data.&lt;/p&gt;
&lt;h3 id=&quot;secure-realtime-authentication&quot;&gt;Secure realtime authentication&lt;/h3&gt;
&lt;p&gt;Clients cannot connect anonymously to protected realtime features.&lt;/p&gt;
&lt;p&gt;An authenticated user first requests a short-lived token from:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;POST /api/realtime/token
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The server creates a dedicated JWT containing only the information required by the realtime gateway.&lt;/p&gt;
&lt;p&gt;The gateway verifies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;signature and expiration;&lt;/li&gt;
&lt;li&gt;issuer and audience;&lt;/li&gt;
&lt;li&gt;realtime-specific purpose;&lt;/li&gt;
&lt;li&gt;user identity;&lt;/li&gt;
&lt;li&gt;user role.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Authentication alone does not grant access to every channel. Each subscription is authorized independently by the server.&lt;/p&gt;
&lt;p&gt;Every user also receives a private channel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;user:&amp;lt;userId&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This provides a controlled foundation for private notifications and direct message delivery.&lt;/p&gt;
&lt;h3 id=&quot;presence-messaging-and-reconnects&quot;&gt;Presence, messaging, and reconnects&lt;/h3&gt;
&lt;p&gt;The new gateway already supports the core operations required by a multiplayer environment:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;presence.join
presence.heartbeat
presence.leave
channel.subscribe
channel.unsubscribe
chat.send
realtime.resume
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a client reconnects, it can request restoration of its previous subscriptions. The server verifies every channel again before restoring access.&lt;/p&gt;
&lt;p&gt;Messages are validated, persisted, deduplicated, and delivered only to authorized recipients.&lt;/p&gt;
&lt;p&gt;We also added backpressure controls so the service can reject excess work safely during temporary overload.&lt;/p&gt;
&lt;h3 id=&quot;preview-database-isolation&quot;&gt;Preview database isolation&lt;/h3&gt;
&lt;p&gt;The preview deployment does not reuse unrestricted production credentials.&lt;/p&gt;
&lt;p&gt;We created:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a dedicated MongoDB preview user;&lt;/li&gt;
&lt;li&gt;a custom least-privilege role;&lt;/li&gt;
&lt;li&gt;access limited to the preview database;&lt;/li&gt;
&lt;li&gt;cluster-level restrictions;&lt;/li&gt;
&lt;li&gt;encrypted Vercel environment variables;&lt;/li&gt;
&lt;li&gt;branch-specific configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The MongoDB URI and realtime signing secret are never committed to GitHub or exposed to frontend code.&lt;/p&gt;
&lt;h3 id=&quot;privacy-aware-observability&quot;&gt;Privacy-aware observability&lt;/h3&gt;
&lt;p&gt;Realtime systems need monitoring, but operational visibility should not become user surveillance.&lt;/p&gt;
&lt;p&gt;Our observability layer collects aggregate technical information such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connection attempts;&lt;/li&gt;
&lt;li&gt;successful and rejected connections;&lt;/li&gt;
&lt;li&gt;active connections;&lt;/li&gt;
&lt;li&gt;disconnects;&lt;/li&gt;
&lt;li&gt;message failures;&lt;/li&gt;
&lt;li&gt;duplicate messages;&lt;/li&gt;
&lt;li&gt;resume operations;&lt;/li&gt;
&lt;li&gt;processing duration;&lt;/li&gt;
&lt;li&gt;Redis failures.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Private conversations and raw personal identifiers are not included in public metrics.&lt;/p&gt;
&lt;p&gt;The detailed metrics endpoint is restricted to authenticated administrators.&lt;/p&gt;
&lt;h3 id=&quot;why-presence-is-still-using-a-fallback&quot;&gt;Why presence is still using a fallback&lt;/h3&gt;
&lt;p&gt;The health response currently reports:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;presence: local-fallback
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means presence works inside the active application instance, but it is not yet coordinated across multiple Vercel instances.&lt;/p&gt;
&lt;p&gt;It is an important distinction: the realtime runtime is operational, but distributed presence is still the next step.&lt;/p&gt;
&lt;p&gt;Redis will provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;shared presence state;&lt;/li&gt;
&lt;li&gt;cross-instance Socket.IO delivery;&lt;/li&gt;
&lt;li&gt;instance coordination;&lt;/li&gt;
&lt;li&gt;presence expiration;&lt;/li&gt;
&lt;li&gt;better horizontal scaling.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-we-are-working-on-next&quot;&gt;What we are working on next&lt;/h3&gt;
&lt;p&gt;Our next development phase is focused on:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;connecting the Metaverse frontend to Socket.IO;&lt;/li&gt;
&lt;li&gt;keeping REST synchronization as a temporary fallback;&lt;/li&gt;
&lt;li&gt;introducing the Socket.IO Redis adapter;&lt;/li&gt;
&lt;li&gt;configuring an isolated preview Redis instance;&lt;/li&gt;
&lt;li&gt;testing multiple simultaneous clients;&lt;/li&gt;
&lt;li&gt;verifying disconnect and resume behavior;&lt;/li&gt;
&lt;li&gt;validating privacy-safe metrics;&lt;/li&gt;
&lt;li&gt;completing the production review and merge.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;current-project-status&quot;&gt;Current project status&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Realtime server: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Vercel preview: &lt;strong&gt;online&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;MongoDB connection: &lt;strong&gt;verified&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Health endpoint: &lt;strong&gt;verified&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Socket authentication: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Channel authorization: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Presence lifecycle: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Reconnect support: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Aggregate observability: &lt;strong&gt;implemented&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Frontend Socket.IO connection: &lt;strong&gt;in progress&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Distributed Redis coordination: &lt;strong&gt;next&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Production release: &lt;strong&gt;pending validation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;building-a-world-not-just-a-page&quot;&gt;Building a world, not just a page&lt;/h3&gt;
&lt;p&gt;The MyZubster Metaverse is intended to become a shared digital space connected to identities, creators, projects, collaboration, and community experiences.&lt;/p&gt;
&lt;p&gt;Making that possible requires more than adding a WebSocket. It requires strong security boundaries, failure handling, database isolation, reconnect logic, privacy-aware monitoring, and distributed state management.&lt;/p&gt;
&lt;p&gt;The server-side foundation is now online.&lt;/p&gt;
&lt;p&gt;The next step is connecting the world to it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;MyZubster: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com&quot;&gt;https://www.myzubster.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem&quot;&gt;https://github.com/MyZubster-Ecosystem&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26533/building-the-realtime-foundation-of-the-myzubster-metaverse</guid>
<pubDate>Wed, 09 Sep 2026 00:12:26 +0000</pubDate>
</item>
<item>
<title>The MyZubster Metaverse has reached a new technical milestone.</title>
<link>https://coderlegion.com/26509/the-myzubster-metaverse-has-reached-a-new-technical-milestone</link>
<description>&lt;p&gt;The MyZubster Metaverse has reached a new technical milestone.&lt;/p&gt;
&lt;p&gt;We have merged a major realtime observability and reliability update into the main MyZubster repository.&lt;/p&gt;
&lt;p&gt;Pull Request:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster/pull/1042&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster/pull/1042&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Merged commit:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster/commit/57fa5be2c315cb9bf55bd306969291ea10ccf766&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster/commit/57fa5be2c315cb9bf55bd306969291ea10ccf766&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-we-implemented&quot;&gt;What we implemented&lt;/h3&gt;
&lt;p&gt;The new system introduces privacy-safe monitoring for the Socket.IO realtime gateway.&lt;/p&gt;
&lt;p&gt;It can measure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;active connections;&lt;/li&gt;
&lt;li&gt;connection and resume attempts;&lt;/li&gt;
&lt;li&gt;delivered and failed messages;&lt;/li&gt;
&lt;li&gt;notification delivery;&lt;/li&gt;
&lt;li&gt;Redis failures;&lt;/li&gt;
&lt;li&gt;queued operations;&lt;/li&gt;
&lt;li&gt;backpressure rejections;&lt;/li&gt;
&lt;li&gt;operation latency percentiles;&lt;/li&gt;
&lt;li&gt;SLO evaluations and alert candidates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The telemetry does not include message content, authentication tokens, private keys, or raw user identifiers.&lt;/p&gt;
&lt;h3 id=&quot;controlled-backpressure&quot;&gt;Controlled backpressure&lt;/h3&gt;
&lt;p&gt;Realtime systems can become unstable when they receive more work than they can process.&lt;/p&gt;
&lt;p&gt;We added a bounded operation queue around critical Socket.IO operations.&lt;/p&gt;
&lt;p&gt;When the system is temporarily busy, an operation can wait in the queue. If the configured capacity is reached, the client receives a retryable error instead of allowing unlimited memory consumption.&lt;/p&gt;
&lt;p&gt;This gives us safer behavior during traffic bursts and measurable capacity limits.&lt;/p&gt;
&lt;h3 id=&quot;durable-messaging&quot;&gt;Durable messaging&lt;/h3&gt;
&lt;p&gt;Messages and notifications are now stored before realtime delivery is attempted.&lt;/p&gt;
&lt;p&gt;The new sequence is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Validate the operation.&lt;/li&gt;
&lt;li&gt;Save the message or notification.&lt;/li&gt;
&lt;li&gt;Attempt Socket.IO delivery.&lt;/li&gt;
&lt;li&gt;Record the delivery result.&lt;/li&gt;
&lt;li&gt;Allow clients to recover stored information later.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A temporary socket or notification failure therefore does not destroy a message that was already saved successfully.&lt;/p&gt;
&lt;h3 id=&quot;redis-recovery&quot;&gt;Redis recovery&lt;/h3&gt;
&lt;p&gt;Redis supports distributed presence when multiple realtime workers are running.&lt;/p&gt;
&lt;p&gt;The presence layer now records Redis connection failures and can temporarily degrade to local in-memory presence.&lt;/p&gt;
&lt;p&gt;This fallback keeps a single worker usable, while metrics clearly identify that distributed presence is unavailable.&lt;/p&gt;
&lt;p&gt;Failed Redis clients are also invalidated so that future operations can reconnect.&lt;/p&gt;
&lt;h3 id=&quot;administrative-metrics&quot;&gt;Administrative metrics&lt;/h3&gt;
&lt;p&gt;We added an administrator-only endpoint:&lt;/p&gt;
&lt;p&gt;GET /api/realtime/metrics&lt;/p&gt;
&lt;p&gt;It provides aggregate metrics, latency information, SLO evaluations, and alert candidates.&lt;/p&gt;
&lt;p&gt;The response is protected by authentication and uses &lt;code&gt;Cache-Control: no-store&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;/h3&gt;
&lt;p&gt;The implementation includes tests covering:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;observability counters and latency;&lt;/li&gt;
&lt;li&gt;Redis degradation;&lt;/li&gt;
&lt;li&gt;notification durability;&lt;/li&gt;
&lt;li&gt;chat delivery failures;&lt;/li&gt;
&lt;li&gt;administrator authorization;&lt;/li&gt;
&lt;li&gt;connection bursts;&lt;/li&gt;
&lt;li&gt;message bursts and backpressure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also created two operational commands:&lt;/p&gt;
&lt;p&gt;npm run metaverse:realtime-self-check&lt;/p&gt;
&lt;p&gt;npm run metaverse:load-baseline&lt;/p&gt;
&lt;p&gt;A local self-check successfully processed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;12 simultaneous connections;&lt;/li&gt;
&lt;li&gt;48 messages;&lt;/li&gt;
&lt;li&gt;44 queued operations;&lt;/li&gt;
&lt;li&gt;zero rejected operations;&lt;/li&gt;
&lt;li&gt;approximately 186 ms message p95 latency.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All modified JavaScript files passed syntax validation, and the 20 files uploaded to GitHub were verified against their remote hashes.&lt;/p&gt;
&lt;h3 id=&quot;what-the-production-check-revealed&quot;&gt;What the production check revealed&lt;/h3&gt;
&lt;p&gt;The Vercel deployment completed successfully, and the existing metaverse is online:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The metaverse health endpoint reports MongoDB as connected and the existing shared-polling transport as healthy:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/api/metaverse/health&quot;&gt;https://www.myzubster.com/api/metaverse/health&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;However, the new realtime metrics endpoint is not publicly active yet.&lt;/p&gt;
&lt;p&gt;The current Vercel deployment executes:&lt;/p&gt;
&lt;p&gt;api/index.js → server.js&lt;/p&gt;
&lt;p&gt;The persistent Socket.IO service is implemented in:&lt;/p&gt;
&lt;p&gt;backend/src/index.js&lt;/p&gt;
&lt;p&gt;This means that the code is merged, but the long-running realtime backend still needs its own production deployment.&lt;/p&gt;
&lt;h3 id=&quot;next-infrastructure-phase&quot;&gt;Next infrastructure phase&lt;/h3&gt;
&lt;p&gt;The next step is to deploy the realtime backend on a persistent Node.js service with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MongoDB;&lt;/li&gt;
&lt;li&gt;Redis;&lt;/li&gt;
&lt;li&gt;a secure realtime token secret;&lt;/li&gt;
&lt;li&gt;WebSocket support;&lt;/li&gt;
&lt;li&gt;routing for &lt;code&gt;/realtime&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;routing for &lt;code&gt;/api/realtime/*&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;monitoring dashboards and alerting;&lt;/li&gt;
&lt;li&gt;Redis and worker restart tests;&lt;/li&gt;
&lt;li&gt;production load testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vercel can continue serving the frontend and serverless APIs, while a persistent Node.js runtime handles Socket.IO traffic.&lt;/p&gt;
&lt;h3 id=&quot;an-important-engineering-lesson&quot;&gt;An important engineering lesson&lt;/h3&gt;
&lt;p&gt;A successful monorepo deployment does not necessarily mean that every service in the repository is running.&lt;/p&gt;
&lt;p&gt;Testing the production URLs helped us discover the exact boundary between the Vercel application and the persistent realtime backend.&lt;/p&gt;
&lt;p&gt;The code foundation is ready. The next objective is to connect it safely to the public MyZubster infrastructure.&lt;/p&gt;
&lt;p&gt;Project links:&lt;/p&gt;
&lt;p&gt;MyZubster Metaverse:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub organization:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem&quot;&gt;https://github.com/MyZubster-Ecosystem&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26509/the-myzubster-metaverse-has-reached-a-new-technical-milestone</guid>
<pubDate>Tue, 08 Sep 2026 16:14:01 +0000</pubDate>
</item>
<item>
<title>Building Social Life: Engineering a Social + WebXR Metaverse Platform</title>
<link>https://coderlegion.com/26279/building-social-life-engineering-a-social-webxr-metaverse-platform</link>
<description>&lt;h2 id=&quot;building-social-life-engineering-a-social-webxr-metaverse-platform&quot;&gt;Building Social Life: Engineering a Social + WebXR Metaverse Platform&lt;/h2&gt;
&lt;p&gt;We're turning &lt;strong&gt;Social Life / MyZubster Metaverse&lt;/strong&gt; from a concept into an actual engineering roadmap.&lt;/p&gt;
&lt;p&gt;The idea is to connect three layers that are usually built separately:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Social Network + Real-World Communities + WebXR Metaverse&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Instead of creating another isolated virtual world, we're designing the metaverse as a native extension of a social platform.&lt;/p&gt;
&lt;p&gt;A user should be able to discover a community, follow its activity, join conversations, discover a public cultural event, enter its virtual twin and continue interacting with that community after the event ends.&lt;/p&gt;
&lt;p&gt;All using the same identity and permission system.&lt;/p&gt;
&lt;h3 id=&quot;the-architecture&quot;&gt;The Architecture&lt;/h3&gt;
&lt;p&gt;Our current technical direction is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js / React&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redis&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Object storage + CDN&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebSockets&lt;/strong&gt; for realtime communication and presence&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebRTC / SFU&lt;/strong&gt; for live media&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Three.js or Babylon.js&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WebXR&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;glTF-based 3D asset pipeline&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The architecture is intentionally modular.&lt;/p&gt;
&lt;p&gt;The metaverse isn't a separate product.&lt;/p&gt;
&lt;p&gt;It sits on top of the same services used by the social platform.&lt;/p&gt;
&lt;p&gt;Conceptually:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Identity → Social Graph → Communities → Content → Realtime → Events → WebXR Rooms&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;phase-a-build-the-social-foundation&quot;&gt;Phase A: Build the Social Foundation&lt;/h3&gt;
&lt;p&gt;Before touching the more exciting immersive features, we're starting with the boring-but-critical infrastructure.&lt;/p&gt;
&lt;p&gt;The first engineering block contains:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Database → Authentication → Profiles → Social Graph&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From there we expand into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Communities&lt;/li&gt;
&lt;li&gt;Posts&lt;/li&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;li&gt;Reactions&lt;/li&gt;
&lt;li&gt;Feed&lt;/li&gt;
&lt;li&gt;Discover&lt;/li&gt;
&lt;li&gt;API contract tests&lt;/li&gt;
&lt;li&gt;End-to-end tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Authentication is designed around modern session management with revocation and server-side authorization.&lt;/p&gt;
&lt;p&gt;Privacy is also introduced during onboarding instead of being treated as an afterthought.&lt;/p&gt;
&lt;h3 id=&quot;phase-b-make-everything-realtime&quot;&gt;Phase B: Make Everything Realtime&lt;/h3&gt;
&lt;p&gt;The second layer introduces a WebSocket-based realtime gateway.&lt;/p&gt;
&lt;p&gt;The realtime architecture covers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User presence&lt;/li&gt;
&lt;li&gt;Community presence&lt;/li&gt;
&lt;li&gt;Virtual-room presence&lt;/li&gt;
&lt;li&gt;Direct messages&lt;/li&gt;
&lt;li&gt;Community channels&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Blocking&lt;/li&gt;
&lt;li&gt;Muting&lt;/li&gt;
&lt;li&gt;Reporting&lt;/li&gt;
&lt;li&gt;Moderation&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;Anti-spam controls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Channels can conceptually represent:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;user:{id}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;community:{id}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;session:{id}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The important rule is that the server remains authoritative.&lt;/p&gt;
&lt;p&gt;The client doesn't decide whether someone belongs in a private community or virtual room.&lt;/p&gt;
&lt;h3 id=&quot;phase-c-enter-webxr&quot;&gt;Phase C: Enter WebXR&lt;/h3&gt;
&lt;p&gt;This is where the social platform becomes an immersive environment.&lt;/p&gt;
&lt;p&gt;We're designing browser-accessible virtual rooms using WebXR.&lt;/p&gt;
&lt;p&gt;The runtime will combine:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;React + Three.js/Babylon.js + WebXR + WebAudio + WebSocket + WebRTC&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Rooms use a defined lifecycle:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Draft → Published → Scheduled → Live → Ended → Archive&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Each environment is represented through a versioned scene manifest referencing CDN-hosted assets.&lt;/p&gt;
&lt;p&gt;That gives us a controlled pipeline for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;glTF environments&lt;/li&gt;
&lt;li&gt;Media screens&lt;/li&gt;
&lt;li&gt;Portals&lt;/li&gt;
&lt;li&gt;Interactive zones&lt;/li&gt;
&lt;li&gt;Spatial audio&lt;/li&gt;
&lt;li&gt;Avatars&lt;/li&gt;
&lt;li&gt;Live stages&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;one-metaverse-multiple-devices&quot;&gt;One Metaverse, Multiple Devices&lt;/h3&gt;
&lt;p&gt;A major requirement is graceful degradation.&lt;/p&gt;
&lt;p&gt;VR hardware should improve the experience, not become a requirement.&lt;/p&gt;
&lt;p&gt;The same room should be accessible from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;VR/XR headsets&lt;/li&gt;
&lt;li&gt;Desktop browsers&lt;/li&gt;
&lt;li&gt;Mobile browsers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means every immersive feature needs a sensible non-XR fallback.&lt;/p&gt;
&lt;p&gt;We're also defining performance budgets, LOD strategies and asset constraints early rather than trying to optimize an enormous 3D application later.&lt;/p&gt;
&lt;h3 id=&quot;avatars-realtime-presence&quot;&gt;Avatars + Realtime Presence&lt;/h3&gt;
&lt;p&gt;Avatars are tied to the existing Social Life identity.&lt;/p&gt;
&lt;p&gt;We're starting lightweight.&lt;/p&gt;
&lt;p&gt;The realtime layer synchronizes ephemeral information such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Position&lt;/li&gt;
&lt;li&gt;Rotation&lt;/li&gt;
&lt;li&gt;Presence&lt;/li&gt;
&lt;li&gt;Basic interaction state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Durable identity and permissions stay in the backend.&lt;/p&gt;
&lt;p&gt;Transient spatial state belongs in the realtime system.&lt;/p&gt;
&lt;p&gt;Keeping those two concerns separate should make the system considerably easier to scale.&lt;/p&gt;
&lt;h3 id=&quot;physical-events-virtual-twins&quot;&gt;Physical Events → Virtual Twins&lt;/h3&gt;
&lt;p&gt;Another part of the architecture connects intentionally public cultural events with virtual rooms.&lt;/p&gt;
&lt;p&gt;A creator or community can publish a public event and optionally attach a virtual environment.&lt;/p&gt;
&lt;p&gt;The lifecycle becomes:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Physical/Public Event → Virtual Twin → Live Session → Replay / Archive&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The virtual experience doesn't have to disappear when the physical event finishes.&lt;/p&gt;
&lt;p&gt;Parts of it can remain accessible as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Replay&lt;/li&gt;
&lt;li&gt;Highlights&lt;/li&gt;
&lt;li&gt;Community content&lt;/li&gt;
&lt;li&gt;Archived rooms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We're deliberately keeping sensitive or concealed real-world location logistics outside the public product model. The event layer is designed around lawful, intentionally public information.&lt;/p&gt;
&lt;h3 id=&quot;creator-tools&quot;&gt;Creator Tools&lt;/h3&gt;
&lt;p&gt;Eventually creators need to operate these spaces without developers manually editing everything.&lt;/p&gt;
&lt;p&gt;So we're designing a Creator Studio around:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Community management&lt;/li&gt;
&lt;li&gt;Event publishing&lt;/li&gt;
&lt;li&gt;Room publishing&lt;/li&gt;
&lt;li&gt;Session management&lt;/li&gt;
&lt;li&gt;Media management&lt;/li&gt;
&lt;li&gt;Virtual-twin linking&lt;/li&gt;
&lt;li&gt;Archive controls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The long-term goal is to make creating a virtual community experience closer to managing a social page than building a game.&lt;/p&gt;
&lt;h3 id=&quot;creator-economy-comes-later&quot;&gt;Creator Economy Comes Later&lt;/h3&gt;
&lt;p&gt;We've also mapped out potential monetization:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Memberships&lt;/li&gt;
&lt;li&gt;Subscriptions&lt;/li&gt;
&lt;li&gt;Digital goods&lt;/li&gt;
&lt;li&gt;Avatar cosmetics&lt;/li&gt;
&lt;li&gt;Virtual-room assets&lt;/li&gt;
&lt;li&gt;Paid virtual sessions&lt;/li&gt;
&lt;li&gt;Creator revenue sharing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But we're intentionally not implementing this first.&lt;/p&gt;
&lt;p&gt;Payments introduce a completely different set of engineering and regulatory problems:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Payments → Ledger → Refunds → Revenue Split → Payouts → Tax/VAT → Compliance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So the roadmap contains a mandatory legal/product/compliance gate before production payment functionality.&lt;/p&gt;
&lt;p&gt;We're also &lt;strong&gt;not requiring a blockchain or token for the MVP&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Digital ownership can start with ordinary server-side entitlement records.&lt;/p&gt;
&lt;p&gt;If decentralized ownership eventually solves a real product problem, it can be evaluated later.&lt;/p&gt;
&lt;h3 id=&quot;turning-architecture-into-linear-issues&quot;&gt;Turning Architecture Into Linear Issues&lt;/h3&gt;
&lt;p&gt;One thing we've been focusing on heavily is converting architecture into executable engineering work.&lt;/p&gt;
&lt;p&gt;The project is now organized into five milestones:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A — Social Foundation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B — Realtime Social&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C — WebXR Metaverse&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;D — Public Events &amp;amp; Virtual Twins&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;E — Creator Economy Gate&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Each milestone has been decomposed into implementation-level issues with dependencies and acceptance criteria.&lt;/p&gt;
&lt;p&gt;For example, the WebXR milestone isn't simply:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Build the metaverse.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's broken down into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WebXR runtime&lt;/li&gt;
&lt;li&gt;Scene manifest and asset pipeline&lt;/li&gt;
&lt;li&gt;Avatar synchronization&lt;/li&gt;
&lt;li&gt;Room lifecycle&lt;/li&gt;
&lt;li&gt;Spatial audio&lt;/li&gt;
&lt;li&gt;WebRTC/SFU media&lt;/li&gt;
&lt;li&gt;Portals and interactive zones&lt;/li&gt;
&lt;li&gt;Performance and LOD&lt;/li&gt;
&lt;li&gt;End-to-end WebXR acceptance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That makes the project much easier to reason about.&lt;/p&gt;
&lt;h3 id=&quot;the-bigger-engineering-question&quot;&gt;The Bigger Engineering Question&lt;/h3&gt;
&lt;p&gt;The interesting challenge isn't really:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;How do we build a metaverse?&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It's:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;How do we make immersive environments behave like a normal part of the web?&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A virtual room should ultimately be another destination in the application.&lt;/p&gt;
&lt;p&gt;You discover it.&lt;/p&gt;
&lt;p&gt;You have permission to access it.&lt;/p&gt;
&lt;p&gt;You enter it.&lt;/p&gt;
&lt;p&gt;Your identity follows you.&lt;/p&gt;
&lt;p&gt;Your community follows you.&lt;/p&gt;
&lt;p&gt;Realtime services connect you to everyone else.&lt;/p&gt;
&lt;p&gt;And when you leave the 3D environment, you're still inside the same social ecosystem.&lt;/p&gt;
&lt;p&gt;That's the architecture we're working toward with &lt;strong&gt;Social Life / MyZubster Metaverse&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;what-s-next&quot;&gt;What's Next&lt;/h3&gt;
&lt;p&gt;We're now moving from architecture into implementation.&lt;/p&gt;
&lt;p&gt;The first development sequence is deliberately simple:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Database → Auth → Profiles → Social Graph → Communities → Content → Feed&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Realtime → Messaging → Presence&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And finally:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WebXR Runtime → Rooms → Avatars → Live Media → Virtual Twins&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I'll share more as individual components move from Linear issues into working code.&lt;/p&gt;
&lt;p&gt;I'm especially interested in hearing from developers working with &lt;strong&gt;WebXR, Three.js/Babylon.js, WebRTC, realtime infrastructure or large social architectures&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;How would you approach a browser-first social metaverse?&lt;/p&gt;
&lt;p&gt;And where do you think the hardest scaling problem will appear first?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26279/building-social-life-engineering-a-social-webxr-metaverse-platform</guid>
<pubDate>Sun, 06 Sep 2026 02:18:28 +0000</pubDate>
</item>
<item>
<title># MyZubster Overnight Update: Metaverse Safety and a Live Space Station</title>
<link>https://coderlegion.com/26181/myzubster-overnight-update-metaverse-safety-and-a-live-space-station</link>
<description>&lt;h2 id=&quot;myzubster-overnight-update-metaverse-safety-and-a-live-space-station&quot;&gt;MyZubster Overnight Update: Metaverse Safety and a Live Space Station&lt;/h2&gt;
&lt;p&gt;Last night we shipped two important improvements to the MyZubster open-source ecosystem: a formal safety baseline for our Metaverse and a public connection to the MyZubster Space Station.&lt;/p&gt;
&lt;h3 id=&quot;neon-plaza-is-becoming-a-real-shared-environment&quot;&gt;Neon Plaza is becoming a real shared environment&lt;/h3&gt;
&lt;p&gt;The MyZubster Metaverse is available here:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neon Plaza already supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shared MongoDB-backed presence&lt;/li&gt;
&lt;li&gt;Keyboard and touch movement&lt;/li&gt;
&lt;li&gt;Public chat and emotes&lt;/li&gt;
&lt;li&gt;Proximity awareness&lt;/li&gt;
&lt;li&gt;Guest and account-linked characters&lt;/li&gt;
&lt;li&gt;Portals to Marketplace, LIFE, Identity, Visual and Zorgax&lt;/li&gt;
&lt;li&gt;Session and browser capability dashboards&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current synchronization model uses serverless-compatible shared polling. WebSockets, 3D/WebXR rendering and spatial voice remain part of the future roadmap.&lt;/p&gt;
&lt;h3 id=&quot;privacy-and-abuse-control-baseline&quot;&gt;Privacy and abuse-control baseline&lt;/h3&gt;
&lt;p&gt;We merged &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster/pull/920&quot;&gt;PR #920&lt;/a&gt;, which documents the verified privacy and retention boundaries of Neon Plaza.&lt;/p&gt;
&lt;p&gt;The baseline establishes that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Presence expires after 90 seconds of inactivity&lt;/li&gt;
&lt;li&gt;Public chat expires after one hour&lt;/li&gt;
&lt;li&gt;User-controlled inputs are sanitized and length-limited&lt;/li&gt;
&lt;li&gt;Logs exclude chat content, tokens and session identifiers&lt;/li&gt;
&lt;li&gt;Authenticated characters are resolved through MyZubster accounts&lt;/li&gt;
&lt;li&gt;Client-provided identity claims are never considered verified&lt;/li&gt;
&lt;li&gt;Permanent movement history is not collected&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The change passed CI, frontend and backend tests, lint, Security Audit, Continuous Evidence Gate and Vercel checks.&lt;/p&gt;
&lt;p&gt;We also documented the remaining gaps honestly: distributed rate limiting, spam detection, mute, block, reporting, moderator auditing and formal deletion procedures are not complete yet.&lt;/p&gt;
&lt;h3 id=&quot;myzubster-space-station-is-online&quot;&gt;MyZubster Space Station is online&lt;/h3&gt;
&lt;p&gt;We also merged &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster/pull/921&quot;&gt;PR #921&lt;/a&gt;, introducing the public Space Station dashboard:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/space-station&quot;&gt;https://www.myzubster.com/space-station&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The website now accesses station health, robot and mission information through same-origin API proxy routes. Backend secrets are never exposed to the browser.&lt;/p&gt;
&lt;p&gt;The live health service currently reports:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;station&quot;: &quot;MYZUBSTER-SPACE-STATION&quot;,
  &quot;status&quot;: &quot;online&quot;,
  &quot;version&quot;: &quot;0.2.0&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browser access remains read-only. Inventory mutations, economic operations and robot commands will not be exposed until a production authentication and authorization layer is available.&lt;/p&gt;
&lt;p&gt;A broader read-only integration for spaces, inventory, MYZ balances and missions is under development in &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster/pull/919&quot;&gt;PR #919&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;where-this-is-going&quot;&gt;Where this is going&lt;/h3&gt;
&lt;p&gt;The goal is to connect several real components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neon Plaza as the social and immersive layer&lt;/li&gt;
&lt;li&gt;Space Station as the robotics and mission layer&lt;/li&gt;
&lt;li&gt;MyZubster Identity for persistent participants&lt;/li&gt;
&lt;li&gt;Marketplace for creator services and digital resources&lt;/li&gt;
&lt;li&gt;LIFE projects for environmental data and verifiable missions&lt;/li&gt;
&lt;li&gt;Evidence gates for reproducible technical claims&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The priority is not to call everything “complete.” The priority is to build openly, test each layer and distinguish production functionality from experiments and roadmap ideas.&lt;/p&gt;
&lt;p&gt;MyZubster is gradually becoming an open ecosystem where people, software agents, robots and real-world data can interact through verifiable identities and transparent infrastructure.&lt;/p&gt;
&lt;p&gt;GitHub: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem/myzubster&quot;&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;br&gt;
Metaverse: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;br&gt;
Space Station: &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/space-station&quot;&gt;https://www.myzubster.com/space-station&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;opensource-metaverse-robotics-nodejs-react-mongodb-webdevelopment&quot;&gt;OpenSource #Metaverse #Robotics #NodeJS #React #MongoDB #WebDevelopment&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26181/myzubster-overnight-update-metaverse-safety-and-a-live-space-station</guid>
<pubDate>Fri, 04 Sep 2026 00:38:10 +0000</pubDate>
</item>
<item>
<title>We’re Taking Zorgax From GitHub Into the Real World — And N4K48 Is One of the First Experiments</title>
<link>https://coderlegion.com/26042/were-taking-zorgax-from-github-into-the-real-world-and-n4k48-is-one-of-the-first-experiments</link>
<description>&lt;h2 id=&quot;we-re-taking-zorgax-from-github-into-the-real-world-and-n4k48-is-one-of-the-first-experiments&quot;&gt;We’re Taking Zorgax From GitHub Into the Real World — And N4K48 Is One of the First Experiments&lt;/h2&gt;
&lt;p&gt;For a long time, most of the work around &lt;strong&gt;MyZubster&lt;/strong&gt; and &lt;strong&gt;Zorgax&lt;/strong&gt; happened where you would expect an open-source project to live:&lt;/p&gt;
&lt;p&gt;GitHub repositories.&lt;/p&gt;
&lt;p&gt;APIs.&lt;/p&gt;
&lt;p&gt;Tests.&lt;/p&gt;
&lt;p&gt;CI pipelines.&lt;/p&gt;
&lt;p&gt;Architecture diagrams.&lt;/p&gt;
&lt;p&gt;Infrastructure experiments.&lt;/p&gt;
&lt;p&gt;But eventually every ambitious software project reaches an uncomfortable point:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Does any of this actually help a real person do something?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That is the phase we are entering now.&lt;/p&gt;
&lt;p&gt;And one of our first experiments has a name:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nicola.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Inside the MyZubster Metaverse, his character is &lt;strong&gt;N4K48&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But the interesting part isn't the avatar.&lt;/p&gt;
&lt;p&gt;It's what is happening outside the Metaverse.&lt;/p&gt;
&lt;h3 id=&quot;from-ai-assistant-to-execution-loop&quot;&gt;From AI assistant to execution loop&lt;/h3&gt;
&lt;p&gt;Zorgax started as an intelligence and coordination layer inside the broader MyZubster ecosystem.&lt;/p&gt;
&lt;p&gt;The model we are exploring is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Knowledge → Reasoning → Recommendation → Human Approval → Action → Measurement → Learning&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The important part is the middle.&lt;/p&gt;
&lt;p&gt;We don't want AI to silently make consequential decisions and then tell humans what happened.&lt;/p&gt;
&lt;p&gt;We want it to help people move from uncertainty to structured action while keeping important decisions human.&lt;/p&gt;
&lt;p&gt;So we started testing that idea with real participants.&lt;/p&gt;
&lt;p&gt;Nicola is one of them.&lt;/p&gt;
&lt;h3 id=&quot;nicola-started-with-an-idea&quot;&gt;Nicola started with an idea&lt;/h3&gt;
&lt;p&gt;The experiment is simple.&lt;/p&gt;
&lt;p&gt;Can Zorgax help someone move from an idea toward a small, testable digital product without pretending that AI already knows whether the idea will succeed?&lt;/p&gt;
&lt;p&gt;The process looks roughly like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;IDEA
  ↓
STRUCTURE
  ↓
VALIDATION
  ↓
EVIDENCE
  ↓
HUMAN DECISION
  ↓
MVP
  ↓
TEST
  ↓
MEASURE
  ↓
LEARN
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No guaranteed revenue.&lt;/p&gt;
&lt;p&gt;No invented market demand.&lt;/p&gt;
&lt;p&gt;No AI-generated success story.&lt;/p&gt;
&lt;p&gt;If the evidence is weak, the system should say that the evidence is weak.&lt;/p&gt;
&lt;h3 id=&quot;then-something-interesting-happened&quot;&gt;Then something interesting happened&lt;/h3&gt;
&lt;p&gt;Nicola didn't stop at discussing the idea.&lt;/p&gt;
&lt;p&gt;He started building.&lt;/p&gt;
&lt;p&gt;A GitHub repository appeared.&lt;/p&gt;
&lt;p&gt;Then the initial MVP structure.&lt;/p&gt;
&lt;p&gt;Then automated testing.&lt;/p&gt;
&lt;p&gt;Then GitHub Actions.&lt;/p&gt;
&lt;p&gt;Then the inevitable debugging.&lt;/p&gt;
&lt;p&gt;Test discovery needed fixing.&lt;/p&gt;
&lt;p&gt;Dependencies needed fixing.&lt;/p&gt;
&lt;p&gt;The server startup process needed fixing.&lt;/p&gt;
&lt;p&gt;Tests needed restructuring.&lt;/p&gt;
&lt;p&gt;HTTP expectations needed correcting.&lt;/p&gt;
&lt;p&gt;And commit by commit, the project started becoming something executable rather than something hypothetical.&lt;/p&gt;
&lt;p&gt;That distinction matters to me.&lt;/p&gt;
&lt;p&gt;There is an enormous difference between:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;AI gave me an idea.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;AI helped me organize a process that resulted in me actually building and testing something.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second one is what we're interested in.&lt;/p&gt;
&lt;h3 id=&quot;a-result-that-isn-t-revenue&quot;&gt;A result that isn't revenue&lt;/h3&gt;
&lt;p&gt;There is another outcome I find interesting.&lt;/p&gt;
&lt;p&gt;Nicola told us that working through this process increased his motivation enough that he decided to buy a computer so he could continue working on the project and with Zorgax.&lt;/p&gt;
&lt;p&gt;I'm deliberately careful about how I describe that.&lt;/p&gt;
&lt;p&gt;It isn't a financial KPI.&lt;/p&gt;
&lt;p&gt;It isn't proof of product-market fit.&lt;/p&gt;
&lt;p&gt;It isn't proof that his MVP will become a business.&lt;/p&gt;
&lt;p&gt;But it &lt;strong&gt;is evidence of behavioral change&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;An idea became activity.&lt;/p&gt;
&lt;p&gt;Activity became code.&lt;/p&gt;
&lt;p&gt;Code became tests.&lt;/p&gt;
&lt;p&gt;And the participant invested in his own ability to continue.&lt;/p&gt;
&lt;p&gt;For an experimental human-AI workflow, that's worth paying attention to.&lt;/p&gt;
&lt;h3 id=&quot;so-why-put-nicola-in-a-metaverse-&quot;&gt;So why put Nicola in a Metaverse?&lt;/h3&gt;
&lt;p&gt;This is where &lt;strong&gt;N4K48&lt;/strong&gt; enters the picture.&lt;/p&gt;
&lt;p&gt;MyZubster already has a browser-based shared environment called &lt;strong&gt;Neon Plaza&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Users can enter as guests, while authenticated users can have account-linked characters.&lt;/p&gt;
&lt;p&gt;The important architectural rule is that a manually entered guest identity is not treated as verified.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Because eventually the Metaverse is supposed to connect to things that matter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub contributions;&lt;/li&gt;
&lt;li&gt;missions;&lt;/li&gt;
&lt;li&gt;bounties;&lt;/li&gt;
&lt;li&gt;projects;&lt;/li&gt;
&lt;li&gt;community roles;&lt;/li&gt;
&lt;li&gt;environmental initiatives;&lt;/li&gt;
&lt;li&gt;creator activity;&lt;/li&gt;
&lt;li&gt;potentially economic transactions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If reputation matters, we can't manufacture it with an arbitrary username.&lt;/p&gt;
&lt;h3 id=&quot;n4k48&quot;&gt;N4K48&lt;/h3&gt;
&lt;p&gt;Nicola's character is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;N4K48&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Archetype:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Explorer&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;World:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Neon Plaza&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The long-term idea is that N4K48 shouldn't simply be a visual avatar.&lt;/p&gt;
&lt;p&gt;It should become a representation of Nicola's verifiable journey through the ecosystem.&lt;/p&gt;
&lt;p&gt;Imagine this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Real contribution
       ↓
GitHub evidence
       ↓
Verification
       ↓
MyZubster identity
       ↓
Metaverse achievement
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of buying a shiny &quot;developer badge&quot;, you earn it because there is actual evidence that you contributed.&lt;/p&gt;
&lt;p&gt;Instead of claiming that you completed a project, the project can point back to its evidence.&lt;/p&gt;
&lt;p&gt;Instead of the Metaverse creating reputation, the Metaverse &lt;strong&gt;visualizes reputation created elsewhere&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That's a much more interesting problem.&lt;/p&gt;
&lt;h3 id=&quot;the-metaverse-becomes-an-interface&quot;&gt;The Metaverse becomes an interface&lt;/h3&gt;
&lt;p&gt;This changes how I think about virtual worlds.&lt;/p&gt;
&lt;p&gt;A Metaverse doesn't necessarily have to be a replacement reality.&lt;/p&gt;
&lt;p&gt;It could be an interface to real activity.&lt;/p&gt;
&lt;p&gt;A GitHub issue could become a mission terminal.&lt;/p&gt;
&lt;p&gt;An environmental sensor network could become a digital twin.&lt;/p&gt;
&lt;p&gt;A community project could have its own district.&lt;/p&gt;
&lt;p&gt;A contributor could walk through Neon Plaza and discover something they can actually work on.&lt;/p&gt;
&lt;p&gt;And a character like N4K48 could carry a history based on real contributions rather than fictional statistics.&lt;/p&gt;
&lt;h3 id=&quot;zorgax-shouldn-t-control-this-world&quot;&gt;Zorgax shouldn't control this world&lt;/h3&gt;
&lt;p&gt;There's another boundary we're trying to preserve.&lt;/p&gt;
&lt;p&gt;Zorgax should not become the invisible ruler of the ecosystem.&lt;/p&gt;
&lt;p&gt;It can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;analyze;&lt;/li&gt;
&lt;li&gt;compare;&lt;/li&gt;
&lt;li&gt;organize;&lt;/li&gt;
&lt;li&gt;suggest;&lt;/li&gt;
&lt;li&gt;detect inconsistencies;&lt;/li&gt;
&lt;li&gt;prepare actions;&lt;/li&gt;
&lt;li&gt;measure outcomes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But sensitive decisions still need explicit human authority.&lt;/p&gt;
&lt;p&gt;That applies to publishing.&lt;/p&gt;
&lt;p&gt;Payments.&lt;/p&gt;
&lt;p&gt;Commercial communication.&lt;/p&gt;
&lt;p&gt;Important identity changes.&lt;/p&gt;
&lt;p&gt;And decisions about whether evidence is sufficient.&lt;/p&gt;
&lt;p&gt;The architecture we're aiming for is therefore not:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;AI → ACTION
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's closer to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;DATA
  ↓
ZORGAX
  ↓
RECOMMENDATION
  ↓
HUMAN DECISION
  ↓
ACTION
  ↓
MEASUREMENT
  ↓
LEARNING
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Slower?&lt;/p&gt;
&lt;p&gt;Sometimes.&lt;/p&gt;
&lt;p&gt;More auditable?&lt;/p&gt;
&lt;p&gt;Hopefully.&lt;/p&gt;
&lt;h3 id=&quot;the-same-principle-applies-to-money&quot;&gt;The same principle applies to money&lt;/h3&gt;
&lt;p&gt;The economic layer we're building follows a similar philosophy.&lt;/p&gt;
&lt;p&gt;MyZubster is exploring non-custodial payment flows.&lt;/p&gt;
&lt;p&gt;The platform shouldn't need someone's private keys.&lt;/p&gt;
&lt;p&gt;A simplified model is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Payment intent
      ↓
External wallet
      ↓
Blockchain transaction
      ↓
Independent verification
      ↓
Entitlement / result
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But even here, a blockchain transaction isn't magical proof that something happened.&lt;/p&gt;
&lt;p&gt;A payment can prove that funds moved.&lt;/p&gt;
&lt;p&gt;It cannot automatically prove that a product was delivered.&lt;/p&gt;
&lt;p&gt;It cannot prove that a GitHub contribution was good.&lt;/p&gt;
&lt;p&gt;It cannot prove that an environmental intervention worked.&lt;/p&gt;
&lt;p&gt;Different claims require different evidence.&lt;/p&gt;
&lt;p&gt;That's becoming one of the recurring principles behind MyZubster.&lt;/p&gt;
&lt;h3 id=&quot;from-virtual-identity-to-real-world-evidence&quot;&gt;From virtual identity to real-world evidence&lt;/h3&gt;
&lt;p&gt;The same architecture becomes even more interesting when we move outside purely digital projects.&lt;/p&gt;
&lt;p&gt;We're exploring concepts involving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IoT;&lt;/li&gt;
&lt;li&gt;environmental monitoring;&lt;/li&gt;
&lt;li&gt;water;&lt;/li&gt;
&lt;li&gt;biodiversity;&lt;/li&gt;
&lt;li&gt;territorial projects;&lt;/li&gt;
&lt;li&gt;digital twins;&lt;/li&gt;
&lt;li&gt;measurable environmental results.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A future workflow might look like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;PHYSICAL WORLD
      ↓
SENSORS
      ↓
DATA
      ↓
ZORGAX
      ↓
HUMAN DECISION
      ↓
ACTION
      ↓
MEASUREMENT
      ↓
VERIFICATION
      ↓
METAVERSE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The virtual representation comes &lt;strong&gt;after the evidence&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not before it.&lt;/p&gt;
&lt;p&gt;That's important.&lt;/p&gt;
&lt;h3 id=&quot;what-exists-today&quot;&gt;What exists today&lt;/h3&gt;
&lt;p&gt;There is still a huge amount to build.&lt;/p&gt;
&lt;p&gt;Neon Plaza is an early environment, not some finished decentralized universe.&lt;/p&gt;
&lt;p&gt;Today we have foundations such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;browser-based Metaverse access;&lt;/li&gt;
&lt;li&gt;guest and authenticated characters;&lt;/li&gt;
&lt;li&gt;account-linked identities;&lt;/li&gt;
&lt;li&gt;shared presence;&lt;/li&gt;
&lt;li&gt;movement;&lt;/li&gt;
&lt;li&gt;chat and emotes;&lt;/li&gt;
&lt;li&gt;temporary data retention;&lt;/li&gt;
&lt;li&gt;production monitoring;&lt;/li&gt;
&lt;li&gt;automated testing;&lt;/li&gt;
&lt;li&gt;a roadmap toward missions, economy and federation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And now we are beginning to connect that infrastructure with real participants.&lt;/p&gt;
&lt;p&gt;N4K48 is one of the first examples.&lt;/p&gt;
&lt;h3 id=&quot;what-nicola-s-experiment-actually-tells-us&quot;&gt;What Nicola's experiment actually tells us&lt;/h3&gt;
&lt;p&gt;Not that Zorgax can create successful companies.&lt;/p&gt;
&lt;p&gt;We don't know that.&lt;/p&gt;
&lt;p&gt;Not that every AI-assisted idea will work.&lt;/p&gt;
&lt;p&gt;Obviously not.&lt;/p&gt;
&lt;p&gt;And certainly not that writing prompts magically creates entrepreneurship.&lt;/p&gt;
&lt;p&gt;What we can say is much smaller — but more useful:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;a participant moved from an idea to structured activity and technical execution.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is now something we can observe.&lt;/p&gt;
&lt;p&gt;Something we can test.&lt;/p&gt;
&lt;p&gt;Something that can fail.&lt;/p&gt;
&lt;p&gt;Something that can improve.&lt;/p&gt;
&lt;p&gt;That is much more valuable to an engineering project than another hypothetical AI demo.&lt;/p&gt;
&lt;h3 id=&quot;building-in-public-means-showing-the-unfinished-parts&quot;&gt;Building in public means showing the unfinished parts&lt;/h3&gt;
&lt;p&gt;This experiment could fail.&lt;/p&gt;
&lt;p&gt;Nicola's MVP might need to change direction.&lt;/p&gt;
&lt;p&gt;Users might not care about it.&lt;/p&gt;
&lt;p&gt;Our assumptions about the Metaverse might be wrong.&lt;/p&gt;
&lt;p&gt;Some parts of Zorgax might turn out to be unnecessarily complicated.&lt;/p&gt;
&lt;p&gt;That's fine.&lt;/p&gt;
&lt;p&gt;The objective isn't to document a predetermined success.&lt;/p&gt;
&lt;p&gt;The objective is to build an evidence loop.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;BUILD
  ↓
TEST
  ↓
OBSERVE
  ↓
DECIDE
  ↓
IMPROVE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And repeat.&lt;/p&gt;
&lt;h3 id=&quot;n4k48-is-just-the-beginning&quot;&gt;N4K48 is just the beginning&lt;/h3&gt;
&lt;p&gt;Eventually I want to walk into Neon Plaza and see characters whose histories actually mean something.&lt;/p&gt;
&lt;p&gt;A developer with contributions you can inspect.&lt;/p&gt;
&lt;p&gt;A researcher connected to a real project.&lt;/p&gt;
&lt;p&gt;A participant building their first digital product.&lt;/p&gt;
&lt;p&gt;A community running an environmental initiative.&lt;/p&gt;
&lt;p&gt;An explorer completing an open-source mission.&lt;/p&gt;
&lt;p&gt;Not because a centralized game database awarded them 5,000 XP.&lt;/p&gt;
&lt;p&gt;Because something happened in the real world — and there is evidence for it.&lt;/p&gt;
&lt;p&gt;That's the experiment.&lt;/p&gt;
&lt;p&gt;Nicola is building.&lt;/p&gt;
&lt;p&gt;N4K48 is entering Neon Plaza.&lt;/p&gt;
&lt;p&gt;And Zorgax is slowly moving from repositories and architecture diagrams into the much messier environment that actually matters:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;reality.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;MyZubster&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com&quot;&gt;https://www.myzubster.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enter Neon Plaza&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.myzubster.com/metaverse&quot;&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MyZubster-Ecosystem&quot;&gt;https://github.com/MyZubster-Ecosystem&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you're building open-source systems around AI agents, verifiable identity, virtual worlds, IoT, human-in-the-loop automation or evidence-based reputation, I'd be interested in comparing approaches.&lt;/p&gt;
&lt;p&gt;We're still building this in public.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26042/were-taking-zorgax-from-github-into-the-real-world-and-n4k48-is-one-of-the-first-experiments</guid>
<pubDate>Wed, 02 Sep 2026 01:08:38 +0000</pubDate>
</item>
<item>
<title>We’re Building Zorgax as a Consent-Driven AI Operating Layer</title>
<link>https://coderlegion.com/25883/were-building-zorgax-as-a-consent-driven-ai-operating-layer</link>
<description>&lt;p&gt;We’re Building Zorgax as a Consent-Driven AI Operating Layer&lt;/p&gt;
&lt;p&gt;We’re currently experimenting with a different approach to AI agents inside MyZubster.&lt;/p&gt;
&lt;p&gt;The goal is not to build an agent that “does everything automatically.”&lt;/p&gt;
&lt;p&gt;The goal is to build an agent that can operate across projects, identity, evidence, GitHub workflows, and eventually economic actions — while keeping consent, auditability, and human approval as first-class constraints.&lt;/p&gt;
&lt;p&gt;That agent is Zorgax.&lt;/p&gt;
&lt;p&gt;The current pilot&lt;/p&gt;
&lt;p&gt;We’re testing Zorgax with a real participant in a digital entrepreneur workflow.&lt;/p&gt;
&lt;p&gt;The process is intentionally structured:&lt;/p&gt;
&lt;p&gt;Idea → Validation → Evidence → Human Choice → Blueprint → MVP → Approval → Possible Launch → Measurement → Learning&lt;/p&gt;
&lt;p&gt;Instead of letting AI jump directly from “idea” to “build,” Zorgax first collects and evaluates evidence.&lt;/p&gt;
&lt;p&gt;For the current pilot, two possible product ideas are being validated with real users.&lt;/p&gt;
&lt;p&gt;Before evaluating the next responses, we created a fixed scoring model.&lt;/p&gt;
&lt;p&gt;Each response can be scored against six criteria:&lt;/p&gt;
&lt;p&gt;real problem;&lt;br&gt;
urgency/intensity;&lt;br&gt;
weakness of current solution;&lt;br&gt;
willingness to test;&lt;br&gt;
clarity of expected result;&lt;br&gt;
clarity of required feature.&lt;/p&gt;
&lt;p&gt;The model is defined before seeing the full dataset.&lt;/p&gt;
&lt;p&gt;This avoids one of the easiest failure modes in AI-assisted decision making: changing the evaluation logic after seeing the answers.&lt;/p&gt;
&lt;p&gt;If the evidence is insufficient, Zorgax should not invent confidence.&lt;/p&gt;
&lt;p&gt;It returns:&lt;/p&gt;
&lt;p&gt;MORE EVIDENCE REQUIRED&lt;/p&gt;
&lt;p&gt;If the evidence is equivalent:&lt;/p&gt;
&lt;p&gt;TIE / HUMAN CHOICE&lt;/p&gt;
&lt;p&gt;That distinction matters.&lt;/p&gt;
&lt;p&gt;Consent-driven automation&lt;/p&gt;
&lt;p&gt;We are now adding another layer:&lt;/p&gt;
&lt;p&gt;Zorgax Participant Profile Automation v0.1&lt;/p&gt;
&lt;p&gt;The idea is to let Zorgax automatically maintain a participant’s project profile, but only inside an explicit consent boundary.&lt;/p&gt;
&lt;p&gt;The intended flow is:&lt;/p&gt;
&lt;p&gt;Consent → Authorized Scope → Data Processing → Proposed Update → Review → Human Approval&lt;/p&gt;
&lt;p&gt;The participant can authorize Zorgax to use things like:&lt;/p&gt;
&lt;p&gt;confirmed questionnaire responses;&lt;br&gt;
project goals;&lt;br&gt;
public GitHub activity;&lt;br&gt;
documented progress;&lt;br&gt;
validated evidence;&lt;br&gt;
roadmap status.&lt;/p&gt;
&lt;p&gt;Sensitive data stays outside the automation:&lt;/p&gt;
&lt;p&gt;passwords;&lt;br&gt;
tokens;&lt;br&gt;
2FA codes;&lt;br&gt;
wallet secrets;&lt;br&gt;
private keys;&lt;br&gt;
banking data;&lt;br&gt;
unnecessary personal information.&lt;/p&gt;
&lt;p&gt;If a field is unknown, the system should preserve that uncertainty instead of filling it with generated content.&lt;/p&gt;
&lt;p&gt;GitHub becomes the audit layer&lt;/p&gt;
&lt;p&gt;One design choice we are testing is using GitHub as the operational audit trail.&lt;/p&gt;
&lt;p&gt;The preferred workflow is:&lt;/p&gt;
&lt;p&gt;ZORGAX → BRANCH → COMMIT → PULL REQUEST → HUMAN REVIEW → MERGE&lt;/p&gt;
&lt;p&gt;This makes AI-generated work inspectable.&lt;/p&gt;
&lt;p&gt;You can see:&lt;/p&gt;
&lt;p&gt;what Zorgax changed,&lt;/p&gt;
&lt;p&gt;why it changed,&lt;/p&gt;
&lt;p&gt;what evidence supported the change,&lt;/p&gt;
&lt;p&gt;and whether a human approved it.&lt;/p&gt;
&lt;p&gt;That is much safer than giving an agent unrestricted write access to production state.&lt;/p&gt;
&lt;p&gt;Identity and the Metaverse&lt;/p&gt;
&lt;p&gt;We’re also applying the same principle to MyZubster Metaverse identities.&lt;/p&gt;
&lt;p&gt;Instead of treating avatars as disconnected aliases, we’re working toward account-linked characters.&lt;/p&gt;
&lt;p&gt;A participant can choose:&lt;/p&gt;
&lt;p&gt;character name;&lt;br&gt;
archetype;&lt;br&gt;
starting world;&lt;/p&gt;
&lt;p&gt;while the identity link is based on a verified account flow.&lt;/p&gt;
&lt;p&gt;The interesting part is not the 3D character.&lt;/p&gt;
&lt;p&gt;It is the identity graph behind it.&lt;/p&gt;
&lt;p&gt;A character could eventually represent:&lt;/p&gt;
&lt;p&gt;verified participation;&lt;br&gt;
contributions;&lt;br&gt;
project history;&lt;br&gt;
achievements;&lt;br&gt;
evidence;&lt;br&gt;
reputation.&lt;/p&gt;
&lt;p&gt;Without exposing credentials to the AI.&lt;/p&gt;
&lt;p&gt;Human-in-the-loop is not a limitation&lt;/p&gt;
&lt;p&gt;A lot of agent systems treat human approval as friction.&lt;/p&gt;
&lt;p&gt;We’re treating it as architecture.&lt;/p&gt;
&lt;p&gt;For example, Zorgax can prepare recommendations, profile changes, project updates, and code changes automatically.&lt;/p&gt;
&lt;p&gt;But sensitive actions remain gated:&lt;/p&gt;
&lt;p&gt;merge to protected branches;&lt;br&gt;
public commercial publication;&lt;br&gt;
real pricing;&lt;br&gt;
spending;&lt;br&gt;
payments;&lt;br&gt;
wallet actions;&lt;br&gt;
destructive database changes;&lt;br&gt;
external commercial communications.&lt;/p&gt;
&lt;p&gt;The larger model is:&lt;/p&gt;
&lt;p&gt;Knowledge → Reasoning → Decision → Human Approval → Action → Measurement → Learning&lt;/p&gt;
&lt;p&gt;That is the direction we are building Zorgax toward.&lt;/p&gt;
&lt;p&gt;Why we think this matters&lt;/p&gt;
&lt;p&gt;AI agents are becoming more capable very quickly.&lt;/p&gt;
&lt;p&gt;But capability without boundaries is not enough.&lt;/p&gt;
&lt;p&gt;When an agent starts interacting with real identity, money, public reputation, infrastructure, or business decisions, we need stronger operational guarantees.&lt;/p&gt;
&lt;p&gt;We need:&lt;/p&gt;
&lt;p&gt;consent, provenance, auditability, reversibility, and human authority.&lt;/p&gt;
&lt;p&gt;Our current hypothesis is simple:&lt;/p&gt;
&lt;p&gt;the best AI operating layer is not the one that removes the human.&lt;/p&gt;
&lt;p&gt;It is the one that removes repetitive work while making important decisions easier to understand and safer to execute.&lt;/p&gt;
&lt;p&gt;That is what we are trying to build with MyZubster + Zorgax.&lt;/p&gt;
&lt;h2 id=&quot;ai-aiagents-opensource-zorgax-myzubster-humanintheloop-github-automation-digitalidentity-metaverse-buildinpublic&quot;&gt;AI #AIAgents #OpenSource #Zorgax #MyZubster #HumanInTheLoop #GitHub #Automation #DigitalIdentity #Metaverse #BuildInPublic&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25883/were-building-zorgax-as-a-consent-driven-ai-operating-layer</guid>
<pubDate>Mon, 31 Aug 2026 01:24:49 +0000</pubDate>
</item>
<item>
<title>Yassen Mainardi Enters the MyZubster Universe</title>
<link>https://coderlegion.com/25564/yassen-mainardi-enters-the-myzubster-universe</link>
<description>&lt;p&gt;Yassen Mainardi Enters the MyZubster Universe&lt;/p&gt;
&lt;p&gt;The MyZubster universe continues to grow.&lt;/p&gt;
&lt;p&gt;Today we introduce Yassen Mainardi, a new character connected to the evolving world of MyZubster — where real-world participation, digital identity, environmental action, technology, culture, music and community can become part of a persistent digital story.&lt;/p&gt;
&lt;p&gt;A character is more than an avatar&lt;/p&gt;
&lt;p&gt;One of the ideas behind MyZubster is that a character should not simply be a profile picture.&lt;/p&gt;
&lt;p&gt;A character can become the representation of a journey.&lt;/p&gt;
&lt;p&gt;Actions, projects, contributions and verified experiences can progressively build its history.&lt;/p&gt;
&lt;p&gt;For Yassen Mainardi, we want to explore exactly this concept:&lt;/p&gt;
&lt;p&gt;real person → digital character → activities → evidence → evolving story&lt;/p&gt;
&lt;p&gt;Instead of creating a static fictional biography, the character can grow alongside the real activities that are actually documented.&lt;/p&gt;
&lt;p&gt;The MyZubster Character Layer&lt;/p&gt;
&lt;p&gt;Our longer-term architecture connects several components:&lt;/p&gt;
&lt;p&gt;Real-world identity&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MyZubster Character&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verified activities&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Photos / evidence / contributions&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reputation &amp;amp; achievements&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Persistent digital history&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    ↓
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MyZubster Universe&lt;/p&gt;
&lt;p&gt;This allows characters such as Yassen Mainardi to potentially participate across different MyZubster categories rather than being locked into a single experience.&lt;/p&gt;
&lt;p&gt;Environment.&lt;br&gt;
Music.&lt;br&gt;
Sport.&lt;br&gt;
Culture.&lt;br&gt;
Technology.&lt;br&gt;
Community projects.&lt;br&gt;
Creative work.&lt;/p&gt;
&lt;p&gt;Each category can become another part of the character's history.&lt;/p&gt;
&lt;p&gt;From characters to a living ecosystem&lt;/p&gt;
&lt;p&gt;This is also why we're developing MyZubster characters alongside our work on maps, environmental pilots, evidence verification and decentralized infrastructure.&lt;/p&gt;
&lt;p&gt;The goal isn't simply to populate a metaverse with avatars.&lt;/p&gt;
&lt;p&gt;The interesting question is:&lt;/p&gt;
&lt;p&gt;What happens when a digital character can carry a verifiable history of what its human counterpart has actually contributed?&lt;/p&gt;
&lt;p&gt;Yassen Mainardi represents another step in exploring that idea.&lt;/p&gt;
&lt;p&gt;The character starts here.&lt;/p&gt;
&lt;p&gt;The story will be written by what happens next.&lt;/p&gt;
&lt;p&gt;Welcome to MyZubster, Yassen.&lt;/p&gt;
&lt;h2 id=&quot;myzubster-opensource-digitalidentity-metaverse-community-buildinpublic-web3&quot;&gt;MyZubster #OpenSource #DigitalIdentity #Metaverse #Community #BuildInPublic #Web3&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25564/yassen-mainardi-enters-the-myzubster-universe</guid>
<pubDate>Thu, 27 Aug 2026 23:50:11 +0000</pubDate>
</item>
<item>
<title>The Internet Is Ruined: Can the Metaverse Still Be Saved?</title>
<link>https://coderlegion.com/13108/the-internet-is-ruined-can-the-metaverse-still-be-saved</link>
<description>
&lt;h1&gt;The Internet Is Ruined: Can the Metaverse Still Be Saved?&lt;/h1&gt;
&lt;p&gt;We live in an era of digital exhaustion. For many, logging onto the modern internet feels less like an exploration of infinite possibilities and more like walking through a crowded, neon-lit shopping mall where every storefront is screaming for your attention, data, and wallet. The promise of the early web&amp;mdash;a decentralized, open landscape for human connection&amp;mdash;has been supplanted by the walled gardens of massive conglomerates. Algorithmic feeds, relentless surveillance capitalism, and the erosion of privacy have turned our digital public square into a battlefield of noise. The internet, in its current iteration, is effectively ruined.&lt;/p&gt;
&lt;h2&gt;The Decline of the Digital Commons&lt;/h2&gt;
&lt;p&gt;To understand why the internet feels broken, we must look at the transition from Web 2.0 to the platform-centric model we inhabit today. Initially, the web was about discovery. You surfed pages, you visited distinct sites, and you learned things. Today, the internet is about &amp;lsquo;consumption environments.&amp;rsquo; We do not &amp;lsquo;browse&amp;rsquo; the web anymore; we scroll through feeds curated by black-box algorithms designed to keep us agitated and engaged. This model has stripped the internet of its spontaneity and replaced it with a flattened, homogenized experience. The result? A digital landscape that feels claustrophobic, repetitive, and increasingly hostile to genuine human interaction.&lt;/p&gt;
&lt;h2&gt;Enter the Metaverse: A Second Chance or a Second Scam?&lt;/h2&gt;
&lt;p&gt;Against this backdrop, the concept of the Metaverse has emerged. Initially marketed as a rebranding exercise for Big Tech, the term has become a lightning rod for criticism. Is it just a glorified video game? Is it a dystopian surveillance trap? These are valid concerns, especially given the current trajectory of centralized technology providers. However, if we peel back the marketing jargon and the shiny VR headsets, the core premise of the Metaverse represents a radical shift in how we relate to digital space.&lt;/p&gt;
&lt;p&gt;The vision of a spatial internet&amp;mdash;one where we are &amp;lsquo;in&amp;rsquo; the experience rather than &amp;lsquo;looking&amp;rsquo; at it&amp;mdash;could be the antidote to the flat, algorithmic noise of our current web. Instead of being passive consumers of content, we can become active participants in persistent, communal spaces. The Metaverse offers the opportunity to decouple our social and professional lives from the data-harvesting social media platforms that have dominated the last two decades.&lt;/p&gt;
&lt;h2&gt;Building for Sovereignty&lt;/h2&gt;
&lt;p&gt;For the Metaverse to save us from the ruin of the current internet, it must be fundamentally different from its predecessor. It cannot be owned by a single corporation. It must be built on open standards, interoperability, and digital sovereignty. The decentralization movement within Web3 is not just about finance; it is about infrastructure. If we can create virtual spaces where users own their digital assets, their identity, and their data, we fundamentally change the power dynamic. The platform no longer owns the user; the user owns the space.&lt;/p&gt;
&lt;p&gt;Imagine a digital world where you can take your avatar, your clothes, your tools, and your reputation from one experience to another without needing permission from a central authority. This is the promise of an interoperable Metaverse. It is the antithesis of the &amp;lsquo;locked-in&amp;rsquo; ecosystem that defines our current mobile experience. By prioritizing open-source code and decentralized protocols, we can build a digital architecture that serves the user first, rather than the advertiser.&lt;/p&gt;
&lt;h2&gt;Reframing the Immersive Experience&lt;/h2&gt;
&lt;p&gt;The skepticism surrounding the Metaverse is largely driven by the &amp;lsquo;gimmick&amp;rsquo; factor. People associate it with clunky headsets and low-resolution avatars. But the Metaverse is not a hardware problem; it is a connectivity and infrastructure problem. It is about the ability to share a sense of &amp;lsquo;presence&amp;rsquo; with others regardless of physical distance. Think of the difference between reading a text message and sitting across the table from a friend. The current internet is all text messages. A properly realized Metaverse provides that sense of shared space.&lt;/p&gt;
&lt;p&gt;This is crucial for the future of work, education, and socialization. We have spent the last few years discovering that digital communication is efficient but emotionally hollow. A persistent, spatial web could restore the nuance of human interaction, allowing for spontaneous meetings, collaborative creative endeavors, and complex environmental design that is simply impossible on a flat 2D webpage.&lt;/p&gt;
&lt;h2&gt;Addressing the Dystopian Risks&lt;/h2&gt;
&lt;p&gt;Of course, the Metaverse is not inherently benign. If we replicate the mistakes of the current web&amp;mdash;centralization, lack of moderation, and unchecked surveillance&amp;mdash;we will simply be building a more effective cage. The risks of digital addiction, harassment, and the further erosion of physical reality are significant. To save the internet through the Metaverse, we need a strong focus on ethics, accessibility, and governance.&lt;/p&gt;
&lt;p&gt;We need to develop new social contracts for virtual spaces. How do we ensure that these environments are inclusive? How do we protect users from toxic behavior without resorting to the censorship models that currently plague social media? These are the questions that technologists, sociologists, and policymakers need to solve right now. The Metaverse should be a tool for human flourishing, not a way to isolate ourselves further from the real world.&lt;/p&gt;
&lt;h2&gt;The Road Ahead: A Call for Openness&lt;/h2&gt;
&lt;p&gt;The current internet is ruined because we let it become a commodity. We traded our privacy and our attention for convenience. Saving the digital future requires a conscious effort to support open, transparent, and user-focused technologies. We must demand interoperability, reject proprietary ecosystems, and push for a web that feels human again.&lt;/p&gt;
&lt;p&gt;The Metaverse is still in its infancy, which means it is still malleable. We have the chance to define what it becomes before it is finalized by monolithic entities. If we treat it as an extension of the open web&amp;mdash;a continuation of the dream of a decentralized, free-flowing information network&amp;mdash;we might just find that the internet isn&amp;rsquo;t broken beyond repair. We might find that we have simply reached the end of one cycle and are ready to build the next one, better, stronger, and more human than before.&lt;/p&gt;
&lt;p&gt;The future of the internet is not something that happens to us; it is something we build. Let us make sure that when we step into the next phase of our digital evolution, we are walking into a world that reflects our best intentions, not our worst habits.&lt;/p&gt;&lt;p&gt;The post &lt;a rel=&quot;nofollow&quot; href=&quot;https://insightginie.com/the-internet-is-ruined-can-the-metaverse-still-be-saved/&quot;&gt;The Internet Is Ruined: Can the Metaverse Still Be Saved?&lt;/a&gt; first appeared on &lt;a rel=&quot;nofollow&quot; href=&quot;https://insightginie.com&quot;&gt;Insight Ginie&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/13108/the-internet-is-ruined-can-the-metaverse-still-be-saved</guid>
<pubDate>Fri, 20 Mar 2026 05:25:59 +0000</pubDate>
</item>
</channel>
</rss>