<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Ioni</title>
    <description>The latest articles on DEV Community by Daniel Ioni (@danielioni).</description>
    <link>https://dev.to/danielioni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4014925%2F997f1a4a-e9ae-47a4-a2fd-cb9c37f82a9f.jpg</url>
      <title>DEV Community: Daniel Ioni</title>
      <link>https://dev.to/danielioni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danielioni"/>
    <language>en</language>
    <item>
      <title>MyZubster Engineering Dev Log</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Sun, 27 Sep 2026 00:52:31 +0000</pubDate>
      <link>https://dev.to/danielioni/myzubster-engineering-dev-log-2ai2</link>
      <guid>https://dev.to/danielioni/myzubster-engineering-dev-log-2ai2</guid>
      <description>&lt;h1&gt;
  
  
  MyZubster Engineering Dev Log
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Sepolia E2E Infrastructure, Google OAuth Validation, Runtime Stabilization and the Road Toward a Production-Grade Platform
&lt;/h2&gt;

&lt;p&gt;Over the last development cycle, we focused on one of the least visible but most important parts of the MyZubster architecture: making the development and Sepolia environments deterministic enough to support real authentication, blockchain payment validation, persistent backend services, and auditable CI/CD workflows.&lt;/p&gt;

&lt;p&gt;This was not simply a feature implementation.&lt;/p&gt;

&lt;p&gt;The work involved debugging several layers of the system simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js runtime dependencies&lt;/li&gt;
&lt;li&gt;PM2 process supervision&lt;/li&gt;
&lt;li&gt;MongoDB connectivity&lt;/li&gt;
&lt;li&gt;reverse-proxy behavior&lt;/li&gt;
&lt;li&gt;Google OAuth callbacks&lt;/li&gt;
&lt;li&gt;frontend/backend routing&lt;/li&gt;
&lt;li&gt;Sepolia E2E infrastructure&lt;/li&gt;
&lt;li&gt;Git branch isolation&lt;/li&gt;
&lt;li&gt;secret hygiene&lt;/li&gt;
&lt;li&gt;GitHub CI evidence generation&lt;/li&gt;
&lt;li&gt;deployment diagnostics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The objective is to move MyZubster from a system where individual components work independently toward an environment where the entire lifecycle can be reproduced, tested and eventually promoted safely.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. Starting Point
&lt;/h1&gt;

&lt;p&gt;The environment initially had several runtime and infrastructure issues that prevented reliable E2E validation.&lt;/p&gt;

&lt;p&gt;One of the first failures appeared in the UrbanLab Node.js service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: Cannot find module 'helmet'
Require stack:
- /opt/I-ECO-01/server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspection of &lt;code&gt;server.js&lt;/code&gt; showed that the application required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;helmet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;helmet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;socket.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winston&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;winston&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the original dependency tree only contained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cors
dotenv
express
mongoose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three runtime dependencies were missing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helmet
socket.io
winston
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mismatch caused PM2 to continuously restart the application.&lt;/p&gt;

&lt;p&gt;At one point, the process had accumulated millions of restart attempts.&lt;/p&gt;

&lt;p&gt;This is an important operational lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A process manager can keep a process alive, but it cannot make an invalid runtime healthy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PM2 was correctly restarting the process. The actual problem was an incomplete dependency graph.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Runtime Dependency Repair
&lt;/h1&gt;

&lt;p&gt;The missing modules were installed and persisted into &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting dependency set included:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.8.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dotenv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^17.4.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.18.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"helmet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.3.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mongoose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^9.9.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"socket.io"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.8.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"winston"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.19.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Module resolution was then explicitly verified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OK: helmet
OK: socket.io
OK: winston
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After repairing the dependency tree, the UrbanLab backend successfully initialized.&lt;/p&gt;

&lt;p&gt;Runtime output confirmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server started on port 5002
MongoDB connected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The health endpoint returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I-ECO-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mongodb"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"connected"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More importantly, PM2 stability was tested over time.&lt;/p&gt;

&lt;p&gt;The PID remained unchanged and the restart counter stopped increasing.&lt;/p&gt;

&lt;p&gt;This confirmed that the restart loop had actually been eliminated rather than temporarily hidden.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. PM2 Runtime Stabilization
&lt;/h1&gt;

&lt;p&gt;The next step was validating the persistent process topology.&lt;/p&gt;

&lt;p&gt;The VPS currently runs multiple independently supervised services, including:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cloudflared
myzubster-sepolia-e2e
myzubster-social
myzubster-web
urbanlab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the Sepolia backend, we verified that the process remained online after restart and that a stable PID was assigned.&lt;/p&gt;

&lt;p&gt;After the final restart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myzubster-sepolia-e2e → online
PID → 1152840
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The active PM2 process list was then persisted using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/root/.pm2/dump.pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This matters because runtime recovery must survive more than an individual shell session.&lt;/p&gt;

&lt;p&gt;A service that works until the VPS reboots is not a completed deployment.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. MongoDB Connectivity
&lt;/h1&gt;

&lt;p&gt;Database connectivity was validated alongside application startup.&lt;/p&gt;

&lt;p&gt;The backend reported:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MongoDB connected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the public health path remained responsive.&lt;/p&gt;

&lt;p&gt;The architecture also contains a database gate around routes requiring persistence.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP request
      │
      ▼
requireDatabase
      │
      ├── MongoDB available ──► route handler
      │
      └── MongoDB unavailable ──► HTTP 503
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents database-dependent operations from silently executing against an unavailable persistence layer.&lt;/p&gt;

&lt;p&gt;Instead, failure becomes explicit and observable.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. Google OAuth Investigation
&lt;/h1&gt;

&lt;p&gt;The next major objective was Google OAuth.&lt;/p&gt;

&lt;p&gt;The public provider endpoint confirmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"providers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"facebook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This result was reproduced against both the local backend and the public Sepolia endpoint.&lt;/p&gt;

&lt;p&gt;Therefore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google   → enabled
GitHub   → disabled
Facebook → disabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provider configuration itself was not the primary problem.&lt;/p&gt;

&lt;p&gt;The investigation moved deeper into the OAuth callback lifecycle.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. OAuth Callback Observability
&lt;/h1&gt;

&lt;p&gt;Temporary instrumentation was introduced at multiple points in the OAuth flow.&lt;/p&gt;

&lt;p&gt;The goal was to answer a specific question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does Google's callback actually reach the intended backend process with the expected OAuth parameters?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instrumentation captured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;method
path
host
x-forwarded-host
x-forwarded-proto
code presence
state presence
error presence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A clean callback produced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HTTP-GOOGLE-CALLBACK] {
  method: 'GET',
  path: '/api/auth/social/google/callback',
  host: '127.0.0.1:5010',
  forwardedHost: null,
  forwardedProto: 'https',
  hasCode: true,
  hasState: true,
  hasError: false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This result was extremely useful.&lt;/p&gt;

&lt;p&gt;It demonstrated that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Google reached the callback.&lt;/li&gt;
&lt;li&gt;The callback reached the Node.js backend.&lt;/li&gt;
&lt;li&gt;The authorization &lt;code&gt;code&lt;/code&gt; was present.&lt;/li&gt;
&lt;li&gt;OAuth &lt;code&gt;state&lt;/code&gt; was present.&lt;/li&gt;
&lt;li&gt;Google did not return an OAuth-level error.&lt;/li&gt;
&lt;li&gt;HTTPS information survived the proxy path.&lt;/li&gt;
&lt;li&gt;The backend was listening behind the expected local port.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The effective request path is therefore approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google
   │
   ▼
https://sepolia.myzubster.com
   │
   ▼
reverse proxy / tunnel
   │
   ▼
127.0.0.1:5010
   │
   ▼
Express
   │
   ▼
/api/auth/social/google/callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That eliminated several possible failure classes at once.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. OAuth Session Error Isolation
&lt;/h1&gt;

&lt;p&gt;During investigation, an earlier callback produced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[OAUTH-CALLBACK-ERROR] {
  provider: 'google',
  message: 'Sessione OAuth mancante. Riavvia il login dal pulsante MyZubster.'
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of assuming the provider itself was broken, logs were reset and the authentication flow was reproduced from a clean state.&lt;/p&gt;

&lt;p&gt;The backend logs were truncated intentionally before the next test so historical errors could not be confused with current behavior.&lt;/p&gt;

&lt;p&gt;After the clean test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR LOG
empty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while the output log showed the callback arriving correctly.&lt;/p&gt;

&lt;p&gt;This distinction is operationally important.&lt;/p&gt;

&lt;p&gt;Historical log entries are not evidence of a current failure.&lt;/p&gt;

&lt;p&gt;For authentication debugging, each reproduction should ideally have a clearly bounded observation window.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. Temporary Instrumentation Cleanup
&lt;/h1&gt;

&lt;p&gt;Once the callback path had been verified, temporary HTTP-level debugging was removed from &lt;code&gt;server.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The diagnostic block used during investigation was intentionally not kept as permanent production code.&lt;/p&gt;

&lt;p&gt;Syntax validation was then performed again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--check&lt;/span&gt; server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend syntax OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temporary backup files created during the investigation were also identified and removed from the Git working tree.&lt;/p&gt;

&lt;p&gt;This left the repository in a controlled state instead of accidentally committing debug artifacts.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. Permanent OAuth Error Logging
&lt;/h1&gt;

&lt;p&gt;One diagnostic improvement was intentionally retained.&lt;/p&gt;

&lt;p&gt;Previously, callback errors were handled essentially as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;redirectError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This made failures visible to the browser but provided limited server-side evidence.&lt;/p&gt;

&lt;p&gt;The callback now records a concise structured error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[OAUTH-CALLBACK-ERROR]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;redirectError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives operators useful information without intentionally logging OAuth tokens or credentials.&lt;/p&gt;

&lt;p&gt;The objective is not maximum logging.&lt;/p&gt;

&lt;p&gt;The objective is &lt;strong&gt;minimum sufficient observability&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  10. Secret Hygiene
&lt;/h1&gt;

&lt;p&gt;Before committing anything, the working tree was explicitly inspected.&lt;/p&gt;

&lt;p&gt;Special attention was given to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
.env.local
.env.*.local
frontend/.env
backend/.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository's &lt;code&gt;.gitignore&lt;/code&gt; already excludes these files.&lt;/p&gt;

&lt;p&gt;Staging was also checked independently to ensure no environment file had entered the Git index.&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No ENV files staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The modified files were inspected for obvious credentials, tokens or secrets before commit.&lt;/p&gt;

&lt;p&gt;No evident secret was found in the intended patch.&lt;/p&gt;

&lt;p&gt;This is particularly important for OAuth work because debugging often involves credentials, authorization codes and provider configuration.&lt;/p&gt;

&lt;p&gt;Those values must never become part of the repository history.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Frontend Proxy Investigation
&lt;/h1&gt;

&lt;p&gt;During troubleshooting, a Create React App development proxy was considered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createProxyMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http-proxy-middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;createProxyMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:5010&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, inspection showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-proxy-middleware → not installed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than introducing an unnecessary dependency or accidentally changing the deployment topology, the temporary proxy experiment was removed.&lt;/p&gt;

&lt;p&gt;This kept the final change set focused on the problem actually being solved.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Repository Cleanup
&lt;/h1&gt;

&lt;p&gt;Several investigation backups existed temporarily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server.js.before-oauth-http-debug-...
server.js.oauth-working-...
socialAuthController.js.backup-debug
socialAuthController.js.before-google-token-debug
socialAuthController.js.before-oauth-debug
socialAuthController.js.oauth-working-...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These files were useful during live debugging but were not appropriate repository artifacts.&lt;/p&gt;

&lt;p&gt;They were removed before the final commit.&lt;/p&gt;

&lt;p&gt;After cleanup, the Git working tree contained only the intended source modification.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. The Final Commit
&lt;/h1&gt;

&lt;p&gt;The OAuth diagnostics improvement was isolated into a dedicated commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;02f06f22
fix(auth): improve OAuth callback error logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commit modified only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/controllers/socialAuthController.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The patch consisted of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;19 insertions
2 deletions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was deliberate.&lt;/p&gt;

&lt;p&gt;Infrastructure debugging often touches many files temporarily. A good final commit should contain the solution, not the entire debugging history.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. Branch Isolation
&lt;/h1&gt;

&lt;p&gt;The work was performed on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vps/sepolia-e2e-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The branch was pushed to the developer fork:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;danieldirimini-myzubster/myzubster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and configured to track:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin/vps/sepolia-e2e-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository was clean after the push.&lt;/p&gt;

&lt;p&gt;This provides a reproducible boundary between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;production/main development
        │
        └── isolated Sepolia validation branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than making ad-hoc changes directly against the canonical branch.&lt;/p&gt;




&lt;h1&gt;
  
  
  15. Pull Request Created
&lt;/h1&gt;

&lt;p&gt;The work was submitted upstream as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PR #1394
fix(auth): improve OAuth callback error logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PR targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test/eth-sepolia-e2e-validation-20260925
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vps/sepolia-e2e-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PR currently contains one commit and one changed file.&lt;/p&gt;

&lt;p&gt;GitHub reports the PR as mergeable, meaning there is currently no Git merge conflict blocking integration.&lt;/p&gt;

&lt;p&gt;The PR was intentionally scoped to the OAuth callback diagnostics discovered during Sepolia E2E validation.&lt;/p&gt;




&lt;h1&gt;
  
  
  16. CI/CD Evidence Gate
&lt;/h1&gt;

&lt;p&gt;Opening the PR triggered the project's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Continuous Evidence Gate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline performs substantially more than a basic syntax check.&lt;/p&gt;

&lt;p&gt;The observed stages include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set up job
        │
        ▼
Checkout
        │
        ▼
Set up Node
        │
        ▼
Install exact dependency tree
        │
        ▼
Run tests
        │
        ▼
Run vulnerability audit
        │
        ▼
Generate CycloneDX SBOM
        │
        ▼
Build evidence manifest
        │
        ▼
Upload auditable evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the latest inspection, environment setup, checkout, Node setup and exact dependency installation had completed successfully.&lt;/p&gt;

&lt;p&gt;The test stage was running.&lt;/p&gt;

&lt;p&gt;This is an important architectural direction for MyZubster.&lt;/p&gt;

&lt;p&gt;A successful change should eventually mean more than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"It works on the VPS."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source
  +
tests
  +
dependency reproducibility
  +
security audit
  +
SBOM
  +
evidence manifest
  +
deployment validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  17. Sepolia E2E Work Already Present
&lt;/h1&gt;

&lt;p&gt;The branch sits on top of a larger Sepolia payment-validation effort.&lt;/p&gt;

&lt;p&gt;Relevant preceding commits include work for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;real-wallet Sepolia E2E harness
Sepolia E2E verifier
Sepolia E2E runbook
manual Sepolia evidence workflow
independent payment verifier
Sepolia ETH sandbox lifecycle
MetaMask payment UI tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means OAuth debugging is not an isolated feature.&lt;/p&gt;

&lt;p&gt;It is part of a broader effort to establish a real sandbox where identity, wallet interaction, payment execution and backend persistence can eventually be tested together.&lt;/p&gt;

&lt;p&gt;The target is a complete lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 │
 ▼
Authentication
 │
 ▼
MyZubster Identity
 │
 ▼
Wallet
 │
 ▼
Marketplace / Service
 │
 ▼
Sepolia Transaction
 │
 ▼
Blockchain Verification
 │
 ▼
Backend Persistence
 │
 ▼
Application State Transition
 │
 ▼
Auditable Evidence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  18. What We Have Successfully Proven
&lt;/h1&gt;

&lt;p&gt;At this stage, we have evidence for several important properties of the environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Runtime
&lt;/h3&gt;

&lt;p&gt;Node.js services can remain stable under PM2 after dependency correction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;MongoDB connectivity is available to the relevant backend environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Public routing
&lt;/h3&gt;

&lt;p&gt;The Sepolia backend can be reached through the public endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth provider discovery
&lt;/h3&gt;

&lt;p&gt;Google is reported as enabled by both local and public provider endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth transport
&lt;/h3&gt;

&lt;p&gt;Google's callback reaches the intended backend with both &lt;code&gt;code&lt;/code&gt; and &lt;code&gt;state&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy behavior
&lt;/h3&gt;

&lt;p&gt;The callback reaches the internal service through the HTTPS-facing infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error observability
&lt;/h3&gt;

&lt;p&gt;OAuth callback failures now produce concise structured server-side diagnostics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secret handling
&lt;/h3&gt;

&lt;p&gt;Environment files were excluded from staging and were not intentionally committed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Git hygiene
&lt;/h3&gt;

&lt;p&gt;Temporary debugging artifacts were removed before the final commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branch isolation
&lt;/h3&gt;

&lt;p&gt;The work exists on a dedicated E2E validation branch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upstream integration
&lt;/h3&gt;

&lt;p&gt;A dedicated pull request now exists for review.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI evidence
&lt;/h3&gt;

&lt;p&gt;The upstream CI evidence pipeline is executing against the exact commit submitted for integration.&lt;/p&gt;




&lt;h1&gt;
  
  
  19. What Is Not Finished Yet
&lt;/h1&gt;

&lt;p&gt;This distinction is critical.&lt;/p&gt;

&lt;p&gt;We have made substantial progress, but this does &lt;strong&gt;not&lt;/strong&gt; yet mean that the entire MyZubster production architecture is complete.&lt;/p&gt;

&lt;p&gt;Several layers still require additional work.&lt;/p&gt;

&lt;h2&gt;
  
  
  19.1 CI Must Complete
&lt;/h2&gt;

&lt;p&gt;The active evidence gate must finish successfully.&lt;/p&gt;

&lt;p&gt;In particular:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tests
vulnerability audit
SBOM generation
evidence manifest
evidence upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;need final confirmation.&lt;/p&gt;

&lt;p&gt;A locally working OAuth callback is not sufficient reason by itself to merge.&lt;/p&gt;




&lt;h2&gt;
  
  
  19.2 OAuth Needs Full Application-Level Verification
&lt;/h2&gt;

&lt;p&gt;Transport-level success has been demonstrated.&lt;/p&gt;

&lt;p&gt;The next level is proving the entire application state transition.&lt;/p&gt;

&lt;p&gt;We want to validate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google authorization
      │
      ▼
callback
      │
      ▼
provider profile retrieval
      │
      ▼
verified MyZubster account
      │
      ▼
social-login result ticket
      │
      ▼
frontend redirect
      │
      ▼
ticket exchange
      │
      ▼
authenticated frontend session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each boundary should have explicit success and failure tests.&lt;/p&gt;




&lt;h1&gt;
  
  
  20. OAuth State and Session Hardening
&lt;/h1&gt;

&lt;p&gt;The earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sessione OAuth mancante
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;error demonstrates why OAuth state management deserves dedicated tests.&lt;/p&gt;

&lt;p&gt;The system should explicitly test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;valid state
missing state
expired state
replayed state
invalid state
provider mismatch
callback without code
provider-denied authorization
expired login result ticket
reused login result ticket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The long-term goal should be to make OAuth state transitions deterministic and testable rather than dependent on manual browser observation.&lt;/p&gt;




&lt;h1&gt;
  
  
  21. GitHub and Facebook Providers
&lt;/h1&gt;

&lt;p&gt;Provider discovery currently reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;google   = true
github   = false
facebook = false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore Google should be treated as the currently validated provider.&lt;/p&gt;

&lt;p&gt;GitHub and Facebook should not be described as completed authentication integrations until they are enabled and tested through equivalent E2E flows.&lt;/p&gt;

&lt;p&gt;GitHub deserves particular attention because the controller already contains logic related to GitHub automation authorization and encrypted access-token storage.&lt;/p&gt;

&lt;p&gt;That path should eventually receive separate security and authorization tests.&lt;/p&gt;




&lt;h1&gt;
  
  
  22. Payment E2E Completion
&lt;/h1&gt;

&lt;p&gt;The broader objective is not only authentication.&lt;/p&gt;

&lt;p&gt;The Sepolia environment exists to validate real application flows against Ethereum's Sepolia test network.&lt;/p&gt;

&lt;p&gt;The desired payment lifecycle is approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Buyer
  │
  ▼
MetaMask
  │
  ▼
Sepolia transaction
  │
  ▼
transaction hash
  │
  ▼
MyZubster backend
  │
  ▼
chain verification
  │
  ├── wrong chain      → reject
  ├── wrong receiver   → reject
  ├── wrong amount     → reject
  ├── failed tx        → reject
  └── valid payment    → accept
                            │
                            ▼
                     persist state
                            │
                            ▼
                     marketplace order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important property is that the backend must verify blockchain truth independently.&lt;/p&gt;

&lt;p&gt;The browser must never be considered authoritative merely because it reports a successful transaction.&lt;/p&gt;




&lt;h1&gt;
  
  
  23. Idempotency
&lt;/h1&gt;

&lt;p&gt;Payment verification must also be idempotent.&lt;/p&gt;

&lt;p&gt;A transaction hash should not be usable to settle multiple orders accidentally.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TX_HASH = 0xabc...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;must transition from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unseen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verified / associated with order X
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;only once according to the application's business rules.&lt;/p&gt;

&lt;p&gt;Repeated requests must not produce repeated financial state transitions.&lt;/p&gt;

&lt;p&gt;This needs dedicated automated coverage.&lt;/p&gt;




&lt;h1&gt;
  
  
  24. Chain Finality Strategy
&lt;/h1&gt;

&lt;p&gt;A production-grade blockchain integration also needs a defined confirmation policy.&lt;/p&gt;

&lt;p&gt;A transaction being visible is not necessarily equivalent to a transaction being final enough for the application's risk model.&lt;/p&gt;

&lt;p&gt;The architecture therefore needs an explicit rule such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transaction found
      │
      ▼
receipt successful
      │
      ▼
correct chain
      │
      ▼
correct recipient
      │
      ▼
correct value
      │
      ▼
N confirmations
      │
      ▼
settled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact confirmation threshold should be documented and configurable.&lt;/p&gt;




&lt;h1&gt;
  
  
  25. Observability Architecture
&lt;/h1&gt;

&lt;p&gt;The OAuth investigation demonstrated the value of structured logs.&lt;/p&gt;

&lt;p&gt;The next step should be extending that principle consistently.&lt;/p&gt;

&lt;p&gt;Instead of scattered strings such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;something failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;important events should use structured records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oauth_callback_failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"state_missing"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For blockchain verification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment_verification"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chainId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11155111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"txHash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"verified"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sensitive values must remain excluded.&lt;/p&gt;




&lt;h1&gt;
  
  
  26. Correlation IDs
&lt;/h1&gt;

&lt;p&gt;One particularly useful improvement would be request correlation.&lt;/p&gt;

&lt;p&gt;Today an OAuth operation crosses multiple systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;browser
Google
reverse proxy
Express
MongoDB
frontend redirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A generated correlation identifier would allow the same logical operation to be traced across those boundaries.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requestId=oauth_01H...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;could appear in every safe diagnostic event related to that authentication attempt.&lt;/p&gt;

&lt;p&gt;This would dramatically reduce debugging time without requiring verbose or sensitive logs.&lt;/p&gt;




&lt;h1&gt;
  
  
  27. Metrics and Alerting
&lt;/h1&gt;

&lt;p&gt;PM2 status is useful operationally, but long-term infrastructure should expose machine-consumable metrics.&lt;/p&gt;

&lt;p&gt;Useful signals include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP request rate
HTTP 4xx rate
HTTP 5xx rate
OAuth success rate
OAuth failure rate
MongoDB connection failures
payment verification failures
RPC latency
blockchain RPC errors
process restart count
memory usage
event-loop lag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The millions of historical UrbanLab restarts illustrate why this matters.&lt;/p&gt;

&lt;p&gt;A restart loop should generate an alert quickly rather than being discovered manually.&lt;/p&gt;




&lt;h1&gt;
  
  
  28. Dependency Reproducibility
&lt;/h1&gt;

&lt;p&gt;The initial UrbanLab incident also revealed a broader engineering requirement.&lt;/p&gt;

&lt;p&gt;The repository must be sufficient to reconstruct the runtime.&lt;/p&gt;

&lt;p&gt;That means the following must stay synchronized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source imports
package.json
lockfile
CI dependency installation
deployment dependency installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the application imports a package that is absent from the dependency manifest, the build should fail before deployment.&lt;/p&gt;

&lt;p&gt;This is precisely the type of issue CI should prevent.&lt;/p&gt;




&lt;h1&gt;
  
  
  29. Deployment Reproducibility
&lt;/h1&gt;

&lt;p&gt;The long-term deployment goal should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git commit
    │
    ▼
CI validation
    │
    ▼
immutable build artifact
    │
    ▼
staging / Sepolia
    │
    ▼
E2E validation
    │
    ▼
promotion
    │
    ▼
production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSH into server
    │
    ▼
edit files
    │
    ▼
npm install
    │
    ▼
restart PM2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manual VPS work is useful during investigation.&lt;/p&gt;

&lt;p&gt;It should not remain the final deployment architecture.&lt;/p&gt;




&lt;h1&gt;
  
  
  30. Infrastructure as Code
&lt;/h1&gt;

&lt;p&gt;Another logical next step is representing deployment configuration as code.&lt;/p&gt;

&lt;p&gt;The desired state of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Node version
PM2 processes
environment requirements
reverse proxy
ports
health checks
MongoDB connectivity
Cloudflare tunnel
service restart behavior
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should be reproducible.&lt;/p&gt;

&lt;p&gt;The goal is to be able to rebuild the Sepolia environment from documented configuration instead of relying on historical knowledge of the current VPS.&lt;/p&gt;




&lt;h1&gt;
  
  
  31. Environment Separation
&lt;/h1&gt;

&lt;p&gt;MyZubster should maintain strict boundaries between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development
test
Sepolia staging
production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each environment should have independent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;credentials
OAuth configuration
database
RPC endpoints
wallet configuration
frontend origin
backend origin
logging policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Sepolia environment should never accidentally consume production credentials or production payment configuration.&lt;/p&gt;




&lt;h1&gt;
  
  
  32. Security Model
&lt;/h1&gt;

&lt;p&gt;Authentication and blockchain payments both operate on trust boundaries.&lt;/p&gt;

&lt;p&gt;The backend must remain authoritative.&lt;/p&gt;

&lt;p&gt;The browser may claim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Google authenticated me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server must verify the provider result.&lt;/p&gt;

&lt;p&gt;The browser may claim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I paid this order.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server must independently verify the chain.&lt;/p&gt;

&lt;p&gt;The browser may claim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This wallet belongs to me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ownership should be demonstrated cryptographically when required.&lt;/p&gt;

&lt;p&gt;This leads to a simple architectural principle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client claims intent.
Server verifies truth.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  33. Target Architecture
&lt;/h1&gt;

&lt;p&gt;The system we are working toward can be represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────────┐
                    │      Browser        │
                    │ React / Web Client  │
                    └─────────┬───────────┘
                              │
                              ▼
                    ┌─────────────────────┐
                    │ Edge / Proxy Layer  │
                    │ TLS / Cloudflare    │
                    └─────────┬───────────┘
                              │
                              ▼
                ┌─────────────────────────────┐
                │      MyZubster API          │
                │ Node.js / Express           │
                │                             │
                │ Auth                        │
                │ Marketplace                 │
                │ Payments                    │
                │ Wallet                      │
                │ Zorgax                      │
                │ Metaverse                   │
                └──────┬───────────┬──────────┘
                       │           │
              ┌────────▼───┐   ┌───▼──────────────┐
              │  MongoDB   │   │ Blockchain RPC   │
              │ persistence│   │ Sepolia / Mainnet│
              └────────────┘   └──────────────────┘

                       External Trust Providers
                              │
                 ┌────────────┼────────────┐
                 ▼            ▼            ▼
              Google        GitHub      Facebook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Around all of this should exist another layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CI
security audit
SBOM
tests
logs
metrics
deployment evidence
rollback capability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That operational layer is as important as the application itself.&lt;/p&gt;




&lt;h1&gt;
  
  
  34. Definition of Done
&lt;/h1&gt;

&lt;p&gt;For this architecture, "done" should eventually have a strict technical meaning.&lt;/p&gt;

&lt;p&gt;A feature should not be considered complete merely because a browser demonstration succeeds.&lt;/p&gt;

&lt;p&gt;A stronger definition is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation complete
        +
unit tests
        +
integration tests
        +
E2E tests
        +
security checks
        +
dependency audit
        +
no committed secrets
        +
observability
        +
documented deployment
        +
documented rollback
        +
reproducible environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For payment-related functionality, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;independent on-chain verification
idempotency
chain validation
recipient validation
amount validation
confirmation policy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For OAuth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;state validation
provider validation
ticket expiration
replay protection
safe logging
failure-path tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  35. Immediate Engineering Roadmap
&lt;/h1&gt;

&lt;p&gt;The next development sequence should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PR #1394
   │
   ▼
CI Evidence Gate passes
   │
   ▼
review / merge
   │
   ▼
full Google OAuth E2E automation
   │
   ▼
OAuth state/replay/error tests
   │
   ▼
Sepolia payment lifecycle validation
   │
   ▼
idempotency + confirmation policy
   │
   ▼
structured observability
   │
   ▼
deployment reproducibility
   │
   ▼
staging promotion gate
   │
   ▼
production-readiness review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, additional providers and higher-level platform features can be introduced on top of a much stronger foundation.&lt;/p&gt;




&lt;h1&gt;
  
  
  36. Where We Want to Arrive
&lt;/h1&gt;

&lt;p&gt;The ultimate objective is not simply to have Google Login working or to send an ETH transaction on Sepolia.&lt;/p&gt;

&lt;p&gt;Those are individual capabilities.&lt;/p&gt;

&lt;p&gt;The real target is a platform where a complete operation can be trusted from beginning to end.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User authenticates
        │
        ▼
Identity is verified
        │
        ▼
User enters marketplace
        │
        ▼
Wallet is connected
        │
        ▼
Transaction is initiated
        │
        ▼
Blockchain records transaction
        │
        ▼
Backend independently verifies transaction
        │
        ▼
Database records authoritative state
        │
        ▼
Application unlocks purchased resource/service
        │
        ▼
Evidence remains auditable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the entire system should be deployable again from source without depending on undocumented manual VPS state.&lt;/p&gt;

&lt;p&gt;That is the engineering milestone we are moving toward:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a reproducible, observable, security-conscious and independently verifiable MyZubster platform spanning Web2 identity, persistent application state and Web3 settlement.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Current Status
&lt;/h1&gt;

&lt;p&gt;At the end of this development cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UrbanLab runtime dependency failure     → FIXED
UrbanLab PM2 restart loop               → FIXED
MongoDB runtime connectivity            → VERIFIED
Sepolia backend public endpoint         → VERIFIED
Google provider configuration           → VERIFIED
Google callback transport               → VERIFIED
OAuth code/state arrival                → VERIFIED
Temporary OAuth instrumentation         → REMOVED
Persistent OAuth error diagnostics      → IMPLEMENTED
Secret/staging hygiene                  → VERIFIED
Temporary backup files                  → CLEANED
Dedicated Git commit                    → CREATED
Developer branch                        → PUSHED
Upstream PR                             → OPEN
PR mergeability                         → CONFIRMED
Continuous Evidence Gate                → RUNNING
Full production readiness               → NOT YET COMPLETE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important result is not any individual fix.&lt;/p&gt;

&lt;p&gt;We now have a clearer boundary between &lt;strong&gt;what has actually been proven&lt;/strong&gt;, &lt;strong&gt;what remains under validation&lt;/strong&gt;, and &lt;strong&gt;what engineering work is required to transform the Sepolia environment into a reliable promotion gate for MyZubster production releases&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>oauth</category>
      <category>blockchain</category>
      <category>node</category>
      <category>devops</category>
    </item>
    <item>
      <title>🚀 **MyZubster Development Update — Sepolia E2E, Google OAuth &amp; I-ECO-01 Infrastructure Stabilization**</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Sat, 26 Sep 2026 14:15:47 +0000</pubDate>
      <link>https://dev.to/danielioni/myzubster-development-update-sepolia-e2e-google-oauth-i-eco-01-infrastructure-jfm</link>
      <guid>https://dev.to/danielioni/myzubster-development-update-sepolia-e2e-google-oauth-i-eco-01-infrastructure-jfm</guid>
      <description>&lt;p&gt;🚀 &lt;strong&gt;MyZubster Development Update — Sepolia E2E, Google OAuth &amp;amp; I-ECO-01 Infrastructure Stabilization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today we completed a major infrastructure stabilization phase across the &lt;strong&gt;MyZubster Sepolia E2E environment&lt;/strong&gt; and the connected &lt;strong&gt;I-ECO-01 / UrbanLab Escrow infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The work focused on three critical areas: Google OAuth authentication, PM2 runtime configuration, and the stability of the I-ECO-01 Node.js service.&lt;/p&gt;

&lt;p&gt;The result is a significantly cleaner and more stable development environment, with the main backend services running correctly and several previously hidden configuration issues identified and resolved.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Google OAuth — End-to-End Backend Flow Completed
&lt;/h2&gt;

&lt;p&gt;A major part of today's work was dedicated to validating the Google authentication flow used by MyZubster.&lt;/p&gt;

&lt;p&gt;The OAuth implementation was inspected from the initial authentication request all the way through the Google callback and backend processing.&lt;/p&gt;

&lt;p&gt;We verified the public authentication endpoint and confirmed that MyZubster correctly generates the Google authorization request with the expected Client ID and callback URL.&lt;/p&gt;

&lt;p&gt;The Sepolia callback is now correctly configured as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://sepolia.myzubster.com/api/auth/social/google/callback&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;During debugging, the backend was instrumented with additional OAuth tracing so that each important stage of the authentication flow could be observed directly from the PM2 logs.&lt;/p&gt;

&lt;p&gt;The callback successfully reached the MyZubster backend with both the authorization &lt;code&gt;code&lt;/code&gt; and signed &lt;code&gt;state&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;An initial failure was then isolated during the token exchange stage.&lt;/p&gt;

&lt;p&gt;Google returned:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;401 invalid_client&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;with an indication that the configured client secret was invalid.&lt;/p&gt;

&lt;p&gt;This allowed us to distinguish the problem from several other possible causes such as an incorrect callback URL, broken routing, invalid OAuth state, Cloudflare routing, frontend behavior, or an unavailable authentication provider.&lt;/p&gt;

&lt;p&gt;After correcting the OAuth configuration, the backend successfully completed the Google authentication process.&lt;/p&gt;

&lt;p&gt;The final trace reached:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OAUTH-CALLBACK-ENTER&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;followed by:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OAUTH-CALLBACK-SUCCESS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This confirms that the Google OAuth backend flow is operational.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Sepolia Runtime URL Configuration
&lt;/h2&gt;

&lt;p&gt;Another issue was discovered after successful Google authentication.&lt;/p&gt;

&lt;p&gt;Although the &lt;code&gt;.env&lt;/code&gt; configuration correctly referenced:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://sepolia.myzubster.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;the running PM2 process was still capable of using stale runtime environment values.&lt;/p&gt;

&lt;p&gt;This caused successful authentication attempts to redirect users toward an older Vercel deployment instead of the intended Sepolia environment.&lt;/p&gt;

&lt;p&gt;The runtime configuration was inspected at multiple levels:&lt;/p&gt;

&lt;p&gt;• &lt;code&gt;.env&lt;/code&gt; configuration&lt;br&gt;&lt;br&gt;
• Node.js + dotenv environment&lt;br&gt;&lt;br&gt;
• PM2 process environment&lt;br&gt;&lt;br&gt;
• OAuth callback generation&lt;br&gt;&lt;br&gt;
• frontend redirect generation&lt;br&gt;&lt;br&gt;
• running process configuration&lt;/p&gt;

&lt;p&gt;The Sepolia runtime was then explicitly aligned so that the active backend process uses:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FRONTEND_URL=https://sepolia.myzubster.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PUBLIC_APP_URL=https://sepolia.myzubster.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GATEWAY_PUBLIC_URL=https://sepolia.myzubster.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The active PM2 process was verified directly after the update.&lt;/p&gt;

&lt;p&gt;This was important because having the correct value inside &lt;code&gt;.env&lt;/code&gt; is not sufficient if a long-running process manager is still carrying older environment state.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏭 I-ECO-01 / UrbanLab Investigation
&lt;/h2&gt;

&lt;p&gt;During the infrastructure review we also discovered a serious stability problem affecting the &lt;strong&gt;I-ECO-01 / UrbanLab service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The PM2 process had accumulated more than &lt;strong&gt;6.5 million restarts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Despite appearing as &lt;code&gt;online&lt;/code&gt; in PM2, the process was continuously crashing and being restarted.&lt;/p&gt;

&lt;p&gt;This is an important operational lesson: an &lt;code&gt;online&lt;/code&gt; status alone does not necessarily mean that a service is healthy.&lt;/p&gt;

&lt;p&gt;We inspected:&lt;/p&gt;

&lt;p&gt;• PM2 process configuration&lt;br&gt;&lt;br&gt;
• executable path&lt;br&gt;&lt;br&gt;
• working directory&lt;br&gt;&lt;br&gt;
• restart counter&lt;br&gt;&lt;br&gt;
• process PID&lt;br&gt;&lt;br&gt;
• CPU usage&lt;br&gt;&lt;br&gt;
• Node.js error logs&lt;br&gt;&lt;br&gt;
• package dependencies&lt;br&gt;&lt;br&gt;
• server entrypoint&lt;br&gt;&lt;br&gt;
• health endpoint&lt;/p&gt;

&lt;p&gt;The active process was confirmed to be executing:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/opt/I-ECO-01/server.js&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔎 Root Cause Identified
&lt;/h2&gt;

&lt;p&gt;The crash loop was traced to missing Node.js dependencies.&lt;/p&gt;

&lt;p&gt;The I-ECO-01 &lt;code&gt;server.js&lt;/code&gt; required several modules that were not declared or installed in the project dependencies.&lt;/p&gt;

&lt;p&gt;The missing packages were:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helmet&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;socket.io&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;winston&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The server was failing immediately at:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;require('helmet')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MODULE_NOT_FOUND&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because PM2 was configured to automatically restart the process, every crash immediately triggered another launch attempt.&lt;/p&gt;

&lt;p&gt;This created the extremely high restart count.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Dependency Repair
&lt;/h2&gt;

&lt;p&gt;The complete set of external dependencies referenced by the server entrypoint was inspected before modifying the project.&lt;/p&gt;

&lt;p&gt;The missing dependencies were then installed and added to &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting dependency set now includes the required server components:&lt;/p&gt;

&lt;p&gt;• Express&lt;br&gt;&lt;br&gt;
• CORS&lt;br&gt;&lt;br&gt;
• dotenv&lt;br&gt;&lt;br&gt;
• Mongoose&lt;br&gt;&lt;br&gt;
• Helmet&lt;br&gt;&lt;br&gt;
• Socket.IO&lt;br&gt;&lt;br&gt;
• Winston&lt;/p&gt;

&lt;p&gt;Each newly installed package was then independently loaded through Node.js to confirm that module resolution was working correctly.&lt;/p&gt;

&lt;p&gt;All three previously missing modules passed the verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ UrbanLab Restart Loop Resolved
&lt;/h2&gt;

&lt;p&gt;After repairing the dependencies, the UrbanLab service was restarted and monitored.&lt;/p&gt;

&lt;p&gt;The server successfully initialized the Escrow controller and started listening on port &lt;code&gt;5002&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MongoDB also connected successfully.&lt;/p&gt;

&lt;p&gt;Most importantly, we performed a timed stability test rather than relying only on PM2's reported status.&lt;/p&gt;

&lt;p&gt;Before the test:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PID: 1026452&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Restart count: 6548384&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After waiting 15 seconds:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PID: 1026452&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Restart count: 6548384&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The PID remained unchanged and the restart counter did not increase.&lt;/p&gt;

&lt;p&gt;This confirms that the restart loop was successfully stopped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UrbanLab is now running as a stable process rather than continuously crashing and restarting.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ❤️ I-ECO-01 Health Check
&lt;/h2&gt;

&lt;p&gt;The service health endpoint was tested directly on the VPS:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://127.0.0.1:5002/health&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The service returned a healthy response reporting:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;status: ok&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;service: I-ECO-01&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mongodb: connected&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This provides direct application-level confirmation that the service is alive and its database connection is operational.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Escrow Multisig Service
&lt;/h2&gt;

&lt;p&gt;The I-ECO-01 Escrow controller is also initializing successfully.&lt;/p&gt;

&lt;p&gt;The active configuration reports:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multisig threshold:&lt;/strong&gt; 2/3&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Escrow timeout:&lt;/strong&gt; 24 hours&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Escrow fee:&lt;/strong&gt; 0.5%&lt;/p&gt;

&lt;p&gt;The service exposes its Escrow API and initializes WebSocket support alongside the HTTP server.&lt;/p&gt;

&lt;p&gt;This gives the I-ECO-01 environment the foundation required for the next stages of escrow and transaction-flow testing.&lt;/p&gt;




&lt;h2&gt;
  
  
  📡 WebSocket Infrastructure
&lt;/h2&gt;

&lt;p&gt;Socket.IO is now installed and successfully loaded by the server.&lt;/p&gt;

&lt;p&gt;The service initializes WebSocket functionality together with the main HTTP server on port &lt;code&gt;5002&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This prepares the infrastructure for real-time communication between the backend and connected MyZubster / UrbanLab components.&lt;/p&gt;




&lt;h2&gt;
  
  
  🍃 MongoDB Connectivity
&lt;/h2&gt;

&lt;p&gt;MongoDB connectivity was verified after the dependency repair.&lt;/p&gt;

&lt;p&gt;The server reports:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MongoDB connected&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and the health endpoint independently reports:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mongodb: connected&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is particularly important because application startup alone would not demonstrate that the persistence layer is actually available.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ PM2 &amp;amp; VPS Infrastructure
&lt;/h2&gt;

&lt;p&gt;The broader VPS process environment was also inspected.&lt;/p&gt;

&lt;p&gt;The system currently includes services for:&lt;/p&gt;

&lt;p&gt;• MyZubster Sepolia backend&lt;br&gt;&lt;br&gt;
• MyZubster Sepolia frontend&lt;br&gt;&lt;br&gt;
• MyZubster Social&lt;br&gt;&lt;br&gt;
• MyZubster Web&lt;br&gt;&lt;br&gt;
• UrbanLab / I-ECO-01&lt;br&gt;&lt;br&gt;
• Cloudflared&lt;/p&gt;

&lt;p&gt;PM2 itself is managed through systemd using the &lt;code&gt;pm2-root&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;This means the process manager is integrated with the VPS boot environment rather than existing only inside an interactive shell session.&lt;/p&gt;

&lt;p&gt;The corrected process state can therefore be persisted through PM2 after stability verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  ☁️ Cloudflare / Public Routing
&lt;/h2&gt;

&lt;p&gt;The public Sepolia environment continues to operate through the existing Cloudflare infrastructure.&lt;/p&gt;

&lt;p&gt;The public MyZubster Sepolia endpoint remains:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://sepolia.myzubster.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;while the relevant backend services remain bound locally on the VPS.&lt;/p&gt;

&lt;p&gt;This keeps internal services separated from the public entrypoint while allowing the Sepolia environment to expose the required application routes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Why This Debugging Phase Was Important
&lt;/h2&gt;

&lt;p&gt;Several of today's issues demonstrate why infrastructure validation must go beyond checking whether a process simply says &lt;code&gt;online&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We encountered three very different classes of problems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. OAuth configuration mismatch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Google authentication reached the correct backend but failed during token exchange because of an invalid client credential.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Runtime environment mismatch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.env&lt;/code&gt; file contained the correct Sepolia URLs, while the running application could still operate with stale process-level configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Dependency-driven restart loop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PM2 displayed the UrbanLab service as online while it was actually crashing and restarting continuously because required Node.js packages were missing.&lt;/p&gt;

&lt;p&gt;Each issue required validation at a different layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Current Development Status
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MyZubster Sepolia public environment:&lt;/strong&gt; ✅ Operational&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google OAuth provider detection:&lt;/strong&gt; ✅ Operational&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google OAuth callback:&lt;/strong&gt; ✅ Operational&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google OAuth backend token flow:&lt;/strong&gt; ✅ Completed successfully&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OAuth callback state/code handling:&lt;/strong&gt; ✅ Verified&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sepolia frontend redirect configuration:&lt;/strong&gt; ✅ Corrected&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2 runtime environment:&lt;/strong&gt; ✅ Corrected&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I-ECO-01 / UrbanLab startup:&lt;/strong&gt; ✅ Operational&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UrbanLab restart loop:&lt;/strong&gt; ✅ Resolved&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js dependencies:&lt;/strong&gt; ✅ Repaired&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB connectivity:&lt;/strong&gt; ✅ Verified&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I-ECO-01 health endpoint:&lt;/strong&gt; ✅ Healthy&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Escrow controller initialization:&lt;/strong&gt; ✅ Operational&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2-of-3 Escrow configuration:&lt;/strong&gt; ✅ Loaded&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebSocket infrastructure:&lt;/strong&gt; ✅ Initialized&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2/systemd infrastructure:&lt;/strong&gt; ✅ Verified&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Security
&lt;/h2&gt;

&lt;p&gt;No API keys, OAuth secrets, database credentials, wallet private keys, JWT secrets, or other sensitive configuration values are included in this development update.&lt;/p&gt;

&lt;p&gt;Infrastructure credentials remain environment-level configuration and must never be committed to public repositories or included in public debugging output.&lt;/p&gt;

&lt;p&gt;Credential rotation is also part of the security process whenever secrets may have been exposed during development or debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛣️ Next Phase
&lt;/h2&gt;

&lt;p&gt;With the core infrastructure stabilized, development can move away from basic process recovery and toward higher-level integration testing.&lt;/p&gt;

&lt;p&gt;The next stages can focus on:&lt;/p&gt;

&lt;p&gt;• complete browser-level Google authentication verification&lt;br&gt;&lt;br&gt;
• social-login ticket exchange and session persistence&lt;br&gt;&lt;br&gt;
• Sepolia frontend/backend integration&lt;br&gt;&lt;br&gt;
• authenticated user flows&lt;br&gt;&lt;br&gt;
• wallet integration testing&lt;br&gt;&lt;br&gt;
• Escrow API testing&lt;br&gt;&lt;br&gt;
• multisig workflow validation&lt;br&gt;&lt;br&gt;
• WebSocket event testing&lt;br&gt;&lt;br&gt;
• failure and recovery scenarios&lt;br&gt;&lt;br&gt;
• production-readiness checks&lt;/p&gt;

&lt;p&gt;The important milestone is that we now have a much more predictable foundation.&lt;/p&gt;

&lt;p&gt;Google OAuth can complete successfully on the backend, the Sepolia runtime configuration is aligned with the intended public environment, MongoDB is connected, and I-ECO-01 is no longer trapped in a restart loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure debugging is not just about making a process start — it is about proving that every layer remains healthy after it starts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today, we moved MyZubster another significant step in that direction.&lt;/p&gt;

&lt;h1&gt;
  
  
  MyZubster #Sepolia #Web3 #Blockchain #NodeJS #MongoDB #GoogleOAuth #OAuth2 #PM2 #Cloudflare #Monero #Escrow #Multisig #SocketIO #UrbanLab #Infrastructure #BackendDevelopment #DevOps #BuildInPublic #DevelopmentUpdate
&lt;/h1&gt;

</description>
      <category>sepolia</category>
      <category>blockchain</category>
      <category>node</category>
      <category>myzubster</category>
    </item>
    <item>
      <title>MyZubster Marketplace + MetaMask: First Real Ethereum Sepolia Integration Test</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Fri, 25 Sep 2026 05:51:03 +0000</pubDate>
      <link>https://dev.to/danielioni/myzubster-marketplace-metamask-first-real-ethereum-sepolia-integration-test-454d</link>
      <guid>https://dev.to/danielioni/myzubster-marketplace-metamask-first-real-ethereum-sepolia-integration-test-454d</guid>
      <description>&lt;p&gt;MyZubster Marketplace + MetaMask: First Real Ethereum Sepolia Integration Test&lt;/p&gt;

&lt;p&gt;We are moving the MyZubster Marketplace toward a flow where identity, wallet ownership, marketplace requests, and blockchain payments are clearly separated.&lt;/p&gt;

&lt;p&gt;The target flow is:&lt;/p&gt;

&lt;p&gt;MyZubster account → verified wallet → signed marketplace request → accepted order → ETH payment on Ethereum Sepolia → server-side blockchain verification → completed order&lt;/p&gt;

&lt;p&gt;During this development session, we successfully validated several important parts of that architecture in a real test environment.&lt;/p&gt;

&lt;p&gt;Just as importantly, we now have a clear picture of what still needs to be completed before we can call the full Marketplace ETH flow end-to-end verified.&lt;br&gt;
A Separate E2E Environment&lt;/p&gt;

&lt;p&gt;The first decision was to avoid experimenting directly on production.&lt;/p&gt;

&lt;p&gt;We created a dedicated Git worktree on the VPS for the Sepolia E2E branch and kept the production checkout untouched.&lt;/p&gt;

&lt;p&gt;The test backend runs separately on:&lt;/p&gt;

&lt;p&gt;127.0.0.1:5010&lt;/p&gt;

&lt;p&gt;The React test frontend runs on:&lt;/p&gt;

&lt;p&gt;127.0.0.1:3010&lt;/p&gt;

&lt;p&gt;Production continues using its existing service and port.&lt;/p&gt;

&lt;p&gt;This gives us an isolated environment where wallet signing, Marketplace requests, and blockchain transactions can be tested without changing the public deployment.&lt;br&gt;
Ethereum Sepolia RPC Is Working&lt;/p&gt;

&lt;p&gt;We configured an Ethereum Sepolia RPC endpoint through Alchemy.&lt;/p&gt;

&lt;p&gt;The connection was tested directly with JSON-RPC and successfully returned a Sepolia block number.&lt;/p&gt;

&lt;p&gt;That confirms the backend has working blockchain access.&lt;/p&gt;

&lt;p&gt;This is important because MyZubster's payment verifier needs to independently inspect the blockchain and validate:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transaction hash;

sender address;

recipient address;

amount;

network;

transaction status;

confirmation count.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The RPC credential stays on the server and is not exposed to the browser.&lt;br&gt;
The Test Environment Is Not Publicly Exposed&lt;/p&gt;

&lt;p&gt;Instead of opening ports 3010 and 5010 to the Internet, we kept both services bound to localhost on the VPS.&lt;/p&gt;

&lt;p&gt;Access from the development machine is provided through an SSH local tunnel:&lt;/p&gt;

&lt;p&gt;ssh -N \&lt;br&gt;
  -L 127.0.0.1:3010:127.0.0.1:3010 \&lt;br&gt;
  root@SERVER&lt;/p&gt;

&lt;p&gt;The tunnel was successfully verified from Windows:&lt;/p&gt;

&lt;p&gt;TcpTestSucceeded : True&lt;/p&gt;

&lt;p&gt;The frontend also returned:&lt;/p&gt;

&lt;p&gt;HTTP/1.1 200 OK&lt;/p&gt;

&lt;p&gt;This allowed us to use the real browser and MetaMask extension while keeping the development server private.&lt;br&gt;
The React Marketplace Is Running Through the Test Backend&lt;/p&gt;

&lt;p&gt;The React development frontend uses relative API calls such as:&lt;/p&gt;

&lt;p&gt;/api/wallet/me&lt;br&gt;
/api/marketplace/...&lt;/p&gt;

&lt;p&gt;For the E2E environment, the frontend development proxy points to the isolated backend on port 5010.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;p&gt;Browser&lt;br&gt;
   ↓&lt;br&gt;
127.0.0.1:3010&lt;br&gt;
   ↓&lt;br&gt;
React development proxy&lt;br&gt;
   ↓&lt;br&gt;
127.0.0.1:5010&lt;br&gt;
   ↓&lt;br&gt;
MyZubster Sepolia backend&lt;/p&gt;

&lt;p&gt;Both frontend loading and backend health checks are working.&lt;br&gt;
Real MyZubster Authentication Was Reused&lt;/p&gt;

&lt;p&gt;The test frontend requires a valid MyZubster session before a wallet can be connected.&lt;/p&gt;

&lt;p&gt;Because the account being tested uses Google/GitHub OAuth, we reused an already authenticated MyZubster session for the localhost environment.&lt;/p&gt;

&lt;p&gt;No password or private wallet key was required.&lt;/p&gt;

&lt;p&gt;Once the valid MyZubster authentication token was available in the local test origin, the wallet integration became accessible.&lt;br&gt;
MetaMask Wallet Ownership Verification Works&lt;/p&gt;

&lt;p&gt;This is one of the most important results of the test.&lt;/p&gt;

&lt;p&gt;The Marketplace wallet panel initially showed:&lt;/p&gt;

&lt;p&gt;ETH / EVM wallet&lt;/p&gt;

&lt;p&gt;Not verified&lt;/p&gt;

&lt;p&gt;After authenticating the MyZubster account, we selected:&lt;/p&gt;

&lt;p&gt;Connect MetaMask&lt;/p&gt;

&lt;p&gt;The browser successfully communicated with the MetaMask extension.&lt;/p&gt;

&lt;p&gt;MyZubster then requested a wallet challenge from the backend and MetaMask signed that challenge using:&lt;/p&gt;

&lt;p&gt;personal_sign&lt;/p&gt;

&lt;p&gt;This is an off-chain signature.&lt;/p&gt;

&lt;p&gt;It is not a blockchain transaction.&lt;/p&gt;

&lt;p&gt;It does not transfer ETH.&lt;/p&gt;

&lt;p&gt;It does not consume gas.&lt;/p&gt;

&lt;p&gt;It only proves that the current MyZubster user controls the selected EVM wallet.&lt;/p&gt;

&lt;p&gt;The final UI state became:&lt;/p&gt;

&lt;p&gt;Verified · 0xBBBc51B471…03f514bCBb&lt;/p&gt;

&lt;p&gt;Wallet MetaMask verified and linked to your MyZubster account.&lt;/p&gt;

&lt;p&gt;This confirms that the complete wallet ownership flow is working:&lt;/p&gt;

&lt;p&gt;MyZubster authenticated user&lt;br&gt;
        ↓&lt;br&gt;
MetaMask account&lt;br&gt;
        ↓&lt;br&gt;
server-generated challenge&lt;br&gt;
        ↓&lt;br&gt;
personal_sign&lt;br&gt;
        ↓&lt;br&gt;
server signature verification&lt;br&gt;
        ↓&lt;br&gt;
wallet linked to MyZubster account&lt;/p&gt;

&lt;p&gt;Wallet Verification Is Separate From Payment&lt;/p&gt;

&lt;p&gt;One architectural detail is especially important.&lt;/p&gt;

&lt;p&gt;The wallet was verified while MetaMask reported:&lt;/p&gt;

&lt;p&gt;chain ID 84532&lt;/p&gt;

&lt;p&gt;That network is Base Sepolia.&lt;/p&gt;

&lt;p&gt;The Marketplace ETH payment system, however, targets:&lt;/p&gt;

&lt;p&gt;Ethereum Sepolia&lt;br&gt;
chainId: 11155111&lt;br&gt;
hex: 0xaa36a7&lt;/p&gt;

&lt;p&gt;This is not a problem for wallet ownership verification.&lt;/p&gt;

&lt;p&gt;The signature proves control of the EVM address independently of an ETH payment.&lt;/p&gt;

&lt;p&gt;When an actual Marketplace payment starts, the frontend checks the network again and requests MetaMask to switch to Ethereum Sepolia if necessary.&lt;/p&gt;

&lt;p&gt;This gives us an important separation:&lt;/p&gt;

&lt;p&gt;CONNECTED&lt;br&gt;
≠ VERIFIED&lt;br&gt;
≠ AUTHENTICATED&lt;br&gt;
≠ REQUEST SIGNED&lt;br&gt;
≠ TX SUBMITTED&lt;br&gt;
≠ PAID&lt;/p&gt;

&lt;p&gt;Each state represents a different security boundary.&lt;br&gt;
Signed Marketplace Requests Are Implemented&lt;/p&gt;

&lt;p&gt;The Marketplace code can also require a Buyer to sign a Marketplace request.&lt;/p&gt;

&lt;p&gt;The intended process is:&lt;/p&gt;

&lt;p&gt;Buyer selects listing&lt;br&gt;
        ↓&lt;br&gt;
MyZubster creates order challenge&lt;br&gt;
        ↓&lt;br&gt;
Buyer signs challenge with MetaMask&lt;br&gt;
        ↓&lt;br&gt;
Backend verifies signature&lt;br&gt;
        ↓&lt;br&gt;
Marketplace request is created&lt;/p&gt;

&lt;p&gt;Again, this signature is not a payment.&lt;/p&gt;

&lt;p&gt;It proves that the wallet attached to the request is controlled by the authenticated Buyer.&lt;/p&gt;

&lt;p&gt;The request can therefore carry verified wallet evidence to the Seller before any blockchain payment occurs.&lt;br&gt;
Seller Wallet Evidence Is Implemented&lt;/p&gt;

&lt;p&gt;The Marketplace order flow includes wallet evidence that can be shown to the Seller.&lt;/p&gt;

&lt;p&gt;This is intended to allow the Seller to verify that the Buyer request is associated with a wallet already verified by MyZubster.&lt;/p&gt;

&lt;p&gt;The payment lifecycle is therefore not simply:&lt;/p&gt;

&lt;p&gt;click → send ETH&lt;/p&gt;

&lt;p&gt;Instead it becomes:&lt;/p&gt;

&lt;p&gt;identity&lt;br&gt;
→ verified wallet&lt;br&gt;
→ signed request&lt;br&gt;
→ Seller acceptance&lt;br&gt;
→ payment intent&lt;br&gt;
→ blockchain transaction&lt;br&gt;
→ independent verification&lt;/p&gt;

&lt;p&gt;That separation is deliberate.&lt;br&gt;
Ethereum Sepolia Payment Flow Is Implemented&lt;/p&gt;

&lt;p&gt;For ETH orders, the backend can generate a payment intent containing the expected:&lt;/p&gt;

&lt;p&gt;sender&lt;br&gt;
recipient&lt;br&gt;
amount&lt;br&gt;
chain&lt;/p&gt;

&lt;p&gt;The browser then checks that the currently selected MetaMask wallet matches the verified Buyer wallet.&lt;/p&gt;

&lt;p&gt;It also checks that MetaMask is connected to Ethereum Sepolia.&lt;/p&gt;

&lt;p&gt;If necessary, it calls:&lt;/p&gt;

&lt;p&gt;wallet_switchEthereumChain&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;p&gt;0xaa36a7&lt;/p&gt;

&lt;p&gt;Only after those checks does the browser call:&lt;/p&gt;

&lt;p&gt;eth_sendTransaction&lt;/p&gt;

&lt;p&gt;MetaMask still requires explicit user confirmation.&lt;/p&gt;

&lt;p&gt;MyZubster does not hold the user's private key and cannot silently send the transaction.&lt;br&gt;
Server-Side Payment Verification&lt;/p&gt;

&lt;p&gt;Submitting a transaction hash does not automatically make an order paid.&lt;/p&gt;

&lt;p&gt;The backend independently checks the Sepolia transaction.&lt;/p&gt;

&lt;p&gt;The verifier is designed to validate:&lt;/p&gt;

&lt;p&gt;transaction exists&lt;br&gt;
sender matches Buyer&lt;br&gt;
recipient matches Seller&lt;br&gt;
amount matches payment intent&lt;br&gt;
network is Ethereum Sepolia&lt;br&gt;
transaction succeeded&lt;br&gt;
minimum confirmations reached&lt;/p&gt;

&lt;p&gt;The current lifecycle includes states such as:&lt;/p&gt;

&lt;p&gt;CONFIRMING&lt;br&gt;
PAID&lt;br&gt;
FAILED&lt;/p&gt;

&lt;p&gt;The target minimum for the current test is:&lt;/p&gt;

&lt;p&gt;3 confirmations&lt;/p&gt;

&lt;p&gt;This means a transaction may exist on-chain but still remain:&lt;/p&gt;

&lt;p&gt;CONFIRMING&lt;/p&gt;

&lt;p&gt;until the confirmation threshold has been reached.&lt;/p&gt;

&lt;p&gt;Only after successful blockchain verification should the Marketplace order move to:&lt;/p&gt;

&lt;p&gt;PAID&lt;/p&gt;

&lt;p&gt;What We Have Actually Verified&lt;/p&gt;

&lt;p&gt;At this point, we have successfully verified the following in a real environment:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;isolated VPS E2E environment;

production kept separate from the test stack;

Ethereum Sepolia JSON-RPC connectivity;

backend connection to MongoDB;

test backend running independently;

React test frontend running independently;

frontend-to-backend API proxy;

secure browser access through an SSH tunnel;

real MyZubster authenticated session;

MetaMask detected by the browser;

MetaMask account connection;

server-generated wallet challenge;

real personal_sign signature;

server-side wallet signature verification;

EVM wallet successfully linked to a MyZubster account.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That last point is the first major milestone of the real wallet E2E flow.&lt;br&gt;
What Still Needs To Be Tested&lt;/p&gt;

&lt;p&gt;The full Marketplace payment lifecycle is not yet fully E2E validated.&lt;/p&gt;

&lt;p&gt;The next test requires two distinct actors:&lt;/p&gt;

&lt;p&gt;Buyer&lt;br&gt;
Seller&lt;/p&gt;

&lt;p&gt;and ideally two distinct MyZubster accounts with two distinct EVM wallets.&lt;/p&gt;

&lt;p&gt;The remaining E2E sequence is:&lt;/p&gt;

&lt;p&gt;Seller account&lt;br&gt;
→ verify Seller MetaMask wallet&lt;br&gt;
→ activate Seller&lt;br&gt;
→ enable ETH acceptance&lt;br&gt;
→ create ETH listing&lt;/p&gt;

&lt;p&gt;Buyer account&lt;br&gt;
→ verify Buyer MetaMask wallet&lt;br&gt;
→ open Seller listing&lt;br&gt;
→ sign Marketplace request&lt;/p&gt;

&lt;p&gt;Seller&lt;br&gt;
→ inspect Buyer wallet evidence&lt;br&gt;
→ accept request&lt;/p&gt;

&lt;p&gt;Buyer&lt;br&gt;
→ receive ETH payment intent&lt;br&gt;
→ switch MetaMask to Ethereum Sepolia&lt;br&gt;
→ approve Sepolia transaction&lt;/p&gt;

&lt;p&gt;Backend&lt;br&gt;
→ detect transaction&lt;br&gt;
→ verify sender&lt;br&gt;
→ verify recipient&lt;br&gt;
→ verify amount&lt;br&gt;
→ verify successful receipt&lt;br&gt;
→ wait for confirmations&lt;br&gt;
→ mark order PAID&lt;/p&gt;

&lt;p&gt;Seller&lt;br&gt;
→ complete order&lt;/p&gt;

&lt;p&gt;That is the next milestone.&lt;br&gt;
Negative Tests Are Still Required&lt;/p&gt;

&lt;p&gt;A payment system also needs to prove that invalid transactions are rejected.&lt;/p&gt;

&lt;p&gt;The E2E suite still needs real negative-path tests for cases such as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrong Buyer wallet;

wrong network;

wrong recipient;

wrong payment amount;

failed transaction;

insufficient confirmations;

reused transaction hash;

transaction submitted before Seller acceptance;

Seller without a verified EVM wallet;

Seller not configured to accept ETH.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;These tests are as important as the successful payment path.&lt;br&gt;
No Private Keys on the Server&lt;/p&gt;

&lt;p&gt;A core property of the current architecture is that MyZubster never needs access to the MetaMask private key.&lt;/p&gt;

&lt;p&gt;The browser wallet signs locally.&lt;/p&gt;

&lt;p&gt;For ownership verification:&lt;/p&gt;

&lt;p&gt;MetaMask → personal_sign&lt;/p&gt;

&lt;p&gt;For payment:&lt;/p&gt;

&lt;p&gt;MetaMask → eth_sendTransaction&lt;/p&gt;

&lt;p&gt;The server only receives public information such as:&lt;/p&gt;

&lt;p&gt;address&lt;br&gt;
signature&lt;br&gt;
transaction hash&lt;/p&gt;

&lt;p&gt;and independently verifies them.&lt;/p&gt;

&lt;p&gt;This keeps the system non-custodial.&lt;br&gt;
Current Architecture&lt;/p&gt;

&lt;p&gt;The current design can be summarized as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            MyZubster Account
                   │
                   ▼
           Wallet Challenge
                   │
                   ▼
                MetaMask
                   │
            personal_sign
                   │
                   ▼
            Verified Wallet
                   │
                   ▼
          Marketplace Request
                   │
            signed off-chain
                   │
                   ▼
            Seller Acceptance
                   │
                   ▼
             Payment Intent
                   │
                   ▼
         Ethereum Sepolia TX
                   │
                   ▼
        Blockchain Verification
                   │
                   ▼
         CONFIRMING → PAID
                   │
                   ▼
               COMPLETED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Why This Matters&lt;/p&gt;

&lt;p&gt;The important result is not simply that “MetaMask connects.”&lt;/p&gt;

&lt;p&gt;The useful result is that we now have several independent trust boundaries working together:&lt;/p&gt;

&lt;p&gt;MyZubster authentication proves who the platform user is.&lt;/p&gt;

&lt;p&gt;MetaMask signature proves who controls the wallet.&lt;/p&gt;

&lt;p&gt;Marketplace request signatures prove which wallet approved a request.&lt;/p&gt;

&lt;p&gt;The blockchain proves that a payment transaction occurred.&lt;/p&gt;

&lt;p&gt;The MyZubster backend independently verifies whether that transaction satisfies the Marketplace payment intent.&lt;/p&gt;

&lt;p&gt;That is much stronger than trusting a transaction hash supplied by the browser.&lt;br&gt;
Next Milestone&lt;/p&gt;

&lt;p&gt;The next development milestone is straightforward:&lt;/p&gt;

&lt;p&gt;complete one real Buyer → Seller transaction using Sepolia test ETH and observe the order move from request creation all the way to PAID and COMPLETED.&lt;/p&gt;

&lt;p&gt;After that, the same environment can be used to exercise the negative payment cases and strengthen the verifier before any mainnet discussion.&lt;/p&gt;

&lt;p&gt;For now, the most important milestone is confirmed:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A real MyZubster account can authenticate, connect MetaMask, sign an off-chain wallet challenge, and have that EVM wallet independently verified and linked by the MyZubster backend.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The wallet layer is working.&lt;/p&gt;

&lt;p&gt;The next challenge is completing the entire Marketplace payment lifecycle.&lt;/p&gt;

</description>
      <category>sepolia</category>
      <category>integration</category>
      <category>real</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>From “Connect MetaMask” to Verifiable Marketplace Intent: What We Built in MyZubster and What Comes Next</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Fri, 25 Sep 2026 04:42:30 +0000</pubDate>
      <link>https://dev.to/danielioni/from-connect-metamask-to-verifiable-marketplace-intent-what-we-built-in-myzubster-and-what-comes-462i</link>
      <guid>https://dev.to/danielioni/from-connect-metamask-to-verifiable-marketplace-intent-what-we-built-in-myzubster-and-what-comes-462i</guid>
      <description>&lt;p&gt;From “Connect MetaMask” to Verifiable Marketplace Intent: What We Built in MyZubster and What Comes Next&lt;/p&gt;

&lt;p&gt;I’ve been working on a new Ethereum / MetaMask layer for MyZubster.&lt;/p&gt;

&lt;p&gt;What started as:&lt;/p&gt;

&lt;p&gt;“Let’s add MetaMask.”&lt;/p&gt;

&lt;p&gt;quickly became a much more interesting architecture problem.&lt;/p&gt;

&lt;p&gt;Because adding a wallet button is easy.&lt;/p&gt;

&lt;p&gt;Defining what a wallet means inside a real application is not.&lt;/p&gt;

&lt;p&gt;Over the latest development cycle, I implemented four connected pieces:&lt;/p&gt;

&lt;p&gt;MyZubster account&lt;br&gt;
        ↓&lt;br&gt;
verified MetaMask wallet&lt;br&gt;
        ↓&lt;br&gt;
optional Ethereum login&lt;br&gt;
        ↓&lt;br&gt;
signed Marketplace request&lt;br&gt;
        ↓&lt;br&gt;
Seller-visible cryptographic evidence&lt;/p&gt;

&lt;p&gt;But one principle has guided the entire implementation:&lt;/p&gt;

&lt;p&gt;CONNECTED&lt;br&gt;
!= VERIFIED&lt;br&gt;
!= AUTHENTICATED&lt;br&gt;
!= REQUEST_SIGNED&lt;br&gt;
!= ACCEPTED&lt;br&gt;
!= PAID&lt;br&gt;
!= SETTLED&lt;/p&gt;

&lt;p&gt;Keeping those states separate is probably the most important part of the work.&lt;/p&gt;

&lt;p&gt;Why I didn’t want “Web3 everything”&lt;/p&gt;

&lt;p&gt;One possible approach would have been:&lt;/p&gt;

&lt;p&gt;User opens MyZubster&lt;br&gt;
↓&lt;br&gt;
Connect wallet&lt;br&gt;
↓&lt;br&gt;
Every important action becomes a blockchain transaction&lt;br&gt;
↓&lt;br&gt;
Pay gas&lt;br&gt;
↓&lt;br&gt;
Wait for confirmations&lt;/p&gt;

&lt;p&gt;I deliberately did not take that route.&lt;/p&gt;

&lt;p&gt;MyZubster is not intended to become unusable for people who do not already live inside the crypto ecosystem.&lt;/p&gt;

&lt;p&gt;So MetaMask remains an additional capability.&lt;/p&gt;

&lt;p&gt;Users can still access MyZubster through traditional authentication methods.&lt;/p&gt;

&lt;p&gt;The emerging identity model is:&lt;/p&gt;

&lt;p&gt;Email / password&lt;br&gt;
Google&lt;br&gt;
GitHub&lt;br&gt;
Facebook&lt;br&gt;
MetaMask&lt;br&gt;
      ↓&lt;br&gt;
MyZubster account&lt;/p&gt;

&lt;p&gt;But the wallet adds cryptographic capabilities when they are actually useful.&lt;/p&gt;

&lt;p&gt;Milestone 1: proving wallet ownership&lt;/p&gt;

&lt;p&gt;The first problem was simple to describe:&lt;/p&gt;

&lt;p&gt;How does MyZubster know that the authenticated user really controls a particular Ethereum address?&lt;/p&gt;

&lt;p&gt;Reading an address from MetaMask is not sufficient.&lt;/p&gt;

&lt;p&gt;This:&lt;/p&gt;

&lt;p&gt;const accounts = await window.ethereum.request({&lt;br&gt;
  method: 'eth_requestAccounts'&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;only proves that the browser exposed an account.&lt;/p&gt;

&lt;p&gt;It does not give the backend a trustworthy ownership proof.&lt;/p&gt;

&lt;p&gt;So the first implementation introduced a challenge-signature flow.&lt;/p&gt;

&lt;p&gt;The architecture is:&lt;/p&gt;

&lt;p&gt;Authenticated MyZubster user&lt;br&gt;
        ↓&lt;br&gt;
Connect MetaMask&lt;br&gt;
        ↓&lt;br&gt;
eth_requestAccounts&lt;br&gt;
        ↓&lt;br&gt;
read chain ID&lt;br&gt;
        ↓&lt;br&gt;
POST /api/wallet/challenge&lt;br&gt;
        ↓&lt;br&gt;
server-generated nonce + challenge&lt;br&gt;
        ↓&lt;br&gt;
personal_sign&lt;br&gt;
        ↓&lt;br&gt;
POST /api/wallet/verify&lt;br&gt;
        ↓&lt;br&gt;
ethers.verifyMessage()&lt;br&gt;
        ↓&lt;br&gt;
recovered signer == expected wallet&lt;br&gt;
        ↓&lt;br&gt;
WALLET_VERIFIED&lt;/p&gt;

&lt;p&gt;The backend, not the frontend, decides whether a wallet is verified.&lt;/p&gt;

&lt;p&gt;The challenge&lt;/p&gt;

&lt;p&gt;The challenge is tied to:&lt;/p&gt;

&lt;p&gt;MyZubster account&lt;br&gt;
wallet address&lt;br&gt;
chain ID&lt;br&gt;
domain&lt;br&gt;
application URI&lt;br&gt;
random nonce&lt;br&gt;
issued time&lt;br&gt;
expiration&lt;br&gt;
LINK_WALLET action&lt;/p&gt;

&lt;p&gt;And the message explicitly tells the user:&lt;/p&gt;

&lt;p&gt;This is not a payment and does not spend ETH.&lt;/p&gt;

&lt;p&gt;That sentence is more important than it might appear.&lt;/p&gt;

&lt;p&gt;Wallet UX should not blur the difference between:&lt;/p&gt;

&lt;p&gt;sign message&lt;/p&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;p&gt;send transaction&lt;br&gt;
What MyZubster does not store&lt;/p&gt;

&lt;p&gt;The wallet integration is non-custodial.&lt;/p&gt;

&lt;p&gt;MyZubster does not need:&lt;/p&gt;

&lt;p&gt;private keys&lt;br&gt;
seed phrases&lt;br&gt;
mnemonics&lt;br&gt;
MetaMask passwords&lt;br&gt;
wallet secrets&lt;/p&gt;

&lt;p&gt;The application stores only the relationship needed to represent verified wallet ownership.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;evmWallet: {&lt;br&gt;
  walletType: 'EVM',&lt;br&gt;
  provider: 'metamask',&lt;br&gt;
  address: '0x...',&lt;br&gt;
  chainId: 1,&lt;br&gt;
  status: 'WALLET_VERIFIED',&lt;br&gt;
  verifiedAt: Date,&lt;br&gt;
  lastVerifiedAt: Date&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The user remains in control of the wallet.&lt;/p&gt;

&lt;p&gt;Milestone 2: signing Marketplace intent&lt;/p&gt;

&lt;p&gt;Once wallet ownership existed, the next question became:&lt;/p&gt;

&lt;p&gt;Can the buyer cryptographically prove that they intended to request a particular Marketplace listing?&lt;/p&gt;

&lt;p&gt;Without paying gas?&lt;/p&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;That became the second milestone.&lt;/p&gt;

&lt;p&gt;Instead of broadcasting an Ethereum transaction, MyZubster creates a canonical off-chain request.&lt;/p&gt;

&lt;p&gt;The flow is now:&lt;/p&gt;

&lt;p&gt;Verified MyZubster wallet&lt;br&gt;
        ↓&lt;br&gt;
Buyer clicks Request&lt;br&gt;
        ↓&lt;br&gt;
POST /api/marketplace/orders/challenge&lt;br&gt;
        ↓&lt;br&gt;
canonical MARKETPLACE_REQUEST generated&lt;br&gt;
        ↓&lt;br&gt;
MetaMask signs it&lt;br&gt;
        ↓&lt;br&gt;
backend verifies signer&lt;br&gt;
        ↓&lt;br&gt;
MarketplaceOrder created&lt;br&gt;
        ↓&lt;br&gt;
status = REQUESTED&lt;/p&gt;

&lt;p&gt;No ETH is transferred.&lt;/p&gt;

&lt;p&gt;No gas is required.&lt;/p&gt;

&lt;p&gt;What exactly gets signed?&lt;/p&gt;

&lt;p&gt;The server builds a structured request containing information such as:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "schema": "myzubster.marketplace-request.v1",&lt;br&gt;
  "intent": "MARKETPLACE_REQUEST",&lt;br&gt;
  "listingId": "...",&lt;br&gt;
  "quantity": 1,&lt;br&gt;
  "buyerAccountReference": "...",&lt;br&gt;
  "walletAddress": "0x...",&lt;br&gt;
  "chainId": 1,&lt;br&gt;
  "listingSnapshot": {&lt;br&gt;
    "title": "...",&lt;br&gt;
    "price": 25,&lt;br&gt;
    "currency": "EUR",&lt;br&gt;
    "exchangeMode": "payment",&lt;br&gt;
    "sellerId": "..."&lt;br&gt;
  },&lt;br&gt;
  "nonce": "...",&lt;br&gt;
  "issuedAt": "...",&lt;br&gt;
  "expiresAt": "..."&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The listing snapshot is important.&lt;/p&gt;

&lt;p&gt;The signature should represent what the buyer actually saw and requested.&lt;/p&gt;

&lt;p&gt;It should not silently become authorization for a listing after its commercial terms have changed.&lt;/p&gt;

&lt;p&gt;Replay protection&lt;/p&gt;

&lt;p&gt;A signed payload should not be reusable forever.&lt;/p&gt;

&lt;p&gt;The Marketplace challenge therefore includes:&lt;/p&gt;

&lt;p&gt;random nonce&lt;br&gt;
expiration&lt;br&gt;
user binding&lt;br&gt;
wallet binding&lt;br&gt;
listing binding&lt;br&gt;
quantity binding&lt;/p&gt;

&lt;p&gt;Once successfully used, the challenge becomes consumed.&lt;/p&gt;

&lt;p&gt;A second attempt is rejected.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;challenge&lt;br&gt;
↓&lt;br&gt;
signed&lt;br&gt;
↓&lt;br&gt;
verified&lt;br&gt;
↓&lt;br&gt;
order created&lt;br&gt;
↓&lt;br&gt;
CONSUMED&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;p&gt;same signature&lt;br&gt;
↓&lt;br&gt;
order 1&lt;br&gt;
↓&lt;br&gt;
order 2&lt;br&gt;
↓&lt;br&gt;
order 3&lt;br&gt;
What gets stored on the Marketplace order?&lt;/p&gt;

&lt;p&gt;The order now has a dedicated wallet evidence layer.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;walletEvidence: {&lt;br&gt;
  status: 'VERIFIED',&lt;br&gt;
  walletAddress: '0x...',&lt;br&gt;
  networkFamily: 'EVM',&lt;br&gt;
  chainId: 1,&lt;br&gt;
  payloadHash: '...',&lt;br&gt;
  challengeId: '...',&lt;br&gt;
  requestSchema: 'myzubster.marketplace-request.v1',&lt;br&gt;
  signedAt: Date,&lt;br&gt;
  verifiedAt: Date&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The raw signature exists as evidence but is hidden from normal Mongoose queries.&lt;/p&gt;

&lt;p&gt;The important public-facing evidence is the verified relationship and cryptographic hash, not dumping internal authentication material everywhere.&lt;/p&gt;

&lt;p&gt;Milestone 3: Sign-In with Ethereum&lt;/p&gt;

&lt;p&gt;After wallet ownership verification, another possibility became available.&lt;/p&gt;

&lt;p&gt;If a MyZubster account already has a verified EVM wallet, that wallet can also become an optional authentication method.&lt;/p&gt;

&lt;p&gt;So I added an Ethereum login path.&lt;/p&gt;

&lt;p&gt;The login page can now conceptually support:&lt;/p&gt;

&lt;p&gt;Email + password&lt;br&gt;
Google&lt;br&gt;
GitHub&lt;br&gt;
Facebook&lt;br&gt;
MetaMask&lt;/p&gt;

&lt;p&gt;MetaMask does not replace the existing authentication system.&lt;/p&gt;

&lt;p&gt;It extends it.&lt;/p&gt;

&lt;p&gt;Ethereum login flow&lt;/p&gt;

&lt;p&gt;The flow is:&lt;/p&gt;

&lt;p&gt;/social-login&lt;br&gt;
↓&lt;br&gt;
Continue with MetaMask&lt;br&gt;
↓&lt;br&gt;
eth_requestAccounts&lt;br&gt;
↓&lt;br&gt;
eth_chainId&lt;br&gt;
↓&lt;br&gt;
POST /api/auth/ethereum/challenge&lt;br&gt;
↓&lt;br&gt;
short-lived SIWE-style challenge&lt;br&gt;
↓&lt;br&gt;
personal_sign&lt;br&gt;
↓&lt;br&gt;
POST /api/auth/ethereum/verify&lt;br&gt;
↓&lt;br&gt;
server recovers Ethereum signer&lt;br&gt;
↓&lt;br&gt;
find existing MyZubster account with verified wallet&lt;br&gt;
↓&lt;br&gt;
issue normal MyZubster JWT&lt;/p&gt;

&lt;p&gt;The result is still a normal MyZubster session.&lt;/p&gt;

&lt;p&gt;MetaMask is the authentication proof.&lt;/p&gt;

&lt;p&gt;It does not mean the rest of MyZubster suddenly needs blockchain calls.&lt;/p&gt;

&lt;p&gt;An intentional limitation: no automatic wallet-only account creation yet&lt;/p&gt;

&lt;p&gt;For the first version, a random Ethereum wallet cannot silently create a brand-new MyZubster account.&lt;/p&gt;

&lt;p&gt;The wallet must already be linked to an existing account.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;p&gt;unknown wallet&lt;br&gt;
+&lt;br&gt;
valid Ethereum signature&lt;/p&gt;

&lt;p&gt;does not automatically become:&lt;/p&gt;

&lt;p&gt;new MyZubster user&lt;/p&gt;

&lt;p&gt;Instead, the user is asked to first enter through an existing identity method and link the wallet.&lt;/p&gt;

&lt;p&gt;That is intentional.&lt;/p&gt;

&lt;p&gt;Wallet-only onboarding introduces additional questions:&lt;/p&gt;

&lt;p&gt;How does account recovery work?&lt;/p&gt;

&lt;p&gt;What happens if the wallet is lost?&lt;/p&gt;

&lt;p&gt;How do we attach an email later?&lt;/p&gt;

&lt;p&gt;Can wallets be rotated?&lt;/p&gt;

&lt;p&gt;Can an account have multiple wallets?&lt;/p&gt;

&lt;p&gt;How do support and abuse recovery work?&lt;/p&gt;

&lt;p&gt;I want those questions answered before wallet-only registration becomes possible.&lt;/p&gt;

&lt;p&gt;Milestone 4: showing the proof to the Seller&lt;/p&gt;

&lt;p&gt;Cryptographic evidence is not very useful if nobody can understand it.&lt;/p&gt;

&lt;p&gt;So the next step was the Seller experience.&lt;/p&gt;

&lt;p&gt;When a Seller receives a Marketplace request that was signed using a verified wallet, MyZubster now displays:&lt;/p&gt;

&lt;p&gt;✓ Richiesta firmata · wallet verificato&lt;/p&gt;

&lt;p&gt;The Seller can see information such as:&lt;/p&gt;

&lt;p&gt;buyer wallet&lt;br&gt;
EVM chain ID&lt;br&gt;
request payload hash&lt;br&gt;
verification time&lt;/p&gt;

&lt;p&gt;The address and hash are abbreviated in the interface, while the complete values remain available where useful.&lt;/p&gt;

&lt;p&gt;What the Seller does not see&lt;/p&gt;

&lt;p&gt;I deliberately introduced an API projection instead of blindly returning the stored evidence object.&lt;/p&gt;

&lt;p&gt;The participant-facing endpoint returns only information required to understand the proof.&lt;/p&gt;

&lt;p&gt;It does not expose:&lt;/p&gt;

&lt;p&gt;raw MetaMask signature&lt;br&gt;
internal challenge ID&lt;br&gt;
private challenge state&lt;/p&gt;

&lt;p&gt;This is a small implementation detail, but it represents an important rule:&lt;/p&gt;

&lt;p&gt;cryptographic evidence does not mean every internal cryptographic artifact should automatically become public.&lt;/p&gt;

&lt;p&gt;Seller UX: signed is not paid&lt;/p&gt;

&lt;p&gt;The evidence panel also explicitly says:&lt;/p&gt;

&lt;p&gt;This signature proves request intent&lt;br&gt;
and wallet control.&lt;/p&gt;

&lt;p&gt;It is not a payment.&lt;br&gt;
It does not transfer ETH.&lt;br&gt;
It does not mean the Seller accepted the request.&lt;br&gt;
It does not mean the order is settled.&lt;/p&gt;

&lt;p&gt;This distinction is essential to the architecture.&lt;/p&gt;

&lt;p&gt;Today the lifecycle looks like:&lt;/p&gt;

&lt;p&gt;Wallet verified&lt;br&gt;
        ↓&lt;br&gt;
Request signed&lt;br&gt;
        ↓&lt;br&gt;
REQUESTED&lt;br&gt;
        ↓&lt;br&gt;
Seller accepts&lt;br&gt;
        ↓&lt;br&gt;
ACCEPTED&lt;br&gt;
        ↓&lt;br&gt;
payment, if required&lt;br&gt;
        ↓&lt;br&gt;
payment verification&lt;br&gt;
        ↓&lt;br&gt;
COMPLETED&lt;/p&gt;

&lt;p&gt;Signing step 2 does not magically jump to step 6.&lt;/p&gt;

&lt;p&gt;Why I think this architecture is more useful than “put everything on-chain”&lt;/p&gt;

&lt;p&gt;A Marketplace contains many actions.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;p&gt;browse listing&lt;br&gt;
request item&lt;br&gt;
ask question&lt;br&gt;
accept request&lt;br&gt;
reject request&lt;br&gt;
cancel&lt;br&gt;
review&lt;br&gt;
moderate&lt;br&gt;
pay&lt;br&gt;
settle&lt;br&gt;
record evidence&lt;/p&gt;

&lt;p&gt;Putting every one of those on-chain would introduce enormous friction.&lt;/p&gt;

&lt;p&gt;Instead, MyZubster can use different evidence layers for different actions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;ordinary application action&lt;br&gt;
→ database&lt;/p&gt;

&lt;p&gt;important user intent&lt;br&gt;
→ signed off-chain payload&lt;/p&gt;

&lt;p&gt;payment&lt;br&gt;
→ payment rail&lt;/p&gt;

&lt;p&gt;permanent public evidence&lt;br&gt;
→ optional blockchain anchor&lt;/p&gt;

&lt;p&gt;That is much closer to how I think blockchain integration should work.&lt;/p&gt;

&lt;p&gt;Use cryptography where cryptography adds something.&lt;/p&gt;

&lt;p&gt;Use blockchain where permanence adds something.&lt;/p&gt;

&lt;p&gt;Don’t turn every button into gas.&lt;/p&gt;

&lt;p&gt;The current PR stack&lt;/p&gt;

&lt;p&gt;The implementation is currently divided into several pull requests.&lt;/p&gt;

&lt;p&gt;PR #1385 — MetaMask wallet ownership linking&lt;/p&gt;

&lt;p&gt;Introduces:&lt;/p&gt;

&lt;p&gt;Connect MetaMask&lt;br&gt;
wallet challenge&lt;br&gt;
signature verification&lt;br&gt;
verified EVM wallet state&lt;br&gt;
disconnect flow&lt;br&gt;
PR #1386 — Signed MetaMask Marketplace requests&lt;/p&gt;

&lt;p&gt;Introduces:&lt;/p&gt;

&lt;p&gt;MARKETPLACE_REQUEST challenge&lt;br&gt;
canonical request payload&lt;br&gt;
off-chain signature&lt;br&gt;
replay protection&lt;br&gt;
walletEvidence on MarketplaceOrder&lt;br&gt;
PR #1387 — Optional Sign-In with Ethereum&lt;/p&gt;

&lt;p&gt;Introduces:&lt;/p&gt;

&lt;p&gt;Continue with MetaMask&lt;br&gt;
Ethereum authentication challenge&lt;br&gt;
signature verification&lt;br&gt;
existing account lookup&lt;br&gt;
normal MyZubster JWT&lt;br&gt;
PR #1388 — Seller-visible wallet evidence&lt;/p&gt;

&lt;p&gt;Introduces:&lt;/p&gt;

&lt;p&gt;verified request badge&lt;br&gt;
wallet address&lt;br&gt;
chain ID&lt;br&gt;
payload hash&lt;br&gt;
verification timestamp&lt;br&gt;
safe API projection&lt;br&gt;
signed-intent vs payment explanation&lt;/p&gt;

&lt;p&gt;So the architecture is now becoming:&lt;/p&gt;

&lt;p&gt;ACCOUNT&lt;br&gt;
   ↓&lt;br&gt;
WALLET OWNERSHIP&lt;br&gt;
   ↓&lt;br&gt;
AUTHENTICATION&lt;br&gt;
   ↓&lt;br&gt;
SIGNED INTENT&lt;br&gt;
   ↓&lt;br&gt;
MARKETPLACE STATE&lt;br&gt;
   ↓&lt;br&gt;
PAYMENT&lt;br&gt;
   ↓&lt;br&gt;
SETTLEMENT&lt;br&gt;
   ↓&lt;br&gt;
OPTIONAL PERMANENT EVIDENCE&lt;br&gt;
What is still missing?&lt;/p&gt;

&lt;p&gt;Quite a lot.&lt;/p&gt;

&lt;p&gt;And I think documenting the unfinished parts is as important as documenting what works.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Merge and production validation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The wallet work currently exists as a stack of development pull requests.&lt;/p&gt;

&lt;p&gt;Before calling the system production-ready, I still need to complete:&lt;/p&gt;

&lt;p&gt;CI validation&lt;br&gt;
security checks&lt;br&gt;
merge ordering&lt;br&gt;
deployment&lt;br&gt;
production smoke tests&lt;br&gt;
real MetaMask browser tests&lt;/p&gt;

&lt;p&gt;Passing unit tests is not the same as validating the complete browser-wallet-server journey.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Real Seller acceptance evidence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The buyer can sign a request.&lt;/p&gt;

&lt;p&gt;The Seller currently accepts it through the normal authenticated application flow.&lt;/p&gt;

&lt;p&gt;A future version could optionally introduce:&lt;/p&gt;

&lt;p&gt;SELLER_ACCEPTANCE&lt;/p&gt;

&lt;p&gt;as a separately signed intent.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;buyer:&lt;br&gt;
MARKETPLACE_REQUEST signed&lt;/p&gt;

&lt;p&gt;seller:&lt;br&gt;
MARKETPLACE_ACCEPTANCE signed&lt;/p&gt;

&lt;p&gt;That could produce bilateral evidence.&lt;/p&gt;

&lt;p&gt;But this should remain optional rather than forcing both parties through wallet signatures for every exchange.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ETH payment flow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The biggest missing layer is still actual Ethereum payment.&lt;/p&gt;

&lt;p&gt;The architecture should eventually distinguish:&lt;/p&gt;

&lt;p&gt;PAYMENT_REQUESTED&lt;br&gt;
PAYMENT_SUBMITTED&lt;br&gt;
PAYMENT_CONFIRMING&lt;br&gt;
PAID&lt;br&gt;
SETTLED&lt;br&gt;
FAILED&lt;/p&gt;

&lt;p&gt;A buyer signature is not payment evidence.&lt;/p&gt;

&lt;p&gt;Actual ETH payment needs transaction-level evidence.&lt;/p&gt;

&lt;p&gt;That means checking things like:&lt;/p&gt;

&lt;p&gt;network&lt;br&gt;
transaction hash&lt;br&gt;
sender&lt;br&gt;
recipient&lt;br&gt;
amount&lt;br&gt;
block inclusion&lt;br&gt;
confirmation count&lt;br&gt;
transaction status&lt;/p&gt;

&lt;p&gt;before saying:&lt;/p&gt;

&lt;p&gt;PAID&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Network policy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;MetaMask can be connected to many EVM networks.&lt;/p&gt;

&lt;p&gt;MyZubster therefore needs an explicit network policy.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Ethereum Mainnet&lt;br&gt;
Ethereum Sepolia&lt;br&gt;
Base&lt;br&gt;
Base Sepolia&lt;br&gt;
future EVM chains&lt;/p&gt;

&lt;p&gt;Wallet ownership itself can be chain-agnostic in some contexts.&lt;/p&gt;

&lt;p&gt;Payments cannot.&lt;/p&gt;

&lt;p&gt;If an order expects ETH on Ethereum mainnet, a transaction on another chain must not satisfy it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wallet switching&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another real-world UX problem:&lt;/p&gt;

&lt;p&gt;A user verifies:&lt;/p&gt;

&lt;p&gt;0xAAA&lt;/p&gt;

&lt;p&gt;but later MetaMask is currently using:&lt;/p&gt;

&lt;p&gt;0xBBB&lt;/p&gt;

&lt;p&gt;The frontend already detects some wallet mismatch situations, but this needs stronger product handling.&lt;/p&gt;

&lt;p&gt;Eventually MyZubster should clearly show:&lt;/p&gt;

&lt;p&gt;Verified wallet:&lt;br&gt;
0xAAA&lt;/p&gt;

&lt;p&gt;Currently selected MetaMask account:&lt;br&gt;
0xBBB&lt;/p&gt;

&lt;p&gt;Switch account to continue.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wallet recovery and rotation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This becomes important once MetaMask can authenticate users.&lt;/p&gt;

&lt;p&gt;What happens if somebody loses a wallet?&lt;/p&gt;

&lt;p&gt;The application needs a recovery model.&lt;/p&gt;

&lt;p&gt;Possible future flow:&lt;/p&gt;

&lt;p&gt;authenticate through another verified MyZubster identity&lt;br&gt;
↓&lt;br&gt;
request wallet replacement&lt;br&gt;
↓&lt;br&gt;
security confirmation&lt;br&gt;
↓&lt;br&gt;
old wallet revoked&lt;br&gt;
↓&lt;br&gt;
new wallet challenge&lt;br&gt;
↓&lt;br&gt;
new wallet verified&lt;/p&gt;

&lt;p&gt;Without that, wallet authentication risks becoming a trap for users who lose access.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multiple wallets&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Today the model is essentially:&lt;/p&gt;

&lt;p&gt;MyZubster account&lt;br&gt;
↓&lt;br&gt;
one verified EVM wallet&lt;/p&gt;

&lt;p&gt;Long term, a user might reasonably need:&lt;/p&gt;

&lt;p&gt;primary wallet&lt;br&gt;
Marketplace wallet&lt;br&gt;
personal wallet&lt;br&gt;
project wallet&lt;br&gt;
DAO wallet&lt;/p&gt;

&lt;p&gt;That would require a proper wallet registry rather than a single wallet property.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Standard SIWE compatibility&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Ethereum authentication message is currently SIWE-style.&lt;/p&gt;

&lt;p&gt;A future improvement is stricter compatibility with the formal Sign-In with Ethereum model and dedicated parsing/validation instead of relying only on the application’s own message construction.&lt;/p&gt;

&lt;p&gt;That would improve interoperability and reduce ambiguity.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mobile wallet support&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;window.ethereum works well for browser-extension environments such as desktop MetaMask.&lt;/p&gt;

&lt;p&gt;That is not enough for everyone.&lt;/p&gt;

&lt;p&gt;Mobile support may eventually require:&lt;/p&gt;

&lt;p&gt;MetaMask mobile deeplinks&lt;br&gt;
WalletConnect&lt;br&gt;
other EIP-1193 compatible providers&lt;/p&gt;

&lt;p&gt;I don’t want the feature to become “MetaMask desktop only”.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Better evidence inspection&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Seller currently gets a compact evidence summary.&lt;/p&gt;

&lt;p&gt;A future interface could provide an expandable verification view:&lt;/p&gt;

&lt;p&gt;Request schema&lt;br&gt;
Payload hash&lt;br&gt;
Wallet&lt;br&gt;
Network&lt;br&gt;
Signed at&lt;br&gt;
Verified at&lt;br&gt;
Listing snapshot&lt;br&gt;
Verification result&lt;/p&gt;

&lt;p&gt;without exposing secrets.&lt;/p&gt;

&lt;p&gt;Potentially something like:&lt;/p&gt;

&lt;p&gt;Verify signed request&lt;/p&gt;

&lt;p&gt;where MyZubster independently recomputes the payload hash.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Payment evidence must remain separate&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This needs to remain a permanent architectural rule:&lt;/p&gt;

&lt;p&gt;wallet verified&lt;br&gt;
!= payment verified&lt;/p&gt;

&lt;p&gt;Even if the wallet that signed the request later sends the payment.&lt;/p&gt;

&lt;p&gt;Those are two distinct cryptographic events.&lt;/p&gt;

&lt;p&gt;Request evidence says:&lt;/p&gt;

&lt;p&gt;this wallet expressed intent.&lt;/p&gt;

&lt;p&gt;Payment evidence says:&lt;/p&gt;

&lt;p&gt;this blockchain transaction moved value according to the expected payment conditions.&lt;/p&gt;

&lt;p&gt;They should never be collapsed into one status.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Blockchain anchoring&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once an exchange is completed, MyZubster already has experiments around evidence anchoring.&lt;/p&gt;

&lt;p&gt;Eventually the complete evidence chain could look like:&lt;/p&gt;

&lt;p&gt;buyer wallet proof&lt;br&gt;
        ↓&lt;br&gt;
signed request&lt;br&gt;
        ↓&lt;br&gt;
seller acceptance&lt;br&gt;
        ↓&lt;br&gt;
payment evidence&lt;br&gt;
        ↓&lt;br&gt;
completed Marketplace order&lt;br&gt;
        ↓&lt;br&gt;
canonical completion evidence&lt;br&gt;
        ↓&lt;br&gt;
optional Base / Ethereum anchor&lt;/p&gt;

&lt;p&gt;Again, blockchain anchoring should be optional and evidence-driven.&lt;/p&gt;

&lt;p&gt;A Marketplace order should never be described as “on-chain” simply because the application supports blockchain somewhere else.&lt;/p&gt;

&lt;p&gt;What I learned from this implementation&lt;/p&gt;

&lt;p&gt;The interesting lesson is that integrating MetaMask is not really about MetaMask.&lt;/p&gt;

&lt;p&gt;The JavaScript call itself is tiny.&lt;/p&gt;

&lt;p&gt;window.ethereum.request(...)&lt;/p&gt;

&lt;p&gt;The real engineering work is defining what a signature means.&lt;/p&gt;

&lt;p&gt;For every wallet action, the application has to answer:&lt;/p&gt;

&lt;p&gt;Who is signing?&lt;/p&gt;

&lt;p&gt;What exactly are they signing?&lt;/p&gt;

&lt;p&gt;Why are they signing it?&lt;/p&gt;

&lt;p&gt;How long is that signature valid?&lt;/p&gt;

&lt;p&gt;Can it be replayed?&lt;/p&gt;

&lt;p&gt;What account is it bound to?&lt;/p&gt;

&lt;p&gt;What does the signature authorize?&lt;/p&gt;

&lt;p&gt;What does it explicitly NOT authorize?&lt;/p&gt;

&lt;p&gt;What evidence should another participant see?&lt;/p&gt;

&lt;p&gt;What must remain private?&lt;/p&gt;

&lt;p&gt;That is where the real architecture lives.&lt;/p&gt;

&lt;p&gt;Where MyZubster is heading&lt;/p&gt;

&lt;p&gt;The broader idea is becoming clearer.&lt;/p&gt;

&lt;p&gt;MyZubster does not need one giant identity system or one giant blockchain transaction system.&lt;/p&gt;

&lt;p&gt;It can combine several independently verifiable layers:&lt;/p&gt;

&lt;p&gt;MyZubster identity&lt;br&gt;
GitHub identity&lt;br&gt;
Ethereum wallet control&lt;br&gt;
signed intent&lt;br&gt;
Marketplace lifecycle&lt;br&gt;
payment evidence&lt;br&gt;
community reputation&lt;br&gt;
Zorgax assistance&lt;br&gt;
optional blockchain permanence&lt;/p&gt;

&lt;p&gt;Each layer has its own meaning.&lt;/p&gt;

&lt;p&gt;And Zorgax can eventually help users understand those meanings rather than pretending everything is the same kind of “verification”.&lt;/p&gt;

&lt;p&gt;Current architecture&lt;/p&gt;

&lt;p&gt;Today, the direction is:&lt;/p&gt;

&lt;p&gt;Human&lt;br&gt;
 ↓&lt;br&gt;
MyZubster account&lt;br&gt;
 ↓&lt;br&gt;
optional verified identities&lt;br&gt;
 ├── GitHub&lt;br&gt;
 ├── Google&lt;br&gt;
 └── Ethereum wallet&lt;br&gt;
 ↓&lt;br&gt;
signed action&lt;br&gt;
 ↓&lt;br&gt;
application state&lt;br&gt;
 ↓&lt;br&gt;
human counterparty decision&lt;br&gt;
 ↓&lt;br&gt;
payment evidence&lt;br&gt;
 ↓&lt;br&gt;
optional blockchain evidence&lt;/p&gt;

&lt;p&gt;That feels much more useful to me than:&lt;/p&gt;

&lt;p&gt;Connect wallet&lt;br&gt;
↓&lt;br&gt;
Web3&lt;br&gt;
Next development milestone&lt;/p&gt;

&lt;p&gt;The next major technical milestone is the payment boundary:&lt;/p&gt;

&lt;p&gt;SIGNED REQUEST&lt;br&gt;
        ↓&lt;br&gt;
SELLER ACCEPTANCE&lt;br&gt;
        ↓&lt;br&gt;
ETH PAYMENT REQUEST&lt;br&gt;
        ↓&lt;br&gt;
MetaMask transaction approval&lt;br&gt;
        ↓&lt;br&gt;
Ethereum transaction&lt;br&gt;
        ↓&lt;br&gt;
server-side verification&lt;br&gt;
        ↓&lt;br&gt;
confirmations&lt;br&gt;
        ↓&lt;br&gt;
PAID&lt;/p&gt;

&lt;p&gt;Only there should MyZubster start talking about actual ETH movement.&lt;/p&gt;

&lt;p&gt;Until that point:&lt;/p&gt;

&lt;p&gt;A signature is evidence of intent, not evidence of payment.&lt;/p&gt;

&lt;p&gt;And I want that distinction to remain visible in both the code and the product.&lt;/p&gt;

&lt;p&gt;Project: MyZubster&lt;br&gt;
Stack: Node.js, Express, MongoDB, React, ethers, MetaMask&lt;br&gt;
Architecture: non-custodial wallet verification + off-chain signed intent&lt;br&gt;
Status: active development / PR validation&lt;br&gt;
Next major milestone: verified ETH payment lifecycle&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MyZubster-Ecosystem/myzubster" rel="noopener noreferrer"&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Current implementation PRs:&lt;/p&gt;

&lt;h1&gt;
  
  
  1385 — MetaMask wallet ownership
&lt;/h1&gt;

&lt;h1&gt;
  
  
  1386 — signed Marketplace requests
&lt;/h1&gt;

&lt;h1&gt;
  
  
  1387 — optional Sign-In with Ethereum
&lt;/h1&gt;

&lt;h1&gt;
  
  
  1388 — Seller-visible wallet evidence
&lt;/h1&gt;

&lt;p&gt;DEV.to tags&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>metamask</category>
      <category>myzubster</category>
      <category>node</category>
    </item>
    <item>
      <title>Connecting MetaMask to MyZubster: Building Wallet Ownership Without Turning Every Action Into a Blockchain Transaction</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Fri, 25 Sep 2026 04:21:25 +0000</pubDate>
      <link>https://dev.to/danielioni/connecting-metamask-to-myzubster-building-wallet-ownership-without-turning-every-action-into-a-fk1</link>
      <guid>https://dev.to/danielioni/connecting-metamask-to-myzubster-building-wallet-ownership-without-turning-every-action-into-a-fk1</guid>
      <description>&lt;p&gt;Connecting MetaMask to MyZubster: Building Wallet Ownership Without Turning Every Action Into a Blockchain Transaction&lt;/p&gt;

&lt;p&gt;I’m currently adding MetaMask and EVM wallet ownership verification to MyZubster.&lt;/p&gt;

&lt;p&gt;At first sight, this might sound like a simple “Connect Wallet” feature.&lt;/p&gt;

&lt;p&gt;It isn’t.&lt;/p&gt;

&lt;p&gt;The real problem I wanted to solve was:&lt;/p&gt;

&lt;p&gt;How can a MyZubster user prove that they control an Ethereum wallet without giving MyZubster custody of that wallet, without exposing private keys, and without turning every Marketplace action into an on-chain transaction?&lt;/p&gt;

&lt;p&gt;This distinction is becoming increasingly important as MyZubster grows.&lt;/p&gt;

&lt;p&gt;The ecosystem already contains Marketplace flows, GitHub integrations, AI-assisted workflows through Zorgax, blockchain evidence experiments, Base Sepolia anchoring, internal MYZ accounting, and support for multiple crypto assets.&lt;/p&gt;

&lt;p&gt;Adding MetaMask therefore cannot just mean placing a button in the UI.&lt;/p&gt;

&lt;p&gt;It needs a clear security and product model.&lt;/p&gt;

&lt;p&gt;The architecture I’m implementing is based on one central principle:&lt;/p&gt;

&lt;p&gt;Connected wallet&lt;br&gt;
!=&lt;br&gt;
Verified wallet ownership&lt;br&gt;
!=&lt;br&gt;
Signed Marketplace intent&lt;br&gt;
!=&lt;br&gt;
Payment authorization&lt;br&gt;
!=&lt;br&gt;
Payment&lt;br&gt;
!=&lt;br&gt;
Settlement&lt;/p&gt;

&lt;p&gt;Those states must remain separate.&lt;/p&gt;

&lt;p&gt;Why add MetaMask to MyZubster?&lt;/p&gt;

&lt;p&gt;Until now, a MyZubster account could interact with the Marketplace using the normal application identity.&lt;/p&gt;

&lt;p&gt;That works.&lt;/p&gt;

&lt;p&gt;But there are cases where it becomes useful to have an additional cryptographic proof tied to a user-controlled wallet.&lt;/p&gt;

&lt;p&gt;For example, imagine a Marketplace request.&lt;/p&gt;

&lt;p&gt;A buyer could say:&lt;/p&gt;

&lt;p&gt;I want to request this item.&lt;/p&gt;

&lt;p&gt;Today that intention is represented by the authenticated MyZubster account.&lt;/p&gt;

&lt;p&gt;With a verified wallet, the same user could additionally sign a canonical request payload.&lt;/p&gt;

&lt;p&gt;That would create cryptographic evidence that:&lt;/p&gt;

&lt;p&gt;this wallet controlled by this user&lt;br&gt;
signed this exact request&lt;br&gt;
at this specific moment&lt;/p&gt;

&lt;p&gt;without sending a transaction.&lt;/p&gt;

&lt;p&gt;No gas.&lt;/p&gt;

&lt;p&gt;No transfer.&lt;/p&gt;

&lt;p&gt;No smart contract interaction.&lt;/p&gt;

&lt;p&gt;Just an off-chain signature.&lt;/p&gt;

&lt;p&gt;This is the direction I want MyZubster to take.&lt;/p&gt;

&lt;p&gt;The first milestone: proving wallet ownership&lt;/p&gt;

&lt;p&gt;The first feature is deliberately small.&lt;/p&gt;

&lt;p&gt;Before thinking about payments, tokens or escrow, MyZubster needs to answer one question reliably:&lt;/p&gt;

&lt;p&gt;Does the authenticated MyZubster user actually control the wallet address they want to connect?&lt;/p&gt;

&lt;p&gt;Simply receiving an Ethereum address from the browser is not enough.&lt;/p&gt;

&lt;p&gt;A frontend can obtain an address from MetaMask using:&lt;/p&gt;

&lt;p&gt;const accounts = await window.ethereum.request({&lt;br&gt;
  method: 'eth_requestAccounts'&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;const address = accounts[0];&lt;/p&gt;

&lt;p&gt;But at this stage MyZubster should only consider the wallet:&lt;/p&gt;

&lt;p&gt;CONNECTED&lt;/p&gt;

&lt;p&gt;not:&lt;/p&gt;

&lt;p&gt;VERIFIED&lt;/p&gt;

&lt;p&gt;The proof comes from signing a server-generated challenge.&lt;/p&gt;

&lt;p&gt;Current architecture&lt;/p&gt;

&lt;p&gt;The flow I’m implementing looks like this:&lt;/p&gt;

&lt;p&gt;MyZubster authenticated user&lt;br&gt;
        ↓&lt;br&gt;
Connect MetaMask&lt;br&gt;
        ↓&lt;br&gt;
eth_requestAccounts&lt;br&gt;
        ↓&lt;br&gt;
Read wallet address&lt;br&gt;
        ↓&lt;br&gt;
Read chain ID&lt;br&gt;
        ↓&lt;br&gt;
POST /api/wallet/challenge&lt;br&gt;
        ↓&lt;br&gt;
MyZubster generates a one-time challenge&lt;br&gt;
        ↓&lt;br&gt;
MetaMask signs the challenge&lt;br&gt;
        ↓&lt;br&gt;
personal_sign&lt;br&gt;
        ↓&lt;br&gt;
POST /api/wallet/verify&lt;br&gt;
        ↓&lt;br&gt;
Server recovers signer with ethers&lt;br&gt;
        ↓&lt;br&gt;
Recovered address == requested wallet?&lt;br&gt;
        ↓&lt;br&gt;
YES&lt;br&gt;
        ↓&lt;br&gt;
WALLET_VERIFIED&lt;/p&gt;

&lt;p&gt;The important part is that verification happens on the server.&lt;/p&gt;

&lt;p&gt;The browser never gets to say:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "walletVerified": true&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;and have the backend trust it.&lt;/p&gt;

&lt;p&gt;That would defeat the entire purpose.&lt;/p&gt;

&lt;p&gt;The API&lt;/p&gt;

&lt;p&gt;The first implementation introduces four authenticated endpoints:&lt;/p&gt;

&lt;p&gt;GET    /api/wallet/me&lt;br&gt;
POST   /api/wallet/challenge&lt;br&gt;
POST   /api/wallet/verify&lt;br&gt;
DELETE /api/wallet/disconnect&lt;/p&gt;

&lt;p&gt;They intentionally represent a very small wallet lifecycle.&lt;/p&gt;

&lt;p&gt;GET /api/wallet/me returns the wallet state associated with the authenticated MyZubster account.&lt;/p&gt;

&lt;p&gt;POST /api/wallet/challenge starts ownership verification.&lt;/p&gt;

&lt;p&gt;POST /api/wallet/verify validates the signature.&lt;/p&gt;

&lt;p&gt;DELETE /api/wallet/disconnect removes the relationship between the MyZubster account and the EVM wallet.&lt;/p&gt;

&lt;p&gt;Generating the challenge&lt;/p&gt;

&lt;p&gt;The challenge is generated server-side.&lt;/p&gt;

&lt;p&gt;It is bound to several pieces of information:&lt;/p&gt;

&lt;p&gt;MyZubster user&lt;br&gt;
wallet address&lt;br&gt;
chain ID&lt;br&gt;
MyZubster domain&lt;br&gt;
application URI&lt;br&gt;
cryptographically random nonce&lt;br&gt;
issued time&lt;br&gt;
expiration time&lt;br&gt;
intended action&lt;/p&gt;

&lt;p&gt;The intended action for this flow is:&lt;/p&gt;

&lt;p&gt;LINK_WALLET&lt;/p&gt;

&lt;p&gt;A simplified challenge looks conceptually like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.myzubster.com" rel="noopener noreferrer"&gt;www.myzubster.com&lt;/a&gt; wants you to link your Ethereum account to MyZubster:&lt;/p&gt;

&lt;p&gt;0x1234...abcd&lt;/p&gt;

&lt;p&gt;Sign this message to prove wallet control.&lt;br&gt;
This is not a payment and does not spend ETH.&lt;/p&gt;

&lt;p&gt;URI: &lt;a href="https://www.myzubster.com" rel="noopener noreferrer"&gt;https://www.myzubster.com&lt;/a&gt;&lt;br&gt;
Version: 1&lt;br&gt;
Chain ID: 1&lt;br&gt;
Nonce: d70b4f...&lt;br&gt;
Issued At: 2026-09-25T04:00:00.000Z&lt;br&gt;
Expiration Time: 2026-09-25T04:05:00.000Z&lt;br&gt;
Request ID: LINK_WALLET:user-123&lt;/p&gt;

&lt;p&gt;That wording is intentional.&lt;/p&gt;

&lt;p&gt;A wallet signature must never be presented to the user as if it were a payment.&lt;/p&gt;

&lt;p&gt;Why the nonce matters&lt;/p&gt;

&lt;p&gt;Without a nonce, a signature can potentially be replayed.&lt;/p&gt;

&lt;p&gt;For example, imagine MyZubster accepted the same signature indefinitely.&lt;/p&gt;

&lt;p&gt;Someone could capture the signed message and submit it again later.&lt;/p&gt;

&lt;p&gt;Instead, every challenge gets a cryptographically random nonce:&lt;/p&gt;

&lt;p&gt;crypto.randomBytes(16).toString('hex');&lt;/p&gt;

&lt;p&gt;The challenge also expires after a short period.&lt;/p&gt;

&lt;p&gt;For the first implementation, the default validity window is around five minutes.&lt;/p&gt;

&lt;p&gt;So the verification logic checks:&lt;/p&gt;

&lt;p&gt;challenge exists&lt;br&gt;
↓&lt;br&gt;
challenge has not expired&lt;br&gt;
↓&lt;br&gt;
requested address matches&lt;br&gt;
↓&lt;br&gt;
message matches the server challenge&lt;br&gt;
↓&lt;br&gt;
signature is valid&lt;br&gt;
↓&lt;br&gt;
recovered signer matches wallet address&lt;/p&gt;

&lt;p&gt;Only after all of those conditions succeed does MyZubster persist the wallet as verified.&lt;/p&gt;

&lt;p&gt;Signature verification with ethers&lt;/p&gt;

&lt;p&gt;MyZubster already uses ethers, so the backend can recover the signer directly.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;const recovered = verifyMessage(message, signature);&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;if (recovered !== expectedAddress) {&lt;br&gt;
  throw new Error('Wallet signer mismatch');&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Addresses are normalized before comparison.&lt;/p&gt;

&lt;p&gt;That avoids accidental mismatches caused by formatting or checksum casing.&lt;/p&gt;

&lt;p&gt;What gets stored?&lt;/p&gt;

&lt;p&gt;MyZubster does not store:&lt;/p&gt;

&lt;p&gt;private keys&lt;br&gt;
seed phrases&lt;br&gt;
mnemonics&lt;br&gt;
wallet passwords&lt;br&gt;
MetaMask secrets&lt;/p&gt;

&lt;p&gt;The account only needs metadata about the wallet relationship.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;evmWallet: {&lt;br&gt;
  walletType: 'EVM',&lt;br&gt;
  provider: 'metamask',&lt;br&gt;
  address: '0x...',&lt;br&gt;
  chainId: 1,&lt;br&gt;
  status: 'WALLET_VERIFIED',&lt;br&gt;
  verifiedAt: Date,&lt;br&gt;
  lastVerifiedAt: Date&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;During verification there is also temporary challenge state containing things such as:&lt;/p&gt;

&lt;p&gt;address&lt;br&gt;
chainId&lt;br&gt;
nonce hash&lt;br&gt;
message hash&lt;br&gt;
issuedAt&lt;br&gt;
expiresAt&lt;br&gt;
action&lt;/p&gt;

&lt;p&gt;The challenge metadata is not part of the public wallet profile.&lt;/p&gt;

&lt;p&gt;Wallet state matters&lt;/p&gt;

&lt;p&gt;I’m explicitly modelling wallet state instead of using one boolean.&lt;/p&gt;

&lt;p&gt;The first states are:&lt;/p&gt;

&lt;p&gt;WALLET_NOT_CONNECTED&lt;/p&gt;

&lt;p&gt;WALLET_CHALLENGE_PENDING&lt;/p&gt;

&lt;p&gt;WALLET_VERIFIED&lt;/p&gt;

&lt;p&gt;WALLET_DISCONNECTED&lt;/p&gt;

&lt;p&gt;This becomes useful later because Zorgax and the UI can explain exactly what has happened.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;MetaMask is connected.&lt;/p&gt;

&lt;p&gt;is different from:&lt;/p&gt;

&lt;p&gt;MetaMask ownership has been cryptographically verified.&lt;/p&gt;

&lt;p&gt;And both are different from:&lt;/p&gt;

&lt;p&gt;You paid for this order.&lt;br&gt;
Connecting MetaMask in the frontend&lt;/p&gt;

&lt;p&gt;The existing MyZubster Wallet Hub is being extended instead of creating a completely separate wallet system.&lt;/p&gt;

&lt;p&gt;The user sees:&lt;/p&gt;

&lt;p&gt;Connect MetaMask&lt;/p&gt;

&lt;p&gt;The browser first asks MetaMask for the account:&lt;/p&gt;

&lt;p&gt;const accounts = await window.ethereum.request({&lt;br&gt;
  method: 'eth_requestAccounts'&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Then MyZubster reads the chain:&lt;/p&gt;

&lt;p&gt;const chainHex = await window.ethereum.request({&lt;br&gt;
  method: 'eth_chainId'&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;After receiving the challenge from the backend, MetaMask signs the exact message:&lt;/p&gt;

&lt;p&gt;const signature = await window.ethereum.request({&lt;br&gt;
  method: 'personal_sign',&lt;br&gt;
  params: [message, address]&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;That signature is then sent back to MyZubster.&lt;/p&gt;

&lt;p&gt;The server decides whether the wallet becomes verified.&lt;/p&gt;

&lt;p&gt;Preventing one wallet from silently belonging to multiple accounts&lt;/p&gt;

&lt;p&gt;There is another interesting product question.&lt;/p&gt;

&lt;p&gt;What happens if:&lt;/p&gt;

&lt;p&gt;MyZubster account A&lt;/p&gt;

&lt;p&gt;verifies:&lt;/p&gt;

&lt;p&gt;0xABC...&lt;/p&gt;

&lt;p&gt;and then account B attempts to verify the same address?&lt;/p&gt;

&lt;p&gt;For now, the implementation treats an already verified relationship as a conflict.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;/p&gt;

&lt;p&gt;MyZubster Account A&lt;br&gt;
        ↓&lt;br&gt;
0xABC&lt;br&gt;
        ↓&lt;br&gt;
VERIFIED&lt;/p&gt;

&lt;p&gt;MyZubster Account B&lt;br&gt;
        ↓&lt;br&gt;
attempts 0xABC&lt;br&gt;
        ↓&lt;br&gt;
WALLET_ALREADY_LINKED&lt;/p&gt;

&lt;p&gt;This does not mean the Ethereum address is a person's legal identity.&lt;/p&gt;

&lt;p&gt;It simply prevents MyZubster from claiming contradictory account-to-wallet relationships at the same time.&lt;/p&gt;

&lt;p&gt;What changes in MyZubster?&lt;/p&gt;

&lt;p&gt;This feature changes more than the wallet UI.&lt;/p&gt;

&lt;p&gt;It introduces a new cryptographic identity layer into the ecosystem.&lt;/p&gt;

&lt;p&gt;Today MyZubster can already know things such as:&lt;/p&gt;

&lt;p&gt;MyZubster account identity&lt;br&gt;
GitHub identity&lt;br&gt;
community profile&lt;br&gt;
Marketplace role&lt;br&gt;
Zorgax profile context&lt;/p&gt;

&lt;p&gt;Now it can additionally know:&lt;/p&gt;

&lt;p&gt;this authenticated account proved control&lt;br&gt;
of this EVM wallet&lt;br&gt;
at this time&lt;/p&gt;

&lt;p&gt;That becomes a reusable primitive.&lt;/p&gt;

&lt;p&gt;The next step: signed Marketplace requests&lt;/p&gt;

&lt;p&gt;This is where the feature starts becoming much more interesting.&lt;/p&gt;

&lt;p&gt;Once a wallet is verified, a Marketplace request can be signed off-chain.&lt;/p&gt;

&lt;p&gt;Imagine a listing:&lt;/p&gt;

&lt;p&gt;Listing ID: garden-tools-103&lt;br&gt;
Quantity: 2&lt;br&gt;
Buyer: account-42&lt;br&gt;
Wallet: 0xABC...&lt;/p&gt;

&lt;p&gt;MyZubster could generate a canonical payload:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "schema": "myzubster.marketplace-request.v1",&lt;br&gt;
  "intent": "MARKETPLACE_REQUEST",&lt;br&gt;
  "listingId": "garden-tools-103",&lt;br&gt;
  "quantity": 2,&lt;br&gt;
  "buyerAccountReference": "account-42",&lt;br&gt;
  "walletAddress": "0xABC...",&lt;br&gt;
  "nonce": "6f4c...",&lt;br&gt;
  "issuedAt": "2026-09-25T10:00:00Z",&lt;br&gt;
  "expiresAt": "2026-09-25T10:05:00Z"&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The buyer signs it.&lt;/p&gt;

&lt;p&gt;The server verifies it.&lt;/p&gt;

&lt;p&gt;Then the Marketplace order can be created as:&lt;/p&gt;

&lt;p&gt;REQUESTED&lt;/p&gt;

&lt;p&gt;with accompanying cryptographic evidence.&lt;/p&gt;

&lt;p&gt;But still:&lt;/p&gt;

&lt;p&gt;REQUEST_SIGNED != PAYMENT&lt;/p&gt;

&lt;p&gt;That distinction is extremely important.&lt;/p&gt;

&lt;p&gt;Why not put every Marketplace request on-chain?&lt;/p&gt;

&lt;p&gt;Because I don’t think blockchain should be used simply because blockchain exists.&lt;/p&gt;

&lt;p&gt;If every Marketplace request required an Ethereum transaction, the flow would become:&lt;/p&gt;

&lt;p&gt;request item&lt;br&gt;
↓&lt;br&gt;
open wallet&lt;br&gt;
↓&lt;br&gt;
estimate gas&lt;br&gt;
↓&lt;br&gt;
approve transaction&lt;br&gt;
↓&lt;br&gt;
wait for blockchain&lt;br&gt;
↓&lt;br&gt;
continue&lt;/p&gt;

&lt;p&gt;That adds cost and friction without necessarily adding proportional value.&lt;/p&gt;

&lt;p&gt;Instead, the initial architecture is:&lt;/p&gt;

&lt;p&gt;Marketplace request&lt;br&gt;
        ↓&lt;br&gt;
off-chain wallet signature&lt;br&gt;
        ↓&lt;br&gt;
seller acceptance&lt;br&gt;
        ↓&lt;br&gt;
exchange lifecycle&lt;br&gt;
        ↓&lt;br&gt;
structured evidence&lt;br&gt;
        ↓&lt;br&gt;
optional blockchain anchor&lt;/p&gt;

&lt;p&gt;Blockchain is used when permanence adds value.&lt;/p&gt;

&lt;p&gt;Not as mandatory friction.&lt;/p&gt;

&lt;p&gt;MyZubster already has EVM infrastructure&lt;/p&gt;

&lt;p&gt;This MetaMask work is not happening in isolation.&lt;/p&gt;

&lt;p&gt;The codebase already contains Ethereum-related infrastructure.&lt;/p&gt;

&lt;p&gt;There is currently support or experimental infrastructure around:&lt;/p&gt;

&lt;p&gt;ethers&lt;br&gt;
Ethereum Sepolia&lt;br&gt;
Base Sepolia&lt;br&gt;
Marketplace ETH payment verification&lt;br&gt;
blockchain evidence anchoring&lt;br&gt;
NFT experimentation&lt;br&gt;
knowledge evidence commitments&lt;/p&gt;

&lt;p&gt;For example, MyZubster already has server-side verification code capable of checking Ethereum Sepolia transactions.&lt;/p&gt;

&lt;p&gt;It also has Base Sepolia evidence flows where a canonical payload can be anchored and independently verified.&lt;/p&gt;

&lt;p&gt;The wallet-linking feature connects the user-controlled EVM side of that architecture.&lt;/p&gt;

&lt;p&gt;User wallet vs server wallet&lt;/p&gt;

&lt;p&gt;This distinction is also critical.&lt;/p&gt;

&lt;p&gt;MyZubster already uses dedicated server-side wallets for certain blockchain evidence experiments.&lt;/p&gt;

&lt;p&gt;Those wallets must remain completely separate from user wallets.&lt;/p&gt;

&lt;p&gt;The architecture should always preserve:&lt;/p&gt;

&lt;p&gt;User MetaMask wallet&lt;br&gt;
        !=&lt;br&gt;
MyZubster server anchoring wallet&lt;/p&gt;

&lt;p&gt;A user signs actions with their own wallet.&lt;/p&gt;

&lt;p&gt;A server evidence wallet performs explicitly defined infrastructure operations.&lt;/p&gt;

&lt;p&gt;Private keys for infrastructure wallets never go to the frontend.&lt;/p&gt;

&lt;p&gt;User private keys never go to MyZubster.&lt;/p&gt;

&lt;p&gt;What this could enable later&lt;/p&gt;

&lt;p&gt;Once wallet verification and signed intents are reliable, several future features become technically possible.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;signed Marketplace agreements&lt;br&gt;
optional blockchain settlement&lt;br&gt;
escrow experiments&lt;br&gt;
NFT ownership interactions&lt;br&gt;
portable proof of participation&lt;br&gt;
token-gated experiences&lt;br&gt;
signed contribution evidence&lt;br&gt;
Metaverse ownership features&lt;br&gt;
cross-application identity proofs&lt;/p&gt;

&lt;p&gt;But I’m deliberately not implementing all of these at once.&lt;/p&gt;

&lt;p&gt;The foundation has to be trustworthy first.&lt;/p&gt;

&lt;p&gt;What it changes for Zorgax&lt;/p&gt;

&lt;p&gt;Zorgax can also become more useful when wallet state is explicit.&lt;/p&gt;

&lt;p&gt;Instead of guessing, the assistant can answer questions like:&lt;/p&gt;

&lt;p&gt;User:&lt;br&gt;
Is my wallet connected?&lt;/p&gt;

&lt;p&gt;Zorgax:&lt;br&gt;
Your MetaMask wallet is linked and ownership has been verified.&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;User:&lt;br&gt;
Did I pay for this Marketplace request?&lt;/p&gt;

&lt;p&gt;Zorgax:&lt;br&gt;
No. Your wallet signed the request, but there is no confirmed payment evidence.&lt;/p&gt;

&lt;p&gt;That may sound like a small distinction.&lt;/p&gt;

&lt;p&gt;In financial or blockchain-related systems, it is not.&lt;/p&gt;

&lt;p&gt;It prevents the AI layer from confusing:&lt;/p&gt;

&lt;p&gt;signature&lt;br&gt;
transaction&lt;br&gt;
payment&lt;br&gt;
settlement&lt;br&gt;
Human approval remains part of the design&lt;/p&gt;

&lt;p&gt;This also follows the architecture I recently implemented for Zorgax and GitHub:&lt;/p&gt;

&lt;p&gt;AI proposes&lt;br&gt;
↓&lt;br&gt;
human reviews&lt;br&gt;
↓&lt;br&gt;
human approves&lt;br&gt;
↓&lt;br&gt;
system executes&lt;br&gt;
↓&lt;br&gt;
external result can be verified&lt;/p&gt;

&lt;p&gt;Wallet interactions should follow the same principle.&lt;/p&gt;

&lt;p&gt;MyZubster should never silently ask a wallet to perform economically meaningful actions.&lt;/p&gt;

&lt;p&gt;If a future operation transfers ETH or another asset, the user should see clearly:&lt;/p&gt;

&lt;p&gt;network&lt;br&gt;
asset&lt;br&gt;
amount&lt;br&gt;
destination&lt;br&gt;
action&lt;br&gt;
estimated cost&lt;/p&gt;

&lt;p&gt;before MetaMask asks for confirmation.&lt;/p&gt;

&lt;p&gt;Security lessons&lt;/p&gt;

&lt;p&gt;Building wallet integration makes one thing very clear:&lt;/p&gt;

&lt;p&gt;The hardest part is not opening MetaMask.&lt;/p&gt;

&lt;p&gt;This is easy:&lt;/p&gt;

&lt;p&gt;window.ethereum.request({&lt;br&gt;
  method: 'eth_requestAccounts'&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;The harder problem is designing the meaning of everything around that call.&lt;/p&gt;

&lt;p&gt;What does “connected” mean?&lt;/p&gt;

&lt;p&gt;What does “verified” mean?&lt;/p&gt;

&lt;p&gt;Can a challenge be replayed?&lt;/p&gt;

&lt;p&gt;Does the signature expire?&lt;/p&gt;

&lt;p&gt;Is the signature bound to the authenticated account?&lt;/p&gt;

&lt;p&gt;Can the same signature be used in another environment?&lt;/p&gt;

&lt;p&gt;Does the interface clearly explain that signing a message is not paying?&lt;/p&gt;

&lt;p&gt;Can the same wallet become associated with multiple MyZubster users?&lt;/p&gt;

&lt;p&gt;What happens when someone loses control of the wallet?&lt;/p&gt;

&lt;p&gt;Those are the questions that turn a wallet button into an actual product feature.&lt;/p&gt;

&lt;p&gt;Tests&lt;/p&gt;

&lt;p&gt;I’m also adding automated tests around these boundaries.&lt;/p&gt;

&lt;p&gt;The current implementation tests cases such as:&lt;/p&gt;

&lt;p&gt;valid wallet signs challenge&lt;br&gt;
→ accepted&lt;/p&gt;

&lt;p&gt;different wallet signs challenge&lt;br&gt;
→ rejected&lt;/p&gt;

&lt;p&gt;expired challenge&lt;br&gt;
→ rejected&lt;/p&gt;

&lt;p&gt;message explicitly states that signing is not payment&lt;br&gt;
→ required&lt;/p&gt;

&lt;p&gt;There are also wiring tests checking that the API is authenticated and that the frontend uses the expected MetaMask provider methods.&lt;/p&gt;

&lt;p&gt;Current status&lt;/p&gt;

&lt;p&gt;The first implementation is now in a GitHub pull request:&lt;/p&gt;

&lt;p&gt;PR #1385 — MetaMask wallet ownership linking&lt;/p&gt;

&lt;p&gt;It contains the wallet model, challenge service, API endpoints, frontend integration and tests.&lt;/p&gt;

&lt;p&gt;This should be considered the wallet ownership foundation, not the final Ethereum payment implementation.&lt;/p&gt;

&lt;p&gt;The next milestone is:&lt;/p&gt;

&lt;p&gt;Verified MetaMask wallet&lt;br&gt;
↓&lt;br&gt;
canonical MARKETPLACE_REQUEST&lt;br&gt;
↓&lt;br&gt;
off-chain signature&lt;br&gt;
↓&lt;br&gt;
server verification&lt;br&gt;
↓&lt;br&gt;
MarketplaceOrder REQUESTED&lt;/p&gt;

&lt;p&gt;After that, payment flows can remain a completely separate layer.&lt;/p&gt;

&lt;p&gt;The bigger architectural change&lt;/p&gt;

&lt;p&gt;For me, the most interesting part is not “MyZubster supports MetaMask”.&lt;/p&gt;

&lt;p&gt;It is that MyZubster is gradually gaining multiple independent layers of verifiable intent.&lt;/p&gt;

&lt;p&gt;GitHub can prove public development activity.&lt;/p&gt;

&lt;p&gt;MyZubster accounts represent application identity.&lt;/p&gt;

&lt;p&gt;MetaMask can prove control of an EVM address.&lt;/p&gt;

&lt;p&gt;Off-chain signatures can prove intent.&lt;/p&gt;

&lt;p&gt;Marketplace state can represent agreement.&lt;/p&gt;

&lt;p&gt;Payment verification can prove payment.&lt;/p&gt;

&lt;p&gt;Blockchain anchors can preserve selected evidence.&lt;/p&gt;

&lt;p&gt;Zorgax can help humans navigate all of those states without becoming the source of truth itself.&lt;/p&gt;

&lt;p&gt;That produces an architecture that looks more like:&lt;/p&gt;

&lt;p&gt;Identity&lt;br&gt;
   ↓&lt;br&gt;
Cryptographic control&lt;br&gt;
   ↓&lt;br&gt;
Signed intent&lt;br&gt;
   ↓&lt;br&gt;
Application state&lt;br&gt;
   ↓&lt;br&gt;
Payment evidence&lt;br&gt;
   ↓&lt;br&gt;
Optional permanent blockchain evidence&lt;/p&gt;

&lt;p&gt;instead of:&lt;/p&gt;

&lt;p&gt;Connect wallet&lt;br&gt;
↓&lt;br&gt;
everything is blockchain&lt;/p&gt;

&lt;p&gt;And I think that distinction will matter a lot as MyZubster evolves.&lt;/p&gt;

&lt;p&gt;Project: MyZubster&lt;br&gt;
Stack: Node.js, Express, MongoDB, React, ethers, MetaMask&lt;br&gt;
Current focus: non-custodial EVM wallet ownership verification&lt;br&gt;
Next milestone: signed Marketplace requests without gas&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MyZubster-Ecosystem/myzubster" rel="noopener noreferrer"&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MetaMask implementation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MyZubster-Ecosystem/myzubster/pull/1385" rel="noopener noreferrer"&gt;https://github.com/MyZubster-Ecosystem/myzubster/pull/1385&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>metamask</category>
      <category>myzubster</category>
      <category>transaction</category>
    </item>
    <item>
      <title>From Zero to Community: GitHub, Zorgax, Pilot Projects and the MyZubster Metaverse</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Thu, 24 Sep 2026 12:48:08 +0000</pubDate>
      <link>https://dev.to/danielioni/from-zero-to-community-github-zorgax-pilot-projects-and-the-myzubster-metaverse-4b2m</link>
      <guid>https://dev.to/danielioni/from-zero-to-community-github-zorgax-pilot-projects-and-the-myzubster-metaverse-4b2m</guid>
      <description>&lt;h1&gt;
  
  
  From Zero to Community: GitHub, Zorgax, Pilot Projects and the MyZubster Metaverse
&lt;/h1&gt;

&lt;p&gt;We have been working on a new onboarding flow for &lt;strong&gt;MyZubster&lt;/strong&gt; with one main goal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make it possible for someone to start from zero and progressively become part of a real open-source community.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should not need to already know GitHub, understand the architecture of the project, or know where to start contributing.&lt;/p&gt;

&lt;p&gt;The new flow connects &lt;strong&gt;Zorgax, GitHub, community projects, pilot projects, the MyZubster Metaverse and the Comic Universe&lt;/strong&gt; into one continuous experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start from zero
&lt;/h2&gt;

&lt;p&gt;A new user can begin without an existing developer profile.&lt;/p&gt;

&lt;p&gt;MyZubster can guide them through creating or connecting a GitHub account and then use &lt;strong&gt;Zorgax&lt;/strong&gt; to help build their public identity step by step.&lt;/p&gt;

&lt;p&gt;The important part is that Zorgax does not simply publish something automatically.&lt;/p&gt;

&lt;p&gt;The user can review the proposed profile, edit it and explicitly approve what should be published.&lt;/p&gt;

&lt;p&gt;The flow can manage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub display name and bio&lt;/li&gt;
&lt;li&gt;GitHub profile README&lt;/li&gt;
&lt;li&gt;MyZubster profile information&lt;/li&gt;
&lt;li&gt;community and project discovery&lt;/li&gt;
&lt;li&gt;access to pilot-project paths&lt;/li&gt;
&lt;li&gt;the user's Metaverse identity&lt;/li&gt;
&lt;li&gt;the user's node inside the MyZubster Comic Universe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turns GitHub from a simple login provider into part of the user's portable project identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zorgax as the onboarding layer
&lt;/h2&gt;

&lt;p&gt;Instead of landing on a large repository and wondering what to do next, a user can talk to &lt;strong&gt;Zorgax&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Zorgax can help understand the user's interests and connect them to relevant areas of the ecosystem.&lt;/p&gt;

&lt;p&gt;The idea is to move from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I discovered MyZubster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create / connect GitHub
        ↓
Build an approved profile with Zorgax
        ↓
Discover communities
        ↓
Enter pilot projects
        ↓
Become a character / node in the Metaverse
        ↓
Appear in the Comic Universe
        ↓
Contribute back through GitHub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a bridge between technical contribution and community participation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communities become entry points
&lt;/h2&gt;

&lt;p&gt;We also worked on making communities more than static categories.&lt;/p&gt;

&lt;p&gt;They can now become &lt;strong&gt;entry points into contribution flows&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A person interested in privacy, open source, circular economy, local communities, visual culture or other areas can enter through the topic they understand first.&lt;/p&gt;

&lt;p&gt;From there, Zorgax can guide them toward projects, documentation and contribution opportunities.&lt;/p&gt;

&lt;p&gt;For example, the current ecosystem includes paths connected to areas such as Monero/privacy, circular projects, community initiatives and open-source development.&lt;/p&gt;

&lt;p&gt;The goal is not to force every participant to become a developer.&lt;/p&gt;

&lt;p&gt;A contribution can start from code, documentation, testing, design, research, local experience or a pilot-project observation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilot projects become interactive
&lt;/h2&gt;

&lt;p&gt;One of the most important ideas behind MyZubster is connecting online collaboration with &lt;strong&gt;real-world pilot projects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of reading about a project and stopping there, users should be able to move directly from a community into a project flow.&lt;/p&gt;

&lt;p&gt;Zorgax becomes the guide between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interest → community → project → action → documented contribution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful for experimental projects where technical developers and people with practical experience need to work together.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub profile automation — with human approval
&lt;/h2&gt;

&lt;p&gt;We also introduced a more complete GitHub profile automation flow.&lt;/p&gt;

&lt;p&gt;A connected user can let Zorgax prepare a complete profile proposal including a name, bio and README.&lt;/p&gt;

&lt;p&gt;Before anything is published, the user sees the final version and explicitly approves it.&lt;/p&gt;

&lt;p&gt;The system also keeps rollback information so previous profile content can be restored.&lt;/p&gt;

&lt;p&gt;This means AI assistance can help with the boring part of building a developer identity without removing human control over what becomes public.&lt;/p&gt;

&lt;h2&gt;
  
  
  From GitHub profile to Metaverse character
&lt;/h2&gt;

&lt;p&gt;The profile does not stop at GitHub.&lt;/p&gt;

&lt;p&gt;Once the identity is approved, it can become part of the &lt;strong&gt;MyZubster Metaverse / Neon Plaza&lt;/strong&gt; experience.&lt;/p&gt;

&lt;p&gt;The same identity can then be represented as a character or node inside the virtual environment.&lt;/p&gt;

&lt;p&gt;This gives the onboarding process a visual continuation.&lt;/p&gt;

&lt;p&gt;Instead of creating an account and immediately seeing another dashboard, a user can move into a world that represents communities, projects and people.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comic Universe
&lt;/h2&gt;

&lt;p&gt;The same identity can also be connected to the &lt;strong&gt;MyZubster Comic Universe&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The comic is not only storytelling.&lt;/p&gt;

&lt;p&gt;We are experimenting with it as another interface for understanding the ecosystem.&lt;/p&gt;

&lt;p&gt;Projects, people, communities and concepts can become visual nodes inside a shared narrative.&lt;/p&gt;

&lt;p&gt;A user can therefore move from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub identity
→ MyZubster profile
→ community
→ pilot project
→ Metaverse character
→ Comic Universe node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while keeping GitHub as the public technical source of identity and contribution history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we are building it this way
&lt;/h2&gt;

&lt;p&gt;Open-source projects often assume that new contributors already understand GitHub, issues, pull requests, repositories and project structure.&lt;/p&gt;

&lt;p&gt;That creates a large entry barrier.&lt;/p&gt;

&lt;p&gt;We want to test a different approach.&lt;/p&gt;

&lt;p&gt;Someone should be able to arrive because they are interested in a community, a real-world project, a technology or even the visual world of MyZubster.&lt;/p&gt;

&lt;p&gt;Zorgax can then progressively explain the technical layers as they become necessary.&lt;/p&gt;

&lt;p&gt;The objective is to create a loop where participation produces identity, identity produces connections and those connections lead to new contributions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PERSON
  ↓
IDENTITY
  ↓
COMMUNITY
  ↓
PROJECT
  ↓
EXPERIENCE
  ↓
EVIDENCE
  ↓
CONTRIBUTION
  ↓
OPEN SOURCE
  ↺
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;There is still a lot to improve.&lt;/p&gt;

&lt;p&gt;We want to keep connecting communities with real pilot projects, improve the onboarding experience and make the transition between GitHub, Zorgax, the Metaverse and the Comic Universe increasingly seamless.&lt;/p&gt;

&lt;p&gt;The broader experiment is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can an open-source ecosystem make joining a project feel less like learning a toolchain and more like entering a living community?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is what we are trying to build with MyZubster.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/MyZubster-Ecosystem/myzubster" rel="noopener noreferrer"&gt;https://github.com/MyZubster-Ecosystem/myzubster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MyZubster: &lt;a href="https://www.myzubster.com/" rel="noopener noreferrer"&gt;https://www.myzubster.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Zorgax Profile Onboarding: &lt;a href="https://www.myzubster.com/zorgax-profile-onboarding" rel="noopener noreferrer"&gt;https://www.myzubster.com/zorgax-profile-onboarding&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Metaverse: &lt;a href="https://www.myzubster.com/metaverse" rel="noopener noreferrer"&gt;https://www.myzubster.com/metaverse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comic Universe: &lt;a href="https://www.myzubster.com/fumetto" rel="noopener noreferrer"&gt;https://www.myzubster.com/fumetto&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  opensource #github #ai #community
&lt;/h1&gt;

</description>
      <category>myzubster</category>
      <category>zorgax</category>
      <category>github</category>
      <category>community</category>
    </item>
    <item>
      <title>Rebuilding the MyZubster Knowledge Explorer as a Static, Evidence-Aware Knowledge Interface</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Wed, 23 Sep 2026 05:21:10 +0000</pubDate>
      <link>https://dev.to/danielioni/rebuilding-the-myzubster-knowledge-explorer-as-a-static-evidence-aware-knowledge-interface-1amf</link>
      <guid>https://dev.to/danielioni/rebuilding-the-myzubster-knowledge-explorer-as-a-static-evidence-aware-knowledge-interface-1amf</guid>
      <description>&lt;h1&gt;
  
  
  Rebuilding the MyZubster Knowledge Explorer as a Static, Evidence-Aware Knowledge Interface
&lt;/h1&gt;

&lt;p&gt;The MyZubster Knowledge Explorer already exposed a catalogue of canonical records across domains such as Fermentation, Monero, Programming, Art, Sport, Martial Arts and Animals.&lt;/p&gt;

&lt;p&gt;The problem was not data availability. The problem was interaction architecture.&lt;/p&gt;

&lt;p&gt;The previous page mixed domain discovery, record search, evidence interpretation and record inspection in one long visual flow. It was possible to browse the catalogue, but difficult to answer basic operational questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which records belong to a domain?&lt;/li&gt;
&lt;li&gt;Is this item a personal practice, an observation, a protocol or an external source?&lt;/li&gt;
&lt;li&gt;Can I search by stable record ID?&lt;/li&gt;
&lt;li&gt;How do I distinguish a documented claim from independently verified guidance?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We rebuilt &lt;code&gt;public/knowledge.html&lt;/code&gt; as a static, client-side knowledge explorer with explicit evidence boundaries.&lt;/p&gt;

&lt;p&gt;The updated page is deployed at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://myzubster-knowledge-myzubster.vercel.app/knowledge.html" rel="noopener noreferrer"&gt;https://myzubster-knowledge-myzubster.vercel.app/knowledge.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment surface
&lt;/h2&gt;

&lt;p&gt;The implementation intentionally uses the smallest possible deployment surface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myzubster-knowledge/
└── public/
    └── knowledge.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no new backend service, database migration, serverless function or framework runtime.&lt;/p&gt;

&lt;p&gt;The page is a self-contained HTML document containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;semantic HTML;&lt;/li&gt;
&lt;li&gt;CSS design tokens and responsive layout rules;&lt;/li&gt;
&lt;li&gt;a client-side record registry;&lt;/li&gt;
&lt;li&gt;domain navigation;&lt;/li&gt;
&lt;li&gt;full-text filtering;&lt;/li&gt;
&lt;li&gt;evidence-state filtering;&lt;/li&gt;
&lt;li&gt;an inline record-detail renderer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Vercel deployment path remains static:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /root/myzubster-knowledge

&lt;span class="nb"&gt;cp &lt;/span&gt;public/knowledge.html &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"public/knowledge.html.bak.&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F-%H%M%S&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0644 /tmp/knowledge.html public/knowledge.html

vercel &lt;span class="nt"&gt;--prod&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--scope&lt;/span&gt; myzubster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A timestamped backup is created before replacement. The deployment can therefore be rolled back without relying on an untracked local copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The record model
&lt;/h2&gt;

&lt;p&gt;The initial implementation uses an in-memory JavaScript registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MZ-001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Knowledge Layer — canonical record protocol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyZubster&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PROTOCOL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Defines the Knowledge Explorer as a catalogue of traceable records with a stable ID, domain, evidence state, provenance and review boundary.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is intentionally minimal, but it establishes the fields required for a future canonical-record format:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stable, human-readable identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Record title&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;domain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Knowledge domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;state&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Evidence classification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Human-readable context and limitations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The next iteration should externalize these records into versioned Markdown files with validated front matter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AHP-002&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Absorbent-product experience contribution model&lt;/span&gt;
&lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CIRCULAR_ECONOMIES&lt;/span&gt;
&lt;span class="na"&gt;evidence_state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PROTOCOL&lt;/span&gt;
&lt;span class="na"&gt;review_status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PROPOSED&lt;/span&gt;
&lt;span class="na"&gt;provenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UNKNOWN&lt;/span&gt;
&lt;span class="na"&gt;source_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would make the website a generated view over source-controlled knowledge objects rather than a manually maintained client-side array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence states are a first-class UI concern
&lt;/h2&gt;

&lt;p&gt;The explorer does not present every entry as equally reliable.&lt;/p&gt;

&lt;p&gt;Current values include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PERSONAL_PRACTICE
OBSERVATION
EXTERNAL_SOURCE
PROTOCOL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are not cosmetic labels. They encode the epistemic boundary of a record:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PERSONAL_PRACTICE&lt;/code&gt;: first-hand practice reported by a contributor;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OBSERVATION&lt;/code&gt;: a documented observation that may still require reproduction;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXTERNAL_SOURCE&lt;/code&gt;: a claim linked to an identifiable external source;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PROTOCOL&lt;/code&gt;: a proposed method, data model or verification procedure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core product rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A stored record is not automatically verified guidance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially important for health-adjacent, environmental and circular-economy content. Data integrity, document provenance and scientific validity are separate properties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search implementation
&lt;/h2&gt;

&lt;p&gt;The page supports a composable filter pipeline based on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;selected domain;&lt;/li&gt;
&lt;li&gt;selected evidence state;&lt;/li&gt;
&lt;li&gt;free-text query.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The current filtering implementation is deliberately framework-free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is sufficient for a small static catalogue and has predictable runtime behaviour:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no server round trip;&lt;/li&gt;
&lt;li&gt;no dependency on a search provider;&lt;/li&gt;
&lt;li&gt;no indexing infrastructure;&lt;/li&gt;
&lt;li&gt;deterministic results;&lt;/li&gt;
&lt;li&gt;zero persistence requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For larger catalogues, the next step should be build-time index generation and client-side indexed search rather than a backend search API by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain navigation
&lt;/h2&gt;

&lt;p&gt;The domain list is derived from a fixed domain registry and rendered dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allDomains&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyZubster&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Circular economies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fermentation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Monero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sound system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Music&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Art&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Martial arts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Programming&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;University&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Animals&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Permaculture&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Collaboration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each domain displays its active record count. Empty domains remain visible rather than being removed.&lt;/p&gt;

&lt;p&gt;That is intentional. An empty domain is not necessarily a missing feature. It can represent a mapped knowledge area that is ready to receive documented contributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  New MyZubster protocol records
&lt;/h2&gt;

&lt;p&gt;We added a dedicated &lt;code&gt;MyZubster&lt;/code&gt; domain with five protocol records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MZ-001 — Knowledge Layer — canonical record protocol
MZ-002 — Evidence states — from collection to independent review
MZ-003 — Zorgax — AI assistance with human verification
MZ-004 — Development requests — turning patterns into testable work
MZ-005 — Circular economies — verified contribution model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These records document the intended system architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI may structure, retrieve and connect knowledge;&lt;/li&gt;
&lt;li&gt;AI is not the authority that determines truth;&lt;/li&gt;
&lt;li&gt;a content hash can establish integrity, not scientific validity;&lt;/li&gt;
&lt;li&gt;a repeated pattern can become a scoped &lt;code&gt;DevelopmentRequest&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;a digital event trail does not prove a physical-world outcome without measurement and independent review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the foundation for a knowledge layer that can grow without silently converting proposals into facts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Circular economies and absorbent hygiene products
&lt;/h2&gt;

&lt;p&gt;We also introduced a &lt;code&gt;Circular economies&lt;/code&gt; domain with the &lt;code&gt;AHP-###&lt;/code&gt; identifier family:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AHP-001 — Circular Hygiene — evidence pilot framework
AHP-002 — Absorbent-product experience contribution model
AHP-003 — Absorbent materials — test and traceability template
AHP-004 — Circular economies — reproducible pilot catalogue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All four entries are classified as &lt;code&gt;PROTOCOL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That status is critical. The records define how evidence may be collected and structured; they do not claim that material recovery, safety, environmental impact, product performance or clinical outcomes have already been verified.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;AHP-002&lt;/code&gt; establishes a possible contribution model for lived product experience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lived experience
  → documented observation
  → aggregate pattern
  → DevelopmentRequest
  → prototype or research task
  → independent review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A user report can be valuable input to design. It is not a substitute for clinical evidence, product testing or external validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record inspection
&lt;/h2&gt;

&lt;p&gt;Selecting a card renders a detail panel from the selected record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;detail visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div class="detail-grid"&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;div class="meta"&amp;gt;
          &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;
          &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;h2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;ul class="facts"&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;Evidence state&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;Domain&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;Record ID&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current panel intentionally exposes only the available metadata. It does not fabricate source URLs, review results, hashes or relation graphs that are not yet defined by the canonical source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification performed before deployment
&lt;/h2&gt;

&lt;p&gt;The static page JavaScript was parsed before publication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'
const fs = require("fs");
const source = fs.readFileSync("dist/index.html", "utf8");
const script = source.match(/&amp;lt;script&amp;gt;([\s\S]*?)&amp;lt;\/script&amp;gt;/)[1];
new Function(script);
console.log("JavaScript valid");
'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The VPS-side artifact was then verified before replacing the production file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"MZ-001&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;AHP-001&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;Circular economies"&lt;/span&gt; /tmp/knowledge.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected identifiers were present before deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is not implemented yet
&lt;/h2&gt;

&lt;p&gt;This release is a static product slice, not a complete evidence protocol.&lt;/p&gt;

&lt;p&gt;It does not yet include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown or JSON source ingestion;&lt;/li&gt;
&lt;li&gt;schema validation in CI;&lt;/li&gt;
&lt;li&gt;record-level source URLs;&lt;/li&gt;
&lt;li&gt;canonical content hashes;&lt;/li&gt;
&lt;li&gt;contributor identity verification;&lt;/li&gt;
&lt;li&gt;consent-aware submission forms;&lt;/li&gt;
&lt;li&gt;reviewer permissions;&lt;/li&gt;
&lt;li&gt;relation graph traversal;&lt;/li&gt;
&lt;li&gt;external validation workflows;&lt;/li&gt;
&lt;li&gt;physical-world audit evidence;&lt;/li&gt;
&lt;li&gt;automatic status promotion from &lt;code&gt;PROTOCOL&lt;/code&gt; to verified guidance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those omissions are deliberate. The interface must not imply capabilities that do not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next implementation steps
&lt;/h2&gt;

&lt;p&gt;The technical roadmap is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store records as Markdown files with YAML front matter.&lt;/li&gt;
&lt;li&gt;Add a schema validator for IDs, domains, evidence states and provenance fields.&lt;/li&gt;
&lt;li&gt;Generate the record registry and domain counts at build time.&lt;/li&gt;
&lt;li&gt;Add stable routes such as &lt;code&gt;/knowledge/AHP-001&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add source, evidence and relation links.&lt;/li&gt;
&lt;li&gt;Implement contribution intake with explicit consent and &lt;code&gt;UNKNOWN&lt;/code&gt; defaults.&lt;/li&gt;
&lt;li&gt;Add independent review records before exposing any &lt;code&gt;VERIFIED_GUIDANCE&lt;/code&gt; state.&lt;/li&gt;
&lt;li&gt;Keep the distinction between data integrity and physical/scientific validation explicit in both code and UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Knowledge Explorer is no longer only a list of documents.&lt;/p&gt;

&lt;p&gt;It is now a lightweight, static interface for an evidence-aware knowledge model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;share
→ document
→ classify
→ inspect
→ test
→ review
→ improve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important architectural decision is not the UI framework. It is the refusal to treat a digital record, an AI summary or a contributor claim as verified truth by default.&lt;/p&gt;

&lt;p&gt;That boundary is what allows MyZubster to evolve from a catalogue into a traceable knowledge infrastructure.&lt;/p&gt;

</description>
      <category>myzubster</category>
      <category>knowledge</category>
      <category>interface</category>
      <category>explorer</category>
    </item>
    <item>
      <title>From GitHub to the Metaverse: Building Verified Profiles and Knowledge with MyZubster and Zorgax</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Wed, 23 Sep 2026 03:00:45 +0000</pubDate>
      <link>https://dev.to/danielioni/from-github-to-the-metaverse-building-verified-profiles-and-knowledge-with-myzubster-and-zorgax-5533</link>
      <guid>https://dev.to/danielioni/from-github-to-the-metaverse-building-verified-profiles-and-knowledge-with-myzubster-and-zorgax-5533</guid>
      <description>&lt;h1&gt;
  
  
  From GitHub to the Metaverse: Building Verified Profiles and Knowledge with MyZubster and Zorgax
&lt;/h1&gt;

&lt;p&gt;Over the last few days, we have been working on a part of MyZubster that is becoming increasingly important to the whole project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;turning a simple user account into a verified digital identity connected to real skills, experiences, projects, evidence, contributors and knowledge.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal is not to build another social network where people write a short bio and stop there.&lt;/p&gt;

&lt;p&gt;The idea behind MyZubster is broader.&lt;/p&gt;

&lt;p&gt;A profile should be able to explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who you are;&lt;/li&gt;
&lt;li&gt;what you can actually do;&lt;/li&gt;
&lt;li&gt;what you are learning;&lt;/li&gt;
&lt;li&gt;what projects you have worked on;&lt;/li&gt;
&lt;li&gt;what evidence exists;&lt;/li&gt;
&lt;li&gt;who you have collaborated with;&lt;/li&gt;
&lt;li&gt;which parts of your experience are verified;&lt;/li&gt;
&lt;li&gt;and which information you explicitly want to make public.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, MyZubster should avoid inventing skills or turning weak signals into professional qualifications.&lt;/p&gt;

&lt;p&gt;That is where Zorgax enters the picture.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub as a verified identity layer
&lt;/h2&gt;

&lt;p&gt;One of the systems we are developing is the connection between MyZubster and GitHub.&lt;/p&gt;

&lt;p&gt;When a user authenticates through GitHub, MyZubster can associate the account with a verified GitHub identity.&lt;/p&gt;

&lt;p&gt;That is very different from simply allowing someone to write:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My GitHub username is this."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, MyZubster can know that the GitHub identity is actually connected to the authenticated account.&lt;/p&gt;

&lt;p&gt;From there, Zorgax can use publicly available information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub profile information;&lt;/li&gt;
&lt;li&gt;repositories;&lt;/li&gt;
&lt;li&gt;profile README;&lt;/li&gt;
&lt;li&gt;repository descriptions;&lt;/li&gt;
&lt;li&gt;programming languages;&lt;/li&gt;
&lt;li&gt;public project activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But an important principle is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;data is not automatically a skill.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Having a JavaScript repository does not automatically mean someone is an advanced JavaScript developer.&lt;/p&gt;

&lt;p&gt;Having cybersecurity repositories does not automatically make someone a professional security engineer.&lt;/p&gt;

&lt;p&gt;The system should distinguish between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;evidence;&lt;/li&gt;
&lt;li&gt;declared experience;&lt;/li&gt;
&lt;li&gt;verified activity;&lt;/li&gt;
&lt;li&gt;inferred context;&lt;/li&gt;
&lt;li&gt;and actual professional claims.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction is very important for us.&lt;/p&gt;




&lt;h1&gt;
  
  
  Yassen: from GitHub authentication to the MyZubster Metaverse
&lt;/h1&gt;

&lt;p&gt;We have already seen this workflow become real with Yassen.&lt;/p&gt;

&lt;p&gt;Yassen configured his GitHub profile and connected it to MyZubster.&lt;/p&gt;

&lt;p&gt;Through that process, he entered the MyZubster Metaverse with a complete authenticated identity.&lt;/p&gt;

&lt;p&gt;This is important because the Metaverse character is not just an anonymous avatar disconnected from everything else.&lt;/p&gt;

&lt;p&gt;The identity can be linked back to the authenticated MyZubster account and its verified GitHub profile.&lt;/p&gt;

&lt;p&gt;So the flow becomes something like:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
text
GitHub identity
        ↓
MyZubster authentication
        ↓
verified account
        ↓
Metaverse character
        ↓
projects, contributors and evidence
Yassen also added danieldirimini-myzubster as a contributor.
That creates another important connection.
Instead of thinking about profiles as isolated pages, we can start thinking about a network of people who have actually collaborated.
A contribution can become part of a larger graph:
Person
  ↓
Project
  ↓
Contribution
  ↓
Evidence
  ↓
Other contributors
This is one of the directions we want MyZubster to develop further.
Profiles should describe real people, not AI-generated identities
While building the profile onboarding system, we also found an interesting problem.
Zorgax is an AI assistant inside MyZubster.
During early profile onboarding tests, a question such as:
"What practical activities can you do?"

could sometimes be interpreted by the assistant as a question directed at Zorgax itself.
That produced answers about what the AI could do instead of interviewing the user.
We corrected this behavior.
The onboarding system now explicitly tells Zorgax:
- it is interviewing the user;
- the questions are about the user's professional profile;
- it must not answer questionnaire questions as itself;
- it must not attribute Zorgax capabilities to the user;
- it should ask one question at a time;
- it should wait for the user's answer.
This sounds like a small change, but it represents a fundamental rule.
AI must help structure a person's identity, not create one for them.
Building my own professional profile inside MyZubster
We are now using the same system to structure my own profile.
Instead of creating a generic biography, we went through my experiences one by one.
We separated:
- skills I can use operationally;
- long-term practical experience;
- self-taught knowledge;
- things I am currently learning;
- available evidence;
- interests;
- professional goals;
- collaboration availability.
We also deliberately avoided presenting self-taught experience as formal certification.
For example, my profile includes areas such as:
MyZubster
I directly manage the development and evolution of MyZubster.
My work includes:
- project coordination;
- testing;
- identifying problems;
- following deployments;
- documentation;
- coordinating contributors;
- using GitHub, Linear and Vercel;
- using AI tools such as ChatGPT and Zorgax;
- working with the VPS and terminal when necessary.
At the same time, I do not describe myself as an advanced software developer if that level of expertise has not yet been reached.
That distinction matters.
Cybersecurity and Kali Linux
I have spent more than ten years studying and experimenting with Kali Linux and cybersecurity in a self-taught way.
The public professional profile only represents legitimate skills such as:
- Linux;
- terminal usage;
- networking;
- scanning;
- configuration;
- security testing in authorized environments or laboratories.
The profile system is designed to exclude unrelated or sensitive information that should not become part of a public professional identity.
Calisthenics
I practiced calisthenics for approximately four years.
My practical experience includes movements such as:
- human flag;
- L-sit;
- V-sit;
- muscle-up;
- freestyle;
- back lever;
- front lever.
There are video records available as evidence.
Again, the system does not convert this into invented certifications or coaching qualifications.
It simply records the experience that actually exists.
Thai boxing and MMA
My profile also includes:
- around four years of Thai boxing;
- around two years of MMA;
- training and sparring with other athletes.
This is recorded as practical experience, not as professional coaching or competitive certification.
Event organization and free parties
Another significant part of my experience comes from events.
I have participated in free party culture for almost twenty years and personally organized more than ten events.
This involved practical responsibilities such as:
- finding locations;
- coordinating people;
- DJs and music;
- sound systems;
- bar organization;
- shifts;
- communication;
- security;
- transport;
- technical setup;
- visual setup.
I have also worked directly with:
- lasers;
- LaserCube;
- projectors;
- screens;
- visual effects.
I am also learning video mapping.
For audio systems, I have practical basic knowledge of:
- connections;
- mixers;
- speakers;
- levels;
- simple troubleshooting.
The profile explicitly avoids describing this as professional audio engineering expertise.
Barista experience
I also have around four years of experience working as a barista.
That includes:
- coffee preparation;
- café work;
- preparation of alcoholic drinks.
Kefir as practical knowledge
Another important area for me is kefir.
I have approximately seven years of practical experience with:
- preparation;
- maintaining kefir grains;
- fermentation;
- managing fermentation time;
- sharing grains;
- teaching other people how to prepare and maintain kefir.
This is particularly interesting for MyZubster because kefir is not only a profile skill.
It can also become part of the knowledge system.
A practical skill can generate:
experience
   ↓
evidence
   ↓
structured knowledge
   ↓
verification
   ↓
knowledge available to others
That is one of the core ideas behind MyZubster Knowledge.
Permaculture, gardening and botany
I have also studied permaculture independently through books and practical experimentation.
My experience includes:
- gardening;
- plants;
- botany;
- practical cultivation.
These activities were also part of my volunteer experience.
Volunteer experience
I spent around two years volunteering with the Comunità Papa Giovanni XXIII.
My practical responsibilities included:
- helping manage the facility;
- organizing work;
- supporting young people;
- coordinating daily activities;
- participating in and coordinating group meetings.
The professional profile deliberately describes this as practical organizational and support experience.
It does not assign medical, psychological or therapeutic professional qualifications that I do not hold.
That is another important principle of the system:
experience should be represented accurately without inflating it into credentials.
Psychology as self-directed study
I have also spent approximately seven years studying psychology independently through books.
This includes interests such as:
- Freud;
- dreams;
- psychological dynamics;
- fragility and personal development.
Again, MyZubster represents this as:
self-directed study
and not as a psychologist or therapist qualification.
The structured professional profile
To support all of this, we added a structured professional profile model to MyZubster.
The profile can contain:
headline
summary
skills
experience level
evidence
practical experiences
interests
professional goals
collaboration availability
approval status
visibility
version
timestamps
One example of a skill can look conceptually like this:
{
  "name": "Kali Linux / Cybersecurity",
  "experience": "10+ years of self-directed study and practice",
  "level": "Self-taught practical experience",
  "evidence": [
    "Personal practice"
  ],
  "notes": "Only legitimate and authorized security activities are represented"
}
Explicit approval before saving or publishing
One of the most important rules we implemented is that Zorgax cannot simply decide to publish a professional profile.
The API requires explicit approval.
A profile update must include something equivalent to:
{
  "approved": true,
  "visibility": "private"
}
or:
{
  "approved": true,
  "visibility": "public"
}
Without explicit approval, the server refuses to register the professional profile.
This means the user remains in control.
The onboarding interface now presents two distinct actions:
Approve and save privately
or:
Approve and publish on MyZubster
The AI can help organize information.
The human decides whether it becomes part of the profile.
Private and public identity are not the same thing
This distinction is very important.
Not everything a person knows, has experienced or has discussed with an AI belongs on a public profile.
For that reason, MyZubster is being designed around different states.
Conceptually:
Private information
       ↓
Profile candidate
       ↓
User review
       ↓
Explicit approval
       ↓
Private profile
       OR
Public profile
This model will also be important for the Knowledge system.
From profiles to knowledge
The next layer is MyZubster Knowledge.
A user's experience should not automatically become universal knowledge.
For example:
"I have made kefir for seven years"

is a personal experience.
It can become evidence for a contribution.
But it is not automatically the same as:
"This is the scientifically correct way to make kefir."

Those are different claims.
So we use another principle:
message != knowledge
candidate != verified
verified != public
A contribution can start as a candidate.
Then it can be connected to:
- evidence;
- sources;
- people;
- projects;
- GitHub activity;
- practical demonstrations;
- reviewers.
Only after verification should it become part of the public Knowledge layer.
Zorgax as the connection layer
Zorgax is becoming the system that connects these pieces.
It is important to clarify that Zorgax is not simply "a language model trained from scratch."
Zorgax is the AI and orchestration layer inside MyZubster.
It can combine:
- language models;
- verified knowledge;
- evidence;
- workflows;
- user profiles;
- GitHub;
- MyZubster projects;
- contributors;
- human approvals.
So the architecture starts looking more like:
                MyZubster
                    |
        +-----------+-----------+
        |                       |
      Users                  Knowledge
        |                       |
    Profiles                 Evidence
        |                       |
      GitHub                  Sources
        |                       |
 Contributions ------------ Verification
        |                       |
        +--------- Zorgax ------+
                    |
                Metaverse
The Metaverse becomes more than avatars
This is where the Yassen example becomes especially interesting.
If a Metaverse user can be connected to:
- an authenticated MyZubster account;
- a verified GitHub profile;
- real repositories;
- contributions;
- other contributors;
- professional knowledge;
- evidence;
then the Metaverse stops being just a virtual world populated by anonymous avatars.
A character can become a representation of a real digital identity.
Imagine entering the MyZubster Metaverse and meeting someone.
Instead of only seeing:
Yassen
the system could eventually allow you to understand:
Yassen
├── Verified MyZubster account
├── Verified GitHub identity
├── Projects
├── Contributions
├── Collaborators
├── Skills
├── Knowledge contributions
└── Evidence
Of course, only information the user has chosen to make public should appear.
Contributors as part of the identity graph
When Yassen added danieldirimini-myzubster as a contributor, it demonstrated another direction for the ecosystem.
A project is not only code.
It is a network of people.
That network can eventually connect:
Developer
   ↓
Repository
   ↓
Contribution
   ↓
Contributor
   ↓
Evidence
   ↓
Reputation
   ↓
Knowledge
This can become much more meaningful than follower counts.
Instead of asking:
"How popular is this person?"

we can ask:
"What have they actually contributed?"

Why we are doing this
I want MyZubster to become my main professional project.
But at the same time, I am using the project itself as a way to continuously develop my skills.
That means MyZubster is also becoming a record of the learning process.
Instead of pretending to already know everything, the profile can distinguish between:
I know this
I have practical experience with this
I am currently learning this
I have evidence for this
I want to improve this
For me, this is much more honest and useful than a traditional CV.
The bigger idea
What we are building can eventually connect four important concepts:
Identity
Who is this person?
Evidence
What proof exists?
Contribution
What has this person actually done?
Knowledge
What can the community verify and reuse?
And Zorgax can help connect them without replacing human judgment.
The long-term model looks something like this:
IDENTITY
   ↓
EXPERIENCE
   ↓
EVIDENCE
   ↓
CONTRIBUTION
   ↓
VERIFICATION
   ↓
KNOWLEDGE
   ↓
COLLABORATION
That is the direction we are exploring with MyZubster.
Not just a marketplace.
Not just a Metaverse.
Not just an AI assistant.
Not just GitHub integration.
But an ecosystem where people, projects, real-world experience, evidence and knowledge can become connected.
And, most importantly, where the person remains in control of what becomes public.
What we have working now
At the current stage we have already implemented important pieces of this architecture:
- GitHub-based verified identities;
- authenticated MyZubster accounts;
- GitHub-linked Metaverse characters;
- structured professional profiles;
- skills and experience with evidence;
- explicit user approval before profile persistence;
- private and public profile visibility;
- Zorgax-guided profile onboarding;
- protection against AI inventing user capabilities;
- a public Knowledge Explorer;
- a verification-oriented Knowledge layer;
- contributor relationships;
- Vercel deployment infrastructure.
The professional profile implementation has also been tested with automated regression tests before deployment.
What we are doing next
The next step is not simply to add more fields.
The real challenge is connecting the graph.
We want to increasingly connect:
MyZubster profile
       ↓
GitHub
       ↓
projects
       ↓
contributors
       ↓
evidence
       ↓
Knowledge
       ↓
Zorgax
       ↓
Metaverse identity
My own profile is currently being used as one of the real examples for building this system.
The goal is to make the profile itself useful to the ecosystem:
not just a biography,
but a structured representation of what I can do, what I have done, what I am learning, what evidence exists and how I can collaborate with others.
That is the direction we are taking MyZubster.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>metaverse</category>
      <category>knowledge</category>
      <category>yassen</category>
      <category>profiles</category>
    </item>
    <item>
      <title>Building MyZubster in Public: Marketplace Validation, Metaverse Progress, and the Bugs We Found</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Tue, 22 Sep 2026 15:49:03 +0000</pubDate>
      <link>https://dev.to/danielioni/building-myzubster-in-public-marketplace-validation-metaverse-progress-and-the-bugs-we-found-4fpd</link>
      <guid>https://dev.to/danielioni/building-myzubster-in-public-marketplace-validation-metaverse-progress-and-the-bugs-we-found-4fpd</guid>
      <description>&lt;p&gt;Ti conviene pubblicarlo dopo una piccola revisione: il contenuto è buono, ma nel testo che hai incollato ci sono alcuni problemi di Markdown e il link finale al repository punta ancora al vecchio MyZubster-Ecosystem. Qui sotto ti lascio una versione pulita e pronta da incollare su DEV.to, mantenendo il tono tecnico e “build in public”.&lt;br&gt;
Building MyZubster in Public: Marketplace Validation, Metaverse Progress, and the Bugs We Found&lt;br&gt;
MyZubster is an open-source ecosystem connecting community projects, a Marketplace, internal MYZ utility credits, environmental pilots, contributor workflows, Zorgax, and an experimental browser-based Metaverse.&lt;br&gt;
Right now, we are following a simple principle:&lt;br&gt;
Before adding more blockchain complexity, we must prove that the basic product works for real people.&lt;/p&gt;

&lt;p&gt;That means testing the Marketplace, validating Seller onboarding, improving account security, collecting privacy-respecting product evidence, and documenting failures as carefully as successful tests.&lt;br&gt;
A free-first Marketplace&lt;br&gt;
The current Seller model is designed to be free-first.&lt;br&gt;
Users can explore the Marketplace without paying. Creating a basic Seller profile does not require a card or bank account, and payment onboarding begins only when a Seller wants to receive real payments.&lt;br&gt;
The intended model is:&lt;br&gt;
Marketplace visitor&lt;br&gt;
    ↓&lt;br&gt;
Free account&lt;br&gt;
    ↓&lt;br&gt;
Free Seller activation&lt;br&gt;
    ↓&lt;br&gt;
Limited commercial listings&lt;br&gt;
    ↓&lt;br&gt;
Optional payment onboarding&lt;br&gt;
    ↓&lt;br&gt;
Paid transactions&lt;br&gt;
A wallet or cryptocurrency is not required for basic participation.&lt;br&gt;
During our latest production test, the interface correctly displayed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Become a Seller for free”&lt;/li&gt;
&lt;li&gt;no initial Stripe Checkout&lt;/li&gt;
&lt;li&gt;no mandatory wallet or Monero setup&lt;/li&gt;
&lt;li&gt;the platform commission disclosure for eligible paid transactions&lt;/li&gt;
&lt;li&gt;access to the listing form after Seller activation
But the test also exposed an important defect.
The sixth-listing limit failed
The Free Seller policy is supposed to allow a maximum of five active commercial listings.
Five existing test listings were already visible.
We then prepared a controlled sixth listing:
TEST — Seller Free limit verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technical test listing.&lt;br&gt;
Do not purchase.&lt;br&gt;
The expected result was:&lt;br&gt;
FREE_SELLER_ACTIVE_LISTING_LIMIT&lt;br&gt;
The actual result was:&lt;br&gt;
Listing published&lt;br&gt;
The sixth commercial listing became publicly visible.&lt;br&gt;
That matters because a frontend policy is not enough.&lt;br&gt;
If a business rule exists, it must be enforced by the server before persistence.&lt;br&gt;
The fix needs to address several layers:&lt;br&gt;
Client validation&lt;br&gt;
      ↓&lt;br&gt;
Authentication&lt;br&gt;
      ↓&lt;br&gt;
Authorization&lt;br&gt;
      ↓&lt;br&gt;
Server-side policy&lt;br&gt;
      ↓&lt;br&gt;
Database persistence&lt;br&gt;
      ↓&lt;br&gt;
Regression tests&lt;br&gt;
The server must enforce the listing limit before writing the new listing.&lt;br&gt;
It must also handle concurrent publication attempts safely, distinguish commercial listings from documented free, barter, or community categories, and prevent unauthorized Seller activation or publication.&lt;br&gt;
This is exactly why we test against production-like workflows.&lt;br&gt;
A rule that exists only in the UI is not a reliable rule.&lt;br&gt;
Neon Plaza Metaverse validation&lt;br&gt;
We also tested the MyZubster Metaverse flow.&lt;br&gt;
The account-linked experience successfully completed several important steps:&lt;br&gt;
Canonical linked character loaded&lt;br&gt;
        ↓&lt;br&gt;
User entered Neon Plaza&lt;br&gt;
        ↓&lt;br&gt;
World reached online state&lt;br&gt;
        ↓&lt;br&gt;
Keyboard movement worked&lt;br&gt;
        ↓&lt;br&gt;
First portal reached&lt;br&gt;
        ↓&lt;br&gt;
First Zorgax mission completed&lt;br&gt;
        ↓&lt;br&gt;
Visited-zone counter updated&lt;br&gt;
        ↓&lt;br&gt;
Progress associated with account&lt;br&gt;
At the time of the test, the world displayed a small number of created characters and one active online session.&lt;br&gt;
Those figures are only point-in-time technical observations.&lt;br&gt;
They should not be interpreted as adoption metrics.&lt;br&gt;
The important part of the test was that the browser experience did not require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a wallet&lt;/li&gt;
&lt;li&gt;a payment&lt;/li&gt;
&lt;li&gt;a VR headset&lt;/li&gt;
&lt;li&gt;a local installation
A normal browser was enough.
Why we are not rushing into WebXR
The Metaverse roadmap currently follows this order:
Foundation
↓
Authentication
↓
Account security
↓
Privacy and abuse controls
↓
Realtime observability
↓
End-to-end acceptance
↓
WebXR runtime
↓
Public events
↓
Virtual twins
It would be easy to jump directly to more visually impressive features.
But adding advanced WebXR, creator-economy systems, or complex token mechanics before identity, moderation, reliability, and acceptance testing are stable would only increase technical debt.
So we are deliberately doing the less glamorous work first.
Privacy-respecting analytics
One of the next Metaverse improvements is a small allowlisted analytics funnel.
We want to understand a few basic events:
Onboarding view
Return visit
Mission start
First mission completion
But analytics should not become uncontrolled tracking.
The payload should only contain bounded properties such as:
surface
guest/account mode
fixed mission identifier
known landmark identifier
It should not contain:
character names
display names
GitHub usernames
session identifiers
chat messages
MYZ account identifiers
wallet information
authentication tokens
This is an important architectural principle for us:
Collect the minimum evidence required to understand whether the product works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not every piece of available data needs to become analytics.&lt;br&gt;
GitHub integration and development evidence&lt;br&gt;
GitHub is becoming increasingly important in MyZubster, but we treat it as an evidence source rather than an automatic source of truth.&lt;br&gt;
A commit proves that a commit exists.&lt;br&gt;
It does not automatically prove that:&lt;br&gt;
the feature works&lt;br&gt;
the requirements were satisfied&lt;br&gt;
the implementation is secure&lt;br&gt;
the architecture is correct&lt;br&gt;
the work was independently verified&lt;br&gt;
This distinction is becoming central to the architecture we are building around Zorgax and DevelopmentRequest.&lt;br&gt;
The longer-term goal is to connect:&lt;br&gt;
Developer&lt;br&gt;
    ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
    ↓&lt;br&gt;
Issue&lt;br&gt;
    ↓&lt;br&gt;
Commit&lt;br&gt;
    ↓&lt;br&gt;
Pull Request&lt;br&gt;
    ↓&lt;br&gt;
Tests&lt;br&gt;
    ↓&lt;br&gt;
Review&lt;br&gt;
    ↓&lt;br&gt;
Verified Contribution&lt;br&gt;
That gives us a much stronger basis for contributor history than simply counting commits.&lt;br&gt;
MYZ accounting&lt;br&gt;
MYZ is currently treated as an internal utility and accounting credit.&lt;br&gt;
It is not designed as an investment promise.&lt;br&gt;
Before production MYZ accounting can be enabled, the canonical ledger needs durable storage and stronger accounting guarantees.&lt;br&gt;
The target architecture requires:&lt;br&gt;
Atomic debit/credit entries&lt;br&gt;
        ↓&lt;br&gt;
Fixed-point arithmetic&lt;br&gt;
        ↓&lt;br&gt;
Unique transfer IDs&lt;br&gt;
        ↓&lt;br&gt;
Idempotency constraints&lt;br&gt;
        ↓&lt;br&gt;
Concurrency protection&lt;br&gt;
        ↓&lt;br&gt;
Durable history&lt;br&gt;
        ↓&lt;br&gt;
Backup and restore evidence&lt;br&gt;
A local JSON file may be useful during early experimentation.&lt;br&gt;
It is not sufficient as a production financial ledger.&lt;br&gt;
The migration toward durable database-backed accounting therefore has to happen before automated production settlement.&lt;br&gt;
External settlement is a separate gate&lt;br&gt;
External XMR settlement remains a later stage.&lt;br&gt;
The intended flow is:&lt;br&gt;
Approved contribution&lt;br&gt;
        ↓&lt;br&gt;
MYZ ledger credit&lt;br&gt;
        ↓&lt;br&gt;
Treasury reconciliation&lt;br&gt;
        ↓&lt;br&gt;
Monero RPC staging&lt;br&gt;
        ↓&lt;br&gt;
Controlled low-value payout&lt;br&gt;
        ↓&lt;br&gt;
Independent TX verification&lt;br&gt;
        ↓&lt;br&gt;
Production automation&lt;br&gt;
One rule is non-negotiable:&lt;br&gt;
A payment must never be marked as completed without independently verifiable transaction evidence.&lt;/p&gt;

&lt;p&gt;A successful API response is not enough.&lt;br&gt;
A local database flag is not enough.&lt;br&gt;
Settlement needs independent evidence.&lt;br&gt;
Zorgax and verified knowledge&lt;br&gt;
Another major area of development is Zorgax.&lt;br&gt;
One of the principles guiding this work is:&lt;br&gt;
A conversation is not knowledge.&lt;/p&gt;

&lt;p&gt;An AI response may be useful.&lt;br&gt;
It may also be incomplete, outdated, or wrong.&lt;br&gt;
So the architecture distinguishes between different states:&lt;br&gt;
Message&lt;br&gt;
   ↓&lt;br&gt;
Candidate information&lt;br&gt;
   ↓&lt;br&gt;
Sources&lt;br&gt;
   ↓&lt;br&gt;
Evidence&lt;br&gt;
   ↓&lt;br&gt;
Review&lt;br&gt;
   ↓&lt;br&gt;
Verified Knowledge&lt;br&gt;
Our Knowledge Layer is being designed around concepts such as:&lt;br&gt;
content&lt;br&gt;
contentHash&lt;br&gt;
version&lt;br&gt;
provenance&lt;br&gt;
sources&lt;br&gt;
evidence&lt;br&gt;
visibility&lt;br&gt;
lineage&lt;br&gt;
verification status&lt;br&gt;
The objective is to allow Zorgax to assist users without treating everything generated by an AI model as verified truth.&lt;br&gt;
DevelopmentRequest&lt;br&gt;
We have also started connecting verified knowledge to software development.&lt;br&gt;
The core abstraction is called DevelopmentRequest.&lt;br&gt;
Its lifecycle looks like this:&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 / REJECTED&lt;br&gt;
A DevelopmentRequest can include:&lt;br&gt;
title&lt;br&gt;
description&lt;br&gt;
verified Knowledge references&lt;br&gt;
requirements&lt;br&gt;
acceptance tests&lt;br&gt;
required evidence&lt;br&gt;
assignee&lt;br&gt;
submission&lt;br&gt;
review&lt;br&gt;
It deliberately does not require a bounty.&lt;br&gt;
Development work and economic incentives are different concerns.&lt;br&gt;
That means this flow can exist independently:&lt;br&gt;
Verified Knowledge&lt;br&gt;
       ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
       ↓&lt;br&gt;
Developer&lt;br&gt;
       ↓&lt;br&gt;
Implementation&lt;br&gt;
       ↓&lt;br&gt;
Evidence&lt;br&gt;
       ↓&lt;br&gt;
Independent Review&lt;br&gt;
A bounty, reward, or settlement mechanism can later be attached when appropriate.&lt;br&gt;
Submission is not verification&lt;br&gt;
This is an important distinction.&lt;br&gt;
A developer submitting code does not automatically mean that the work is complete.&lt;br&gt;
And a commit reference is not sufficient evidence for every type of requirement.&lt;br&gt;
For example, imagine a DevelopmentRequest requiring:&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
A single commit cannot prove all three.
The stronger model we are building maps evidence explicitly:
{
"evidence": [
{
  "requirement": "Unit tests pass",
  "reference": "ci:test-run:4821"
},
{
  "requirement": "Security review completed",
  "reference": "review:security:913"
},
{
  "requirement": "Metaverse integration demonstrated",
  "reference": "demo:metaverse:42"
}
]
}
The goal is simple:
VERIFIED
only when
every required evidence item
has been covered
That gives VERIFIED a much stronger meaning.
Building a feedback loop
All of these components are starting to converge into the same architecture:
Real person
↓
Real activity
↓
Data / Evidence
↓
MyZubster
↓
Verified Knowledge
↓
Zorgax
↓
DevelopmentRequest
↓
Developer
↓
GitHub
↓
Tests
↓
Independent verification
↓
New Knowledge
Eventually the Metaverse can become one of the interfaces used to navigate this system.
The wallet can become one component of identity.
GitHub can preserve technical history.
Zorgax can assist with knowledge and development.
DevelopmentRequest can connect knowledge to actionable work.
But none of these components should automatically create trust by themselves.
What comes next
Our immediate engineering priorities are:&lt;/li&gt;
&lt;li&gt;Complete the Marketplace Seller-limit and authorization validation.&lt;/li&gt;
&lt;li&gt;Finish the authenticated Marketplace end-to-end flow.&lt;/li&gt;
&lt;li&gt;Continue hardening Metaverse authentication and sessions.&lt;/li&gt;
&lt;li&gt;Add privacy-safe onboarding and mission analytics.&lt;/li&gt;
&lt;li&gt;Improve realtime reliability and acceptance testing.&lt;/li&gt;
&lt;li&gt;Continue building the Zorgax verified Knowledge Layer.&lt;/li&gt;
&lt;li&gt;Strengthen DevelopmentRequest evidence verification.&lt;/li&gt;
&lt;li&gt;Connect DevelopmentRequest with GitHub and the Contribution Graph.&lt;/li&gt;
&lt;li&gt;Move MYZ accounting to durable storage before production settlement.&lt;/li&gt;
&lt;li&gt;Keep external payouts gated behind independently verified evidence.
MyZubster is still experimental.
Several important production gates remain open.
That is intentional.
Building in public should not mean publishing only successful demos.
It should also mean documenting:
what worked
what failed
why it failed
what evidence we collected
what needs to change
and what we still cannot claim
That is how we want to build MyZubster.
Not by automating trust.
By making the system increasingly inspectable, testable, and verifiable.
Repository:
&lt;a href="https://github.com/danieldirimini-myzubster/myzubster" rel="noopener noreferrer"&gt;https://github.com/danieldirimini-myzubster/myzubster&lt;/a&gt;
Website:
&lt;a href="https://www.myzubster.com" rel="noopener noreferrer"&gt;https://www.myzubster.com&lt;/a&gt;
Metaverse:
&lt;a href="https://www.myzubster.com/metaverse" rel="noopener noreferrer"&gt;https://www.myzubster.com/metaverse&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>metaverse</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>MyZubster After the Institutional Hearing: From the Metaverse to Real-World Pilots and Verifiable Knowledge</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Tue, 22 Sep 2026 15:28:58 +0000</pubDate>
      <link>https://dev.to/danielioni/myzubster-after-the-institutional-hearing-from-the-metaverse-to-real-world-pilots-and-verifiable-23lm</link>
      <guid>https://dev.to/danielioni/myzubster-after-the-institutional-hearing-from-the-metaverse-to-real-world-pilots-and-verifiable-23lm</guid>
      <description>&lt;p&gt;MyZubster After the Institutional Hearing: From the Metaverse to Real-World Pilots and Verifiable Knowledge&lt;br&gt;
September 22, 2026 — MyZubster&lt;br&gt;
Today we presented MyZubster starting from what already exists: a virtual environment that could be opened and tested live, a real pilot involving a real person, a technical history that can be linked to GitHub, a Knowledge Layer for Zorgax, and an initial structured workflow designed to transform verified knowledge into development work.&lt;br&gt;
The occasion was an institutional hearing connected to the ongoing work around Italy’s national strategy for Artificial Intelligence.&lt;br&gt;
For us, the most important part of the meeting was practical. We did not have to describe only a future vision. We were able to show how several parts of the ecosystem are already beginning to connect.&lt;br&gt;
Showing the MyZubster Metaverse&lt;br&gt;
During the hearing, we opened the MyZubster metaverse and allowed the participants to explore and test it directly.&lt;br&gt;
This gave us the opportunity to explain that, in our vision, a metaverse is not simply a virtual environment where an avatar moves around.&lt;br&gt;
The goal is to progressively build an environment where a person can enter with a digital identity, interact with other people and services, use a wallet, and connect those interactions with a verifiable history of contributions and activities.&lt;br&gt;
In this model, GitHub can play an important role.&lt;br&gt;
A commit, a pull request, a resolved issue, or a piece of software can represent technical evidence of work that was actually performed.&lt;br&gt;
A wallet can represent another component of identity and interaction.&lt;br&gt;
The metaverse therefore becomes the visible interface of a broader chain:&lt;br&gt;
person → identity → activity → contribution → evidence → knowledge → new interaction&lt;br&gt;
Nicola as a Real Pilot Case&lt;br&gt;
To make the concept concrete, we presented the case of Nicola.&lt;br&gt;
We did not present Nicola as a theoretical example, nor as scientific validation.&lt;br&gt;
He is a real person who has participated in the MyZubster ecosystem and in practical experimentation.&lt;br&gt;
One of the first cases was deliberately simple: a physical handover of kefir.&lt;br&gt;
The workflow recorded the delivery, the confirmation of receipt, and the final completion of the process.&lt;br&gt;
The handover was free, with no payment involved, and in this specific case it was not recorded as a blockchain transaction.&lt;br&gt;
The purpose of this small pilot was not to scientifically validate anything about kefir.&lt;br&gt;
The purpose was to test whether a real-world activity could be represented digitally and leave behind usable evidence.&lt;br&gt;
This leads to one of the central questions behind MyZubster:&lt;br&gt;
How can a simple activity become evidence, and how can a collection of evidence become usable knowledge?&lt;/p&gt;

&lt;p&gt;From User to Contributor and Developer&lt;br&gt;
Nicola's involvement did not stop with the pilot.&lt;br&gt;
He also tested parts of MyZubster, reported issues, and worked on his own technical software.&lt;br&gt;
During the hearing, we also explained the software he has been developing using artificial intelligence.&lt;br&gt;
The concept behind that work is to use AI to assist the creation of software, virtual environments, metaverse-related systems, and technical ideas that can potentially connect back into the MyZubster ecosystem.&lt;br&gt;
This gives us a broader model of participation:&lt;br&gt;
user → tester → contributor → developer → producer of new evidence and knowledge&lt;br&gt;
GitHub becomes important again at this stage.&lt;br&gt;
The goal is not to automatically assign value to someone simply because they have a wallet or a GitHub account.&lt;br&gt;
The goal is to be able to reconstruct, when necessary, what was actually built, tested, changed, or contributed.&lt;br&gt;
Zorgax: A Conversation Is Not Knowledge&lt;br&gt;
Another important part of the presentation focused on Zorgax.&lt;br&gt;
One of the principles behind our recent development work is simple:&lt;br&gt;
A conversation is not knowledge.&lt;/p&gt;

&lt;p&gt;An AI model can generate a convincing answer and still be wrong.&lt;br&gt;
For this reason, we have started separating different stages:&lt;br&gt;
Conversation&lt;br&gt;
     ↓&lt;br&gt;
Candidate Information&lt;br&gt;
     ↓&lt;br&gt;
Sources and Evidence&lt;br&gt;
     ↓&lt;br&gt;
Review&lt;br&gt;
     ↓&lt;br&gt;
Verified Knowledge&lt;br&gt;
     ↓&lt;br&gt;
Use by Zorgax&lt;br&gt;
We have implemented a Knowledge Layer that can preserve information such as provenance, versioning, visibility, sources, evidence, and relationships between knowledge items.&lt;br&gt;
The direction is clear:&lt;br&gt;
Zorgax can assist with research, organization, retrieval, and development, but information should not automatically become verified knowledge simply because an AI generated it.&lt;br&gt;
Turning Knowledge Into Development&lt;br&gt;
The next problem was equally important.&lt;br&gt;
Once knowledge has been verified, how do we transform it into software development?&lt;br&gt;
This led us to implement the first vertical slice of DevelopmentRequest.&lt;br&gt;
A DevelopmentRequest is designed to act as a neutral technical contract between verified knowledge and implementation work.&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 / REJECTED&lt;br&gt;
A DevelopmentRequest can contain requirements, acceptance tests, required evidence, and references to the verified Knowledge from which the request originated.&lt;br&gt;
Before creating the persistent request, the system generates a preview and a digest and requires explicit confirmation.&lt;br&gt;
The Knowledge references are also captured with their content hash and version, creating a snapshot of the information on which the development request was based.&lt;br&gt;
This is important because knowledge can evolve over time.&lt;br&gt;
A development task should be able to show which version of the knowledge it was based on.&lt;br&gt;
Development Is Separate From Payment&lt;br&gt;
We also made another architectural decision:&lt;br&gt;
A DevelopmentRequest does not automatically mean a bounty, reward, or payment.&lt;/p&gt;

&lt;p&gt;Development work should exist independently from its economic model.&lt;br&gt;
A technical request can therefore be created, assigned, implemented, submitted, and verified without automatically triggering funding or settlement.&lt;br&gt;
Payment systems can be attached later, where appropriate, as a separate layer.&lt;br&gt;
This separation is important for universities, open-source contributors, research environments, volunteers, funded work, and community experimentation.&lt;br&gt;
They do not all operate under the same economic model.&lt;br&gt;
Evidence Before Verification&lt;br&gt;
Another principle we are strengthening is the difference between submission and verification.&lt;br&gt;
Submitting code does not mean the work is verified.&lt;br&gt;
Adding a commit reference does not automatically prove that every requirement has been satisfied.&lt;br&gt;
For this reason, DevelopmentRequest includes explicit evidence requirements.&lt;br&gt;
The current work is strengthening the rule that a request should only reach VERIFIED when every required evidence item has been properly covered and reviewed.&lt;br&gt;
We also separate the contributor from the reviewer.&lt;br&gt;
The person who created or implemented the work should not automatically be the person who independently verifies it.&lt;br&gt;
This gives us a much clearer chain:&lt;br&gt;
Knowledge&lt;br&gt;
   ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
   ↓&lt;br&gt;
Developer&lt;br&gt;
   ↓&lt;br&gt;
Implementation&lt;br&gt;
   ↓&lt;br&gt;
Tests and Evidence&lt;br&gt;
   ↓&lt;br&gt;
Independent Review&lt;br&gt;
   ↓&lt;br&gt;
Verified Result&lt;br&gt;
   ↓&lt;br&gt;
New Knowledge&lt;br&gt;
Connecting Everything Together&lt;br&gt;
When these pieces are combined, the broader MyZubster architecture becomes easier to understand:&lt;br&gt;
Real Person&lt;br&gt;
    ↓&lt;br&gt;
Real-World Activity&lt;br&gt;
    ↓&lt;br&gt;
Data / Evidence&lt;br&gt;
    ↓&lt;br&gt;
MyZubster&lt;br&gt;
    ↓&lt;br&gt;
Knowledge&lt;br&gt;
    ↓&lt;br&gt;
Zorgax / AI Assistance&lt;br&gt;
    ↓&lt;br&gt;
DevelopmentRequest&lt;br&gt;
    ↓&lt;br&gt;
Developer&lt;br&gt;
    ↓&lt;br&gt;
Code / GitHub&lt;br&gt;
    ↓&lt;br&gt;
Tests&lt;br&gt;
    ↓&lt;br&gt;
Independent Verification&lt;br&gt;
    ↓&lt;br&gt;
New Knowledge&lt;br&gt;
    ↓&lt;br&gt;
Wallet / Identity&lt;br&gt;
    ↓&lt;br&gt;
MyZubster Metaverse&lt;br&gt;
    ↓&lt;br&gt;
New Activities&lt;br&gt;
This also helps explain what MyZubster is not trying to become.&lt;br&gt;
We are not trying to build only a chatbot.&lt;br&gt;
And we are not trying to build only a metaverse.&lt;br&gt;
We are trying to build the connection between people, artificial intelligence, knowledge, software development, identity, evidence, and verifiable contributions.&lt;br&gt;
The University Path&lt;br&gt;
During the hearing, we also explained the dialogue we have started with universities and research groups.&lt;br&gt;
We have contacted academic teams working in areas such as artificial intelligence, agriculture and food science, fermentation, circular economy, LCA/LCSA, water management, monitoring, and impact measurement.&lt;br&gt;
We were careful not to present these discussions as formal partnerships.&lt;br&gt;
In several cases we have shared documentation, received requests for additional information, or started preliminary conversations.&lt;br&gt;
At this stage, we are waiting for further evaluations and feedback.&lt;br&gt;
During the institutional discussion, we were encouraged to continue exploring the university path, with particular attention to the University of Bologna for the AI-related aspects of the project.&lt;br&gt;
A possible future discussion involving Professor Michela Milano was also mentioned.&lt;br&gt;
At this stage, this should be understood as a possible next contact or academic direction, not as an already established collaboration.&lt;br&gt;
Why Universities Matter&lt;br&gt;
This university dimension is important because it defines a boundary between what software can do and what requires scientific expertise.&lt;br&gt;
MyZubster can build workflows, traceability systems, software, knowledge infrastructure, and evidence mechanisms.&lt;br&gt;
But when a pilot becomes a scientific experiment, other requirements become necessary:&lt;br&gt;
protocols, methodology, measurements, controls, ethics, safety, scientific interpretation, KPIs, and validation.&lt;br&gt;
This is where universities and research institutions can play an essential role.&lt;br&gt;
The AI should assist the process.&lt;br&gt;
It should not replace scientific responsibility.&lt;br&gt;
The LIFE 2027 Direction&lt;br&gt;
We also discussed the exploratory LIFE 2027 path.&lt;br&gt;
At this stage, there is no approved or funded MyZubster LIFE project.&lt;br&gt;
The work is still exploratory.&lt;br&gt;
The idea is to start from small real-world cases and determine whether some of them can evolve into scientifically structured pilots.&lt;br&gt;
Areas we have explored include:&lt;br&gt;
kefir and fermentation, circular water, circular economy, Living Labs, traceability, and measurable environmental or social impact.&lt;br&gt;
The important principle remains the same:&lt;br&gt;
MyZubster can help collect data, structure evidence, connect people and tools, and preserve knowledge.&lt;br&gt;
Scientific validation must come from the appropriate experts and institutions.&lt;br&gt;
AI as an Assistant, Not as the Final Authority&lt;br&gt;
The hearing also gave us the opportunity to clarify how we see the role of artificial intelligence.&lt;br&gt;
The objective is not to automate responsibility.&lt;br&gt;
The objective is to use AI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;help people navigate complex information;&lt;/li&gt;
&lt;li&gt;connect problems with relevant knowledge;&lt;/li&gt;
&lt;li&gt;assist software development;&lt;/li&gt;
&lt;li&gt;organize evidence;&lt;/li&gt;
&lt;li&gt;improve traceability;&lt;/li&gt;
&lt;li&gt;preserve useful knowledge;&lt;/li&gt;
&lt;li&gt;help transform verified knowledge into actionable development work.
The final responsibility for consequential decisions should remain with people.
What We Learned From the Hearing
The hearing forced us to explain MyZubster without hiding behind technical complexity.
That was useful.
The project can ultimately be described in a much simpler way:
We start from real people, collect real evidence, use artificial intelligence to assist the process, and try to make the path from an idea to something actually built increasingly verifiable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The metaverse is one interface.&lt;br&gt;
The wallet is one tool.&lt;br&gt;
GitHub preserves part of the technical history.&lt;br&gt;
Zorgax connects assistance and knowledge.&lt;br&gt;
DevelopmentRequest connects knowledge with development work.&lt;br&gt;
Developers build.&lt;br&gt;
Other people review.&lt;br&gt;
Universities can help define the scientific method when the process enters the research domain.&lt;br&gt;
What Comes Next&lt;br&gt;
The next step returns to engineering.&lt;br&gt;
We are continuing to strengthen DevelopmentRequest, especially the relationship between required evidence and verification.&lt;br&gt;
After that, the goal is to progressively connect DevelopmentRequest with the Contribution Graph and GitHub activity.&lt;br&gt;
At the same time, we will continue developing the Zorgax Knowledge Layer and wait for the next steps emerging from the institutional and university discussions.&lt;br&gt;
The hearing was not an endpoint.&lt;br&gt;
It was another real test of the question behind MyZubster:&lt;br&gt;
Can we build an ecosystem where people, AI, software, and virtual environments collaborate without automating trust — but instead making what happened increasingly verifiable?&lt;/p&gt;

&lt;p&gt;That is what we are trying to build.&lt;br&gt;
MyZubster&lt;br&gt;
Open Source • Verified Knowledge • Zorgax • Metaverse • Developers • Community • Research&lt;/p&gt;

</description>
      <category>metaverse</category>
      <category>real</category>
      <category>world</category>
      <category>pilots</category>
    </item>
    <item>
      <title>Building a Verified Knowledge Layer for Zorgax — and Turning It Into a Developer Marketplace</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Tue, 22 Sep 2026 06:18:14 +0000</pubDate>
      <link>https://dev.to/danielioni/building-a-verified-knowledge-layer-for-zorgax-and-turning-it-into-a-developer-marketplace-36c9</link>
      <guid>https://dev.to/danielioni/building-a-verified-knowledge-layer-for-zorgax-and-turning-it-into-a-developer-marketplace-36c9</guid>
      <description>&lt;p&gt;Building a Verified Knowledge Layer for Zorgax — and Turning It Into a Developer Marketplace&lt;br&gt;
How we moved Zorgax from a conversational assistant toward a persistent, reviewable knowledge system — and what comes next for MyZubster Development.&lt;br&gt;
During the last development cycle of MyZubster, we reached an important architectural question:&lt;br&gt;
What happens when an AI assistant stops being only a chat interface and starts accumulating knowledge about the system it helps build?&lt;/p&gt;

&lt;p&gt;For Zorgax, our answer is not “let the model remember everything.”&lt;br&gt;
It is almost the opposite.&lt;br&gt;
We are building a verified knowledge layer where information has provenance, review status, visibility rules, evidence, and an explicit path from discovery to publication.&lt;br&gt;
This is the first step toward something larger: Zorgax Development, a marketplace where verified knowledge can become specifications, development requests, bounties, implementations, reusable modules, and new knowledge.&lt;br&gt;
The Problem: Chat Is Not Knowledge&lt;br&gt;
An AI conversation can contain useful information, but that does not make every statement true.&lt;br&gt;
The same applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;web search results,&lt;/li&gt;
&lt;li&gt;repository observations,&lt;/li&gt;
&lt;li&gt;user messages,&lt;/li&gt;
&lt;li&gt;model-generated explanations,&lt;/li&gt;
&lt;li&gt;old documentation,&lt;/li&gt;
&lt;li&gt;test output,&lt;/li&gt;
&lt;li&gt;roadmap ideas.
We therefore started with one fundamental rule:
message != knowledge
candidate != verified
verified != public
This distinction is becoming one of the most important architectural boundaries inside Zorgax.
Instead of allowing the assistant to silently “learn” whatever appears in a conversation, knowledge goes through an explicit lifecycle.
We Already Had More Infrastructure Than We Expected
Before creating another database or another model, we audited the existing MyZubster architecture.
We found that the project already contained several useful building blocks:
KnowledgeContribution
Knowledge reward flows
Knowledge evidence
Evidence hashing
ResearchDocument
ZorgaxMemory
MYZ reward lifecycle
Independent review
That changed the implementation strategy.
Rather than creating a completely separate KnowledgeAsset system, we extended the existing knowledge infrastructure and made Zorgax a consumer and producer of that system.
This matters because duplicated truth systems eventually disagree.
We want one canonical knowledge lifecycle.
The New Zorgax Knowledge Flow
The first implemented vertical slice now looks like this:
User / Engineering Work
    ↓
Zorgax Knowledge Preview
    ↓
Deterministic SHA-256 Digest
    ↓
Explicit Human Confirmation
    ↓
PENDING_REVIEW
    ↓
Independent Review
    ↓
APPROVED
    ↓
Internal Zorgax Retrieval
    ↓
Explicit Publication
    ↓
PUBLIC Knowledge
There are several deliberate safety boundaries inside this flow.&lt;/li&gt;
&lt;li&gt;Zorgax Does Not Persist Knowledge Automatically
When knowledge is prepared, Zorgax first creates a preview.
Conceptually:
{
title: "Kefir community contract",
category: "marketplace",
description: "Kefir culture listings are FREE-only."
}
A deterministic SHA-256 digest is generated from the normalized preview.
The user then receives an explicit confirmation token such as:
CONFERMA a1b2c3d4
Nothing persistent has happened yet.
Only after the exact preview is confirmed can it enter the knowledge database.
If the preview changes after confirmation, the digest changes and the write is rejected.
This gives us a useful invariant:
Human confirmation applies to the exact data being persisted, not merely to the general intention to save something.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;New Knowledge Starts as INTERNAL
A confirmed knowledge contribution does not immediately become public documentation.
It starts as:
status     = PENDING_REVIEW
visibility = INTERNAL
That gives us two independent dimensions:
verification state
visibility state
They are intentionally separate.
For example:
PENDING_REVIEW + INTERNAL
APPROVED       + INTERNAL
APPROVED       + PUBLIC
REWARDED       + PUBLIC
A contribution can therefore be verified without automatically becoming public.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Legacy Knowledge Fails Closed&lt;br&gt;
One subtle problem appears when adding visibility rules to an existing database.&lt;br&gt;
What should happen to older records that do not yet contain a visibility field?&lt;br&gt;
We chose the conservative behavior:&lt;br&gt;
missing visibility = INTERNAL&lt;br&gt;
Not PUBLIC.&lt;br&gt;
That means deploying the new feature cannot accidentally expose historical knowledge.&lt;br&gt;
This is a small implementation detail, but it represents a larger rule we use throughout MyZubster:&lt;br&gt;
When authorization or privacy metadata is missing, fail closed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Public and Internal Retrieval Are Different&lt;br&gt;
Zorgax now distinguishes two knowledge scopes.&lt;br&gt;
For normal or guest requests:&lt;br&gt;
PUBLIC knowledge only&lt;br&gt;
For explicitly authorized internal/admin contexts:&lt;br&gt;
PUBLIC + INTERNAL verified knowledge&lt;br&gt;
The assistant never receives PENDING_REVIEW or REJECTED contributions as canonical context.&lt;br&gt;
The verified states currently accepted by retrieval are:&lt;br&gt;
APPROVED&lt;br&gt;
REWARD_ELIGIBLE&lt;br&gt;
REWARDED&lt;br&gt;
That gives us a much stronger model than “search every document and put it into the prompt.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verified Knowledge Is Injected Into the Zorgax Prompt&lt;br&gt;
Once retrieval was working, we connected it to the shared Zorgax assistant prompt.&lt;br&gt;
The runtime context can now contain a section conceptually similar to:&lt;br&gt;
INTERNAL VERIFIED KNOWLEDGE&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;[K1] Public marketplace invariant&lt;br&gt;
status=APPROVED&lt;br&gt;
visibility=PUBLIC&lt;br&gt;
category=marketplace&lt;/p&gt;

&lt;p&gt;Kefir culture listings are FREE-only.&lt;br&gt;
Internal items are injected only when the request has the appropriate scope.&lt;br&gt;
This means Zorgax can now answer using three different classes of context:&lt;br&gt;
Canonical runtime facts&lt;br&gt;
Verified internal/public knowledge&lt;br&gt;
Live external research&lt;br&gt;
Those sources are not treated as equivalent.&lt;br&gt;
That distinction will become increasingly important as the system grows.&lt;br&gt;
Knowledge Is Not the Same as Memory&lt;br&gt;
MyZubster already has ZorgaxMemory, but we intentionally did not turn it into the canonical knowledge database.&lt;br&gt;
They serve different purposes.&lt;br&gt;
Zorgax Memory&lt;br&gt;
Useful for temporary/user-related conversational context.&lt;br&gt;
It already distinguishes claims such as:&lt;br&gt;
verified&lt;br&gt;
uncertain&lt;br&gt;
speculative&lt;br&gt;
fictional&lt;br&gt;
and can expire through TTL.&lt;br&gt;
ResearchDocument&lt;br&gt;
Stores retrieved/crawled material.&lt;br&gt;
It includes fields such as content hashes and crawl timestamps.&lt;br&gt;
But retrieved material is still evidence — not automatically truth.&lt;br&gt;
KnowledgeContribution&lt;br&gt;
This is where reviewed shared knowledge lives.&lt;br&gt;
That separation gives us:&lt;br&gt;
Memory&lt;br&gt;
    ≠&lt;br&gt;
Research&lt;br&gt;
    ≠&lt;br&gt;
Verified Knowledge&lt;br&gt;
We Kept Knowledge Rewards Separate From Knowledge Truth&lt;br&gt;
MyZubster already has a knowledge-to-MYZ contribution flow.&lt;br&gt;
We preserved an important invariant:&lt;br&gt;
Creating knowledge does not automatically create a reward.&lt;/p&gt;

&lt;p&gt;The lifecycle can move through states including:&lt;br&gt;
PENDING_REVIEW&lt;br&gt;
APPROVED&lt;br&gt;
REJECTED&lt;br&gt;
REWARD_ELIGIBLE&lt;br&gt;
REWARDED&lt;br&gt;
Independent review is required.&lt;br&gt;
Reward eligibility is another step.&lt;br&gt;
And final reward state requires authoritative ledger evidence.&lt;br&gt;
The knowledge system therefore does not say:&lt;br&gt;
AI generated something&lt;br&gt;
→ pay someone&lt;br&gt;
Instead:&lt;br&gt;
Contribution&lt;br&gt;
→ Review&lt;br&gt;
→ Verification&lt;br&gt;
→ Eligibility&lt;br&gt;
→ Ledger process&lt;br&gt;
This will matter a lot once we connect knowledge to development work.&lt;br&gt;
We Also Fixed Zorgax Live Research&lt;br&gt;
While integrating the knowledge layer, one regression test exposed another useful architectural inconsistency.&lt;br&gt;
The Zorgax capability endpoint said that Google News was available, and the tests expected current/time-sensitive queries to use it before Wikipedia.&lt;br&gt;
But the implementation still contained:&lt;br&gt;
async function googleNewsSearch() {&lt;br&gt;
  return [];&lt;br&gt;
}&lt;br&gt;
The capability existed conceptually, but not operationally.&lt;br&gt;
We implemented a lightweight Google News RSS fallback without introducing another parsing dependency.&lt;br&gt;
For time-sensitive queries, the search strategy now becomes conceptually:&lt;br&gt;
Brave Search&lt;br&gt;
Tavily&lt;br&gt;
Google News&lt;br&gt;
Wikipedia&lt;br&gt;
When paid search API keys are absent:&lt;br&gt;
Google News&lt;br&gt;
Wikipedia&lt;br&gt;
For non-current informational queries, Wikipedia remains a useful background fallback.&lt;br&gt;
This distinction matters because these questions are fundamentally different:&lt;br&gt;
"What is climate?"&lt;br&gt;
and:&lt;br&gt;
"What are the latest climate developments today?"&lt;br&gt;
Freshness is part of the query semantics.&lt;br&gt;
The targeted Zorgax assistant and Knowledge regression tests are now green. Full-suite verification remains a release gate before considering that stabilization cycle complete.&lt;br&gt;
Testing the Knowledge Boundary&lt;br&gt;
We added tests specifically for the new invariants.&lt;br&gt;
Among other things, the tests verify that:&lt;br&gt;
A preview does not persist data.&lt;/p&gt;

&lt;p&gt;Changing a preview invalidates its digest.&lt;/p&gt;

&lt;p&gt;Confirmed knowledge enters as PENDING_REVIEW.&lt;/p&gt;

&lt;p&gt;New contributions default to INTERNAL.&lt;/p&gt;

&lt;p&gt;Public retrieval returns only explicitly PUBLIC knowledge.&lt;/p&gt;

&lt;p&gt;Internal retrieval can include verified INTERNAL knowledge.&lt;/p&gt;

&lt;p&gt;Unreviewed knowledge never reaches the assistant prompt.&lt;/p&gt;

&lt;p&gt;Guest prompts cannot receive INTERNAL knowledge.&lt;/p&gt;

&lt;p&gt;Admin/internal prompts can receive INTERNAL knowledge.&lt;/p&gt;

&lt;p&gt;Knowledge retrieval fails safely when MongoDB is unavailable.&lt;br&gt;
The current focused regression set for this vertical slice passes:&lt;br&gt;
5 test suites&lt;br&gt;
25 tests&lt;br&gt;
25 passing&lt;br&gt;
We also integrated the work using an isolated Git worktree so an unrelated Zorgax research fix and another untracked verifier project were not accidentally mixed into the Knowledge commit.&lt;br&gt;
That operational discipline matters too.&lt;br&gt;
A reliable architecture can still be damaged by careless integration.&lt;br&gt;
The Larger Goal: Zorgax Development&lt;br&gt;
The Knowledge DB is not the final product.&lt;br&gt;
It is infrastructure for the next layer.&lt;br&gt;
We want knowledge to become executable development coordination.&lt;br&gt;
The future loop looks like this:&lt;br&gt;
Engineering Work&lt;br&gt;
      ↓&lt;br&gt;
Evidence&lt;br&gt;
      ↓&lt;br&gt;
Candidate Knowledge&lt;br&gt;
      ↓&lt;br&gt;
Verification&lt;br&gt;
      ↓&lt;br&gt;
Knowledge DB&lt;br&gt;
      ↓&lt;br&gt;
Specification&lt;br&gt;
      ↓&lt;br&gt;
Development Request&lt;br&gt;
      ↓&lt;br&gt;
Proposal&lt;br&gt;
      ↓&lt;br&gt;
Bounty&lt;br&gt;
      ↓&lt;br&gt;
Implementation&lt;br&gt;
      ↓&lt;br&gt;
Tests&lt;br&gt;
      ↓&lt;br&gt;
Verification&lt;br&gt;
      ↓&lt;br&gt;
Accepted Delivery&lt;br&gt;
      ↓&lt;br&gt;
Reward&lt;br&gt;
      ↓&lt;br&gt;
Reusable Module&lt;br&gt;
      ↓&lt;br&gt;
New Knowledge&lt;br&gt;
This is the foundation of what we call Zorgax Development.&lt;br&gt;
Knowledge Should Be Open. Execution Has Value.&lt;br&gt;
We do not want to put a paywall around every technical fact.&lt;br&gt;
The more interesting economic model is:&lt;br&gt;
Knowledge is open. Execution has value.&lt;/p&gt;

&lt;p&gt;A verified architecture decision can be public.&lt;br&gt;
A privacy invariant can be public.&lt;br&gt;
A testing pattern can be public.&lt;br&gt;
But someone may still need help turning that knowledge into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an implementation,&lt;/li&gt;
&lt;li&gt;an integration,&lt;/li&gt;
&lt;li&gt;a migration,&lt;/li&gt;
&lt;li&gt;an audit,&lt;/li&gt;
&lt;li&gt;a reusable module,&lt;/li&gt;
&lt;li&gt;an automation,&lt;/li&gt;
&lt;li&gt;a deployment,&lt;/li&gt;
&lt;li&gt;a security review,&lt;/li&gt;
&lt;li&gt;a verified delivery.
That is where a development marketplace becomes useful.
A Future Development Request Could Look Like This
Instead of publishing only free-form job descriptions, Zorgax could generate machine-readable development requests from verified knowledge.
For example:
{
"title": "Add verified Knowledge retrieval to an assistant",
"domain": "ai-infrastructure",
"requirements": [
"Only reviewed knowledge can enter canonical context",
"Internal knowledge must never reach guest users",
"Persistent writes require explicit confirmation",
"Legacy records must fail closed"
],
"acceptanceTests": [
"guest receives PUBLIC knowledge only",
"admin may receive INTERNAL knowledge",
"PENDING_REVIEW records are excluded"
],
"evidenceRequired": [
"passing tests",
"commit reference",
"review record"
]
}
That request could then become:
DevelopmentRequest
→ Proposal
→ Bounty
→ Delivery
→ Verification
The knowledge itself becomes part of the specification.
Evidence-Based Reputation Instead of Stars
A development marketplace also needs reputation.
We do not want reputation to be only:
★★★★★
Instead, reputation can be derived from actual evidence:&lt;/li&gt;
&lt;li&gt;accepted pull requests,&lt;/li&gt;
&lt;li&gt;verified deliveries,&lt;/li&gt;
&lt;li&gt;passing contract tests,&lt;/li&gt;
&lt;li&gt;maintained modules,&lt;/li&gt;
&lt;li&gt;successful security reviews,&lt;/li&gt;
&lt;li&gt;useful knowledge contributions,&lt;/li&gt;
&lt;li&gt;independent reviews,&lt;/li&gt;
&lt;li&gt;resolved disputes,&lt;/li&gt;
&lt;li&gt;reverted or failed deliveries.
The goal is not to create a popularity score.
The goal is to answer:
What has this contributor demonstrably delivered?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selective Decentralization&lt;br&gt;
We are also interested in decentralized verification, but that does not mean putting the entire Knowledge DB on-chain.&lt;br&gt;
That would be expensive, inflexible, and unnecessary.&lt;br&gt;
A more useful split is:&lt;br&gt;
Off-chain&lt;br&gt;
documentation&lt;br&gt;
source code&lt;br&gt;
knowledge content&lt;br&gt;
search indexes&lt;br&gt;
embeddings&lt;br&gt;
development artifacts&lt;br&gt;
Verifiable / potentially on-chain&lt;br&gt;
content hashes&lt;br&gt;
authorship references&lt;br&gt;
licenses&lt;br&gt;
bounty references&lt;br&gt;
acceptance commitments&lt;br&gt;
settlement references&lt;br&gt;
evidence anchors&lt;br&gt;
The chain can help verify commitments.&lt;br&gt;
It does not need to become the document database.&lt;br&gt;
Search and Embeddings Will Be Derived, Not Canonical&lt;br&gt;
The current MVP can work with MongoDB and structured filtering.&lt;br&gt;
Later we can add:&lt;br&gt;
full-text search&lt;br&gt;
semantic search&lt;br&gt;
embeddings&lt;br&gt;
vector indexes&lt;br&gt;
graph relationships&lt;br&gt;
But those will be derived indexes.&lt;br&gt;
The canonical object remains the reviewed Knowledge record.&lt;br&gt;
This prevents a vector database from silently becoming the definition of truth.&lt;br&gt;
Automatically Generated Knowledge — Without Automatically Generated Truth&lt;br&gt;
Eventually, Zorgax should be able to observe engineering evidence such as:&lt;br&gt;
commits&lt;br&gt;
test results&lt;br&gt;
pull requests&lt;br&gt;
architecture decisions&lt;br&gt;
runtime contracts&lt;br&gt;
evidence hashes&lt;br&gt;
documentation changes&lt;br&gt;
and propose new Knowledge candidates automatically.&lt;br&gt;
For example:&lt;br&gt;
Commit:&lt;br&gt;
fix(kefir): enforce free-only culture donations&lt;/p&gt;

&lt;p&gt;Tests:&lt;br&gt;
kefirMarketplaceContract&lt;br&gt;
kefirHandDelivery&lt;/p&gt;

&lt;p&gt;Extracted candidate:&lt;br&gt;
"Kefir culture listings in the community marketplace are FREE-only."&lt;br&gt;
But the important word is candidate.&lt;br&gt;
Automation can accelerate extraction.&lt;br&gt;
It should not silently promote its own conclusions to verified truth.&lt;br&gt;
So the future system remains:&lt;br&gt;
automatic extraction&lt;br&gt;
        ↓&lt;br&gt;
candidate&lt;br&gt;
        ↓&lt;br&gt;
evidence&lt;br&gt;
        ↓&lt;br&gt;
verification policy / human review&lt;br&gt;
        ↓&lt;br&gt;
canonical knowledge&lt;br&gt;
What Comes Next&lt;br&gt;
The immediate roadmap is now clearer.&lt;br&gt;
We want to extend Knowledge records with stronger provenance and versioning, connect engineering evidence automatically, improve internal search, expose selected verified assets through the public MyZubster Knowledge site, and then introduce the first DevelopmentRequest lifecycle.&lt;br&gt;
From there, Zorgax can begin transforming questions into structured work.&lt;br&gt;
A user could eventually ask:&lt;br&gt;
“Can MyZubster support verified repair services in the Marketplace?”&lt;/p&gt;

&lt;p&gt;Instead of producing only an answer, Zorgax could reason through the existing Knowledge DB and generate:&lt;br&gt;
Known architecture&lt;br&gt;
Missing capability&lt;br&gt;
Required invariants&lt;br&gt;
DevelopmentRequest&lt;br&gt;
Acceptance tests&lt;br&gt;
Evidence requirements&lt;br&gt;
Potential bounty&lt;br&gt;
That is where the assistant becomes more than a chatbot.&lt;br&gt;
It becomes part of the development coordination layer.&lt;br&gt;
The Direction&lt;br&gt;
The architecture we are building can be summarized with one loop:&lt;br&gt;
QUESTION&lt;br&gt;
   ↓&lt;br&gt;
KNOWLEDGE&lt;br&gt;
   ↓&lt;br&gt;
ARCHITECTURE&lt;br&gt;
   ↓&lt;br&gt;
DEVELOPMENT REQUEST&lt;br&gt;
   ↓&lt;br&gt;
IMPLEMENTATION&lt;br&gt;
   ↓&lt;br&gt;
TESTS&lt;br&gt;
   ↓&lt;br&gt;
VERIFICATION&lt;br&gt;
   ↓&lt;br&gt;
DELIVERY&lt;br&gt;
   ↓&lt;br&gt;
REWARD&lt;br&gt;
   ↓&lt;br&gt;
NEW KNOWLEDGE&lt;br&gt;
Zorgax is starting to sit in the middle of that loop.&lt;br&gt;
Not as an autonomous authority.&lt;br&gt;
Not as a model that “knows everything.”&lt;br&gt;
But as an evidence-aware system capable of turning verified knowledge into useful action while keeping human confirmation, review, privacy, and verification boundaries explicit.&lt;br&gt;
That is the foundation we want for Zorgax Development.&lt;br&gt;
We did not come to automate trust. We came to make trust verifiable.&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>From Automated Knowledge to a Developer Marketplace: How We’re Structuring Zorgax Development</title>
      <dc:creator>Daniel Ioni</dc:creator>
      <pubDate>Tue, 22 Sep 2026 05:47:06 +0000</pubDate>
      <link>https://dev.to/danielioni/from-automated-knowledge-to-a-developer-marketplace-how-were-structuring-zorgax-development-2fjj</link>
      <guid>https://dev.to/danielioni/from-automated-knowledge-to-a-developer-marketplace-how-were-structuring-zorgax-development-2fjj</guid>
      <description>&lt;p&gt;From Automated Knowledge to a Developer Marketplace: How We’re Structuring Zorgax Development&lt;br&gt;
Software projects usually accumulate knowledge in the worst possible places.&lt;br&gt;
Some of it lives in source code. Some is hidden inside test failures. Some appears in GitHub issues. Some survives only in deployment notes, terminal sessions, architectural decisions, or conversations between developers.&lt;br&gt;
Over time, this creates a strange situation: the project contains a huge amount of knowledge, but the knowledge itself is difficult to search, reuse, verify, or turn into new work.&lt;br&gt;
With MyZubster and Zorgax, we are starting to structure a different model.&lt;br&gt;
The idea is to build a pipeline where engineering activity produces structured knowledge automatically, that knowledge becomes part of a canonical technical knowledge base, and selected parts of it can then become the foundation of a development marketplace.&lt;br&gt;
The goal is not to sell documentation.&lt;br&gt;
The goal is to make knowledge executable.&lt;br&gt;
The problem: engineering knowledge disappears after the fix&lt;br&gt;
Consider a normal debugging session.&lt;br&gt;
A failing test leads to an investigation. The investigation reveals that a privacy field is leaking through a public API. The production code is fixed. A regression test is added. A commit is created.&lt;br&gt;
From a Git perspective, the job is done.&lt;br&gt;
But several valuable pieces of knowledge were created during that process:&lt;br&gt;
Public cultural APIs must never expose account ownership.&lt;/p&gt;

&lt;p&gt;Restricted location information must remain server-side.&lt;/p&gt;

&lt;p&gt;PRIVATE and unreleased AUTHORIZED_RELEASE locations must not expose&lt;br&gt;
public location text.&lt;/p&gt;

&lt;p&gt;Tests should verify the privacy invariant rather than obsolete field names.&lt;br&gt;
Those principles are more valuable than the individual patch.&lt;br&gt;
They can be reused in another API, another marketplace, another application, or another developer’s project.&lt;br&gt;
The same thing happened while stabilizing payments, social authentication, Seller onboarding, community exchanges, and the test architecture.&lt;br&gt;
So we started asking a different question:&lt;br&gt;
What if every important engineering decision could become reusable structured knowledge?&lt;br&gt;
Knowledge should be generated from real engineering work&lt;br&gt;
We are building the MyZubster Knowledge layer around evidence produced by the development process itself.&lt;br&gt;
Instead of writing documentation only after the fact, knowledge can be extracted from things such as:&lt;br&gt;
tests&lt;br&gt;
production fixes&lt;br&gt;
commit history&lt;br&gt;
architecture decisions&lt;br&gt;
API contracts&lt;br&gt;
security invariants&lt;br&gt;
payment rules&lt;br&gt;
deployment procedures&lt;br&gt;
incident investigations&lt;br&gt;
bounties&lt;br&gt;
verification results&lt;br&gt;
The important part is that the resulting knowledge should not simply be an AI-generated summary.&lt;br&gt;
It should have provenance.&lt;br&gt;
A knowledge entry should be connected to the implementation, tests, decisions, and version that justify it.&lt;br&gt;
Conceptually, a knowledge asset might look like this:&lt;br&gt;
{&lt;br&gt;
  "id": "knowledge-public-api-privacy-v1",&lt;br&gt;
  "title": "Public API ownership and location privacy",&lt;br&gt;
  "domain": "security",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "status": "verified",&lt;br&gt;
  "source": {&lt;br&gt;
    "repository": "myzubster",&lt;br&gt;
    "tests": [&lt;br&gt;
      "zorgaxCulturalApi.test.js"&lt;br&gt;
    ],&lt;br&gt;
    "implementation": [&lt;br&gt;
      "zorgaxCulturalController.js"&lt;br&gt;
    ]&lt;br&gt;
  },&lt;br&gt;
  "invariants": [&lt;br&gt;
    "Public event reads do not expose ownerId",&lt;br&gt;
    "Restricted location text is never public"&lt;br&gt;
  ]&lt;br&gt;
}&lt;br&gt;
Now the information is no longer just prose.&lt;br&gt;
It has identity, versioning, provenance, and an explicit contract.&lt;br&gt;
Zorgax becomes the interface to this knowledge&lt;br&gt;
Zorgax is not meant to be only a chatbot sitting in front of documentation.&lt;br&gt;
The more interesting role is to make the knowledge operational.&lt;br&gt;
A developer could ask:&lt;br&gt;
How should I design a public event API without leaking organizer identity?&lt;/p&gt;

&lt;p&gt;Zorgax could retrieve the relevant architectural knowledge and explain the pattern.&lt;br&gt;
But that is only the first layer.&lt;br&gt;
The user could then say:&lt;br&gt;
Apply this architecture to my project.&lt;/p&gt;

&lt;p&gt;At that point we move from knowledge retrieval into development work.&lt;br&gt;
That transition is where Zorgax Development becomes important.&lt;br&gt;
From knowledge to development requests&lt;br&gt;
We are structuring Zorgax Development around a simple progression:&lt;br&gt;
Question&lt;br&gt;
   ↓&lt;br&gt;
Knowledge&lt;br&gt;
   ↓&lt;br&gt;
Architecture&lt;br&gt;
   ↓&lt;br&gt;
Development request&lt;br&gt;
   ↓&lt;br&gt;
Proposal&lt;br&gt;
   ↓&lt;br&gt;
Implementation&lt;br&gt;
   ↓&lt;br&gt;
Tests&lt;br&gt;
   ↓&lt;br&gt;
Verification&lt;br&gt;
   ↓&lt;br&gt;
Delivery&lt;br&gt;
This creates a natural bridge between an AI knowledge system and a developer marketplace.&lt;br&gt;
Someone may start by reading a free article about payment verification.&lt;br&gt;
Then they ask Zorgax how that architecture would apply to their application.&lt;br&gt;
Zorgax can produce a technical specification.&lt;br&gt;
That specification can become a development request.&lt;br&gt;
A developer, team, or eventually an authorized development agent can propose an implementation.&lt;br&gt;
The implementation can be tested against explicit acceptance criteria.&lt;br&gt;
Only then does the work become a verified delivery.&lt;br&gt;
Knowledge is open. Execution has value.&lt;br&gt;
This distinction is central to the model.&lt;br&gt;
We do not want to build a platform where every useful idea disappears behind a paywall.&lt;br&gt;
Open knowledge creates trust, improves the ecosystem, helps developers learn, and allows technical claims to be examined publicly.&lt;br&gt;
The commercial layer begins when someone wants that knowledge transformed into a result.&lt;br&gt;
The model we are exploring is:&lt;br&gt;
OPEN&lt;/p&gt;

&lt;p&gt;architecture&lt;br&gt;
engineering principles&lt;br&gt;
public documentation&lt;br&gt;
security patterns&lt;br&gt;
testing strategies&lt;br&gt;
basic implementation guidance&lt;/p&gt;

&lt;p&gt;MONETIZED&lt;/p&gt;

&lt;p&gt;custom implementation&lt;br&gt;
integration&lt;br&gt;
migration&lt;br&gt;
security review&lt;br&gt;
technical audit&lt;br&gt;
verified delivery&lt;br&gt;
reusable production modules&lt;br&gt;
development bounties&lt;br&gt;
ongoing support&lt;br&gt;
This is similar to open-source software.&lt;br&gt;
The source can be open while professional implementation still has economic value.&lt;br&gt;
Building a marketplace around verified development&lt;br&gt;
A development marketplace should not work like a generic gig board.&lt;br&gt;
Software work has structure.&lt;br&gt;
A request can have requirements, a repository, tests, acceptance criteria, dependencies, security constraints, budget, and an expected delivery artifact.&lt;br&gt;
So a development request could eventually be represented explicitly:&lt;br&gt;
{&lt;br&gt;
  "title": "Add privacy-safe event locations",&lt;br&gt;
  "repository": "example/project",&lt;br&gt;
  "requirements": [&lt;br&gt;
    "Public API must not expose account ownership",&lt;br&gt;
    "Exact location must remain private",&lt;br&gt;
    "Existing organizer access must continue working"&lt;br&gt;
  ],&lt;br&gt;
  "acceptance": {&lt;br&gt;
    "testsRequired": true,&lt;br&gt;
    "humanReviewRequired": true&lt;br&gt;
  },&lt;br&gt;
  "reward": {&lt;br&gt;
    "asset": "MYZ",&lt;br&gt;
    "amount": 500&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
This is far more useful than:&lt;br&gt;
“Need backend developer, $200.”&lt;/p&gt;

&lt;p&gt;The task becomes machine-readable.&lt;br&gt;
Zorgax can understand it.&lt;br&gt;
Developers can reason about it.&lt;br&gt;
Tests can verify parts of it.&lt;br&gt;
Payment systems can reference it.&lt;br&gt;
And the knowledge produced while solving it can potentially return to the ecosystem.&lt;br&gt;
Development creates more knowledge&lt;br&gt;
This produces an interesting feedback loop.&lt;br&gt;
Imagine that a developer completes the task above.&lt;br&gt;
During implementation, they discover an edge case involving delayed location release.&lt;br&gt;
They add a new test and document the rule.&lt;br&gt;
That new rule becomes another knowledge asset.&lt;br&gt;
Now the system looks like this:&lt;br&gt;
Knowledge&lt;br&gt;
   ↓&lt;br&gt;
Development&lt;br&gt;
   ↓&lt;br&gt;
Implementation&lt;br&gt;
   ↓&lt;br&gt;
Verification&lt;br&gt;
   ↓&lt;br&gt;
New knowledge&lt;br&gt;
   ↓&lt;br&gt;
Better future development&lt;br&gt;
The marketplace is no longer consuming knowledge.&lt;br&gt;
It is producing it.&lt;br&gt;
That is one of the ideas we find most interesting.&lt;br&gt;
Knowledge assets can become reusable modules&lt;br&gt;
Some solutions will eventually move beyond documentation.&lt;br&gt;
A repeated architecture may become a reusable module.&lt;br&gt;
For example, after implementing the same pattern several times, the platform could evolve from:&lt;br&gt;
Knowledge:&lt;br&gt;
"How to verify server-owned payment expectations"&lt;br&gt;
to:&lt;br&gt;
Reference implementation&lt;br&gt;
and eventually to:&lt;br&gt;
Reusable verified module&lt;br&gt;
Examples could include authentication, payment verification, marketplace listings, identity linking, privacy projections, entitlement management, reputation, escrow coordination, or development workflow automation.&lt;br&gt;
The knowledge explains why the module exists.&lt;br&gt;
The tests explain what it guarantees.&lt;br&gt;
The implementation makes it usable.&lt;br&gt;
That combination is much more valuable than code alone.&lt;br&gt;
What decentralization actually needs&lt;br&gt;
We are also exploring how this could support a decentralized marketplace.&lt;br&gt;
That does not mean putting everything on a blockchain.&lt;br&gt;
Most engineering knowledge does not belong on-chain.&lt;br&gt;
Large documents, source code, conversations, and specifications are better stored in Git repositories, databases, or content-addressed storage.&lt;br&gt;
A decentralized layer is more useful for small pieces of verifiable state.&lt;br&gt;
For example:&lt;br&gt;
content hashes&lt;br&gt;
authorship attestations&lt;br&gt;
licenses&lt;br&gt;
ownership&lt;br&gt;
bounty references&lt;br&gt;
payment settlement&lt;br&gt;
delivery acceptance&lt;br&gt;
reputation events&lt;br&gt;
verification records&lt;br&gt;
This allows the marketplace to prove that a particular artifact existed, who published it, which version was accepted, and how a reward was settled without forcing the entire development process onto a blockchain.&lt;br&gt;
Human approval remains important&lt;br&gt;
AI can help generate specifications, search knowledge, compare architectures, prepare code changes, and analyze tests.&lt;br&gt;
But development marketplaces involve consequential actions.&lt;br&gt;
Publishing code, spending money, releasing escrow, accepting a delivery, or changing production infrastructure should not silently happen because an AI model decided it looked correct.&lt;br&gt;
The architecture we are moving toward keeps explicit boundaries around those actions.&lt;br&gt;
Zorgax can advise.&lt;br&gt;
Zorgax can prepare.&lt;br&gt;
Zorgax can verify evidence.&lt;br&gt;
But important execution steps should remain attributable and reviewable.&lt;br&gt;
That principle also makes the marketplace easier to audit.&lt;br&gt;
Reputation should come from evidence&lt;br&gt;
Traditional marketplace reputation often becomes a star rating.&lt;br&gt;
For software development, we can do better.&lt;br&gt;
A development reputation graph could be based on evidence such as:&lt;br&gt;
accepted pull requests&lt;br&gt;
verified deliveries&lt;br&gt;
passing contract tests&lt;br&gt;
maintained modules&lt;br&gt;
resolved bounties&lt;br&gt;
security reviews&lt;br&gt;
documented knowledge contributions&lt;br&gt;
reverted or disputed deliveries&lt;br&gt;
A developer who repeatedly produces maintainable code with good tests should accumulate a very different reputation from someone who simply receives five-star ratings.&lt;br&gt;
This also gives AI systems better signals when helping users choose contributors.&lt;br&gt;
MYZ can represent internal economic coordination&lt;br&gt;
The MyZubster ecosystem already distinguishes between internal accounting and external settlement.&lt;br&gt;
That same separation can be useful here.&lt;br&gt;
Development rewards could be denominated in MYZ where appropriate, while external settlement remains a separate concern.&lt;br&gt;
The important rule is that rewards should be based on verified state.&lt;br&gt;
A test passing should not magically create money.&lt;br&gt;
A pull request existing should not automatically mean a bounty is complete.&lt;br&gt;
A delivery needs an explicit lifecycle.&lt;br&gt;
Conceptually:&lt;br&gt;
CREATED&lt;br&gt;
  ↓&lt;br&gt;
FUNDED&lt;br&gt;
  ↓&lt;br&gt;
IN_PROGRESS&lt;br&gt;
  ↓&lt;br&gt;
DELIVERED&lt;br&gt;
  ↓&lt;br&gt;
VERIFIED&lt;br&gt;
  ↓&lt;br&gt;
ACCEPTED&lt;br&gt;
  ↓&lt;br&gt;
REWARDED&lt;br&gt;
Disputes and cancellations need their own states as well.&lt;br&gt;
This prevents the marketplace from confusing activity with completion.&lt;br&gt;
The Knowledge site becomes the canonical layer&lt;br&gt;
DEV articles like this one explain what we are building and why.&lt;br&gt;
The MyZubster Knowledge site has a different role.&lt;br&gt;
It should become the canonical technical layer.&lt;br&gt;
Instead of storytelling, it should contain things like:&lt;br&gt;
Architecture&lt;br&gt;
Privacy invariants&lt;br&gt;
Authentication contracts&lt;br&gt;
Payment architecture&lt;br&gt;
Marketplace rules&lt;br&gt;
Testing strategy&lt;br&gt;
Development protocols&lt;br&gt;
Decision records&lt;br&gt;
Knowledge assets&lt;br&gt;
Verification rules&lt;br&gt;
That means the same engineering work can produce multiple forms of value.&lt;br&gt;
A debugging session can produce:&lt;br&gt;
a production fix&lt;br&gt;
a regression test&lt;br&gt;
a Git commit&lt;br&gt;
a knowledge entry&lt;br&gt;
a DEV article&lt;br&gt;
a reusable architecture&lt;br&gt;
a future marketplace asset&lt;br&gt;
Nothing has to be thrown away.&lt;br&gt;
Automated knowledge does not mean automated truth&lt;br&gt;
This distinction matters.&lt;br&gt;
An AI can generate thousands of documents very quickly.&lt;br&gt;
That does not create a useful knowledge system.&lt;br&gt;
Knowledge becomes valuable when it is connected to evidence.&lt;br&gt;
We want automated extraction to help answer questions such as:&lt;br&gt;
What changed?&lt;/p&gt;

&lt;p&gt;Why did it change?&lt;/p&gt;

&lt;p&gt;Which invariant does it protect?&lt;/p&gt;

&lt;p&gt;Which tests verify it?&lt;/p&gt;

&lt;p&gt;Which implementation currently enforces it?&lt;/p&gt;

&lt;p&gt;Which version introduced it?&lt;/p&gt;

&lt;p&gt;Is it still true today?&lt;br&gt;
If those questions cannot be answered, the output is probably documentation, not verified knowledge.&lt;br&gt;
The longer-term architecture&lt;br&gt;
The system we are gradually structuring can be summarized like this:&lt;br&gt;
Engineering activity&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
Evidence extraction&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
Structured Knowledge&lt;br&gt;
        │&lt;br&gt;
        ├──────────────► Public Knowledge Base&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
      Zorgax&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
Architecture / Specification&lt;br&gt;
        │&lt;br&gt;
        ▼&lt;br&gt;
Zorgax Development Marketplace&lt;br&gt;
        │&lt;br&gt;
    ┌───┼───────────────┐&lt;br&gt;
    ▼   ▼               ▼&lt;br&gt;
Bounties Services     Modules&lt;br&gt;
    │   │               │&lt;br&gt;
    └───┴───────┬───────┘&lt;br&gt;
                ▼&lt;br&gt;
         Verified Delivery&lt;br&gt;
                │&lt;br&gt;
                ▼&lt;br&gt;
             Reward&lt;br&gt;
                │&lt;br&gt;
                ▼&lt;br&gt;
        New Engineering Evidence&lt;br&gt;
                │&lt;br&gt;
                └────────► New Knowledge&lt;br&gt;
It is a loop.&lt;br&gt;
And that is intentional.&lt;br&gt;
What we are building toward&lt;br&gt;
The vision is not an AI that pretends to know everything.&lt;br&gt;
It is an ecosystem where knowledge can be traced back to real engineering work.&lt;br&gt;
Where developers can reuse that knowledge.&lt;br&gt;
Where Zorgax can turn it into actionable specifications.&lt;br&gt;
Where implementations can be commissioned through a marketplace.&lt;br&gt;
Where delivery can be verified through explicit contracts.&lt;br&gt;
Where useful solutions return to the knowledge base.&lt;br&gt;
And where the economic layer rewards actual implementation and contribution instead of simply locking information behind a paywall.&lt;br&gt;
We are still building the pieces.&lt;br&gt;
But the architecture is becoming clearer:&lt;br&gt;
open knowledge, verifiable engineering, paid execution, reusable results.&lt;br&gt;
If that loop works, a software project stops being only a repository.&lt;br&gt;
It becomes a system that learns from its own development.&lt;/p&gt;

&lt;h1&gt;
  
  
  opensource #ai #webdev #marketplace #nodejs
&lt;/h1&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>webdev</category>
      <category>marketplace</category>
    </item>
  </channel>
</rss>
