Home Doh Ref
Dohballs
  • 📁 doh_chat
  • 📁 doh_modules
    • 📦 dataforge
    • 📦 express
    • 📁 sso
    • 📁 user

uNET Protocol

Universal Network Protocol - A decentralized routing and identity layer for Doh.js applications.

Overview

uNET provides a secure, certificate-based network layer that enables:

  • Decentralized Identity: Cryptographic address certificates prove ownership
  • Flexible Routing: VPUs (Virtual Processing Units) act as routing hubs
  • Federation: Multiple VPUs can bridge for cross-network routing
  • Membership Tiers: Nodes can be anonymous, connected, or full members

Architecture

Address Format

uNET uses a two-part address format: {prefix}-{position}

Position Meaning Example
0 Reserved -
1 Always the Address Provider itself 1-1, acme-1
2+ Regular addresses issued by that provider 1-2, 1-3, acme-500

Self-Documenting Provenance: From any address like 1-5, you instantly know:

  • It was issued by 1-1 (the Address Provider for prefix "1")
  • 1-1 was authorized by 0-1 (the Prefix Root)
  • No lookup required - the trust chain is encoded in the address

Position Allocation: First-come-first-served:

  • Request a specific position (e.g., acme-deploydoh.com) - if available, it's yours
  • If taken, rejection with suggestion of next available position
  • Request null position to get next available automatically
  • Enables semantic addresses while giving requester control over collisions

Trust Hierarchy

┌─────────────────────────────────────────────────────────────────┐
│                        Trust Hierarchy                          │
│                                                                 │
│   0-1 (PREFIX_ROOT - THE single global trust anchor)            │
│    │                                                            │
│    ├──► 1-1 (ADDRESS_PROVIDER for prefix "1")                   │
│    │     │                                                      │
│    │     ├──► 1-2 (regular address)                             │
│    │     ├──► 1-3 (could be a VPU) ◄────────────────────┐       │
│    │     └──► 1-4 (another address)                      │       │
│    │                                                     │       │
│    ├──► acme-1 (ADDRESS_PROVIDER for prefix "acme")      │       │
│    │     │                                               │       │
│    │     └──► acme-500 (address in acme namespace)       │       │
│    │                                                     │       │
│    └──► [more address providers...]                      │       │
│                                                          │       │
│                          VPU (1-3) signs membership      │       │
│                                    │                     │       │
│                                    ▼                     │       │
│                          MEMBERSHIP CERT ────────────────┘       │
│                          (parallel to address chain,             │
│                           proves membership in VPU)              │
└─────────────────────────────────────────────────────────────────┘

Connection Flow

┌─────────────────────────────────────────────────────────────────┐
│   Client (1-2)                           VPU Provider (1-3)     │
│       │                                      │                  │
│       │ ─── RFD Connect ──────────────────► │                  │
│       │     (address cert + optional        │                  │
│       │      membership cert)               │                  │
│       │                                     │                  │
│       │ ◄── Connection Response ─────────── │                  │
│       │     (routing level granted)         │                  │
│       │                                     │                  │
│       │ ═══ Bidirectional Messages ═══════ │                  │
│       │                                     │                  │
└─────────────────────────────────────────────────────────────────┘

Certificate Chains

uNET uses three types of certificate chains:

1. Address Chain (Required)

Every participant must have a valid address certificate chain:

0-1 (PREFIX_ROOT - self-signed trust anchor)
 │
 └─► {prefix}-1 (ADDRESS_PROVIDER - position 1 in their prefix)
          │
          └─► {prefix}-N (ADDRESS - your identity, N >= 2)

Example:

0-1 (Prefix Root)
 └─► 1-1 (Address Provider for prefix "1")
      └─► 1-5 (Your address)

2. Membership Chain (Optional, per-VPU)

Proves membership in a specific VPU. This is parallel to the address chain, not hierarchical:

VPU's ADDRESS CERT (e.g., 1-3 - any valid address offering VPU services)
    └─► MEMBERSHIP CERT (proves you belong to that VPU)

A node can hold multiple membership certificates (member of many VPUs simultaneously). The address is portable - you keep your address when switching VPUs.

3. Bridge Chain (Optional, for federation)

Enables cross-VPU routing. Requires dual signatures from both VPUs:

BRIDGE CERT (signed by VPU A, countersigned by VPU B)

Roles

Prefix Provider (0-1)

  • THE single global trust anchor (address: 0-1)
  • Self-signed PREFIX_ROOT certificate
  • Solely responsible for authorizing Address Providers
  • Has no network connectivity requirement - uses intermediate authorities
  • Stores all CSRs and corresponding public keys for all issued prefixes

Address Provider ({prefix}-1)

  • IS position 1 in their own prefix namespace (e.g., 1-1, acme-1)
  • Authorized by the Prefix Provider (0-1)
  • Issues ADDRESS certificates to nodes (positions 2+)
  • Sets its own rules for what constitutes a valid CSR
  • Can define semantic addressing formats (domains, emails, device names, etc.)

VPU Provider (any valid address)

  • Any valid address that offers routing services (e.g., 1-3)
  • Issues MEMBERSHIP certificates (proves authorization to request routing)
  • Accepts RFD connections from nodes
  • Routes traffic between members
  • Can issue Bridge Certificates for cross-VPU routing
  • Validates user status on every connection (when require_user_auth enabled)

VPU Client

  • Holds ADDRESS certificate chain (portable across VPUs)
  • Can hold multiple MEMBERSHIP certificates (member of many VPUs)
  • Connects to VPUs for routing
  • Chooses which credentials to present per connection
  • Stores membership certs locally for persistence

Configuration

Configure uNET in your boot.pod.yaml (shared baseline) or pod.yaml (local overrides):

unet:
  enabled: true
  debug: false
  providers_base_path: '/.doh/static/unet/providers'  # Base path for provider files

  # Trusted prefix roots (array format)
  trusted_roots:
    - C: https://deploydoh.com  # Where to get C prefix root cert

  roles:
    # Client (connect to VPUs)
    client:
      enabled: true
      identity_path: null           # Custom path for identity storage
      state_path: null              # Custom path for state storage
      settings_path: null           # Custom path for settings
      memberships_path: null        # Custom path for membership certs
      vpu_connections: []           # VPU endpoints to connect to
      vpu_memberships: []           # VPU addresses for phone-home (RFDR)
      auto_connect: true            # Auto-connect on startup
      auto_reconnect: true          # Auto-reconnect on disconnect
      heartbeat_interval: 30000     # Heartbeat interval in ms
      address_provider_endpoint: null  # Endpoint to request address from
      auto_request_address: true    # Auto-request address on startup
      preferred_address: null       # Request specific address ID (e.g., "mynode")

    # Routing hub
    vpu_provider:
      enabled: false
      identity_path: null           # Custom path for identity storage
      state_path: null              # Custom path for state storage
      settings_path: null           # Custom path for settings
      database_name: 'unet'         # Database for memberships
      max_members: null             # Max members (null = unlimited)
      max_connections: null         # Max concurrent connections
      require_membership: true      # Require membership for full routing
      require_user_auth: true       # Require user auth for membership
      allow_non_members: false      # Allow non-member connections (limited routing)
      # VPU address acquisition
      address_provider_endpoint: null  # Endpoint to request VPU's address
      auto_request_address: true    # Auto-request address on startup
      preferred_address: null       # Request specific address ID (e.g., "main-vpu")

    # Issue addresses to nodes
    address_provider:
      enabled: false
      identity_path: null           # Custom path for identity storage
      state_path: null              # Custom path for state storage
      settings_path: null           # Custom path for settings
      database_name: 'unet_addresses'  # Database for address records
      max_addresses: null           # Max addresses to issue
      # Access control
      require_auth: true            # Require user auth for address requests
      allow_preferred: true         # Allow clients to request specific address IDs
      # Prefix acquisition
      prefix_provider_endpoint: null  # Endpoint to request prefix from
      auto_request_prefix: true     # Auto-request prefix on startup
      preferred_prefix: null        # Request specific prefix (e.g., "acme")

    # Trust root for a prefix namespace
    prefix_provider:
      enabled: false
      identity_path: null           # Custom path for identity storage
      state_path: null              # Custom path for state storage
      settings_path: null           # Custom path for settings
      database_name: 'unet_prefixes'  # Database for prefix records
      max_providers: null           # Max address providers to authorize
      # Access control
      require_auth: true            # Require user auth for provider authorization
      allow_preferred: true         # Allow providers to request specific prefixes

Handshake Protocol

Message Types

Category Type Direction Purpose
APC apc:request - Request address validation
apc:announce - Announce address ownership
apc:validate - Confirm/reject address claim
R r:request - Request VPU membership
r:validate - Accept/reject membership
r:capacity - Announce VPU capabilities
r:disconnect - Leave VPU cleanly
Tree Routing rfd:request:up (RFDR) ↑ UP Route request goes upstream through tree
rfd:announce:down (RFDA) ↓ DOWN Route announce follows request path back
rfd:disconnect:up (RFDD) ↑ UP Route disconnect, branch-consumed at routers
rfd:flush:down (RFDF) ↓ DOWN Flush all knowledge of entity
r:capacity:announce (RCA) ↔ LATERAL Capacity announcement (neighbor-scope, TTL=1)
DATA data - Application message
data:ack - Acknowledgment
data:error - Error response
SVC svc:publish - Announce services
svc:query - Query for services
svc:response - Service query response
Control ping - Heartbeat request
pong - Heartbeat response
error - Protocol error

Tree-Based Routing

uNET uses directional routing where messages flow through the network tree:

       VPU (root)
          │
     ┌────┴────┐
     ↓         ↓
  Router A  Router B
     │         │
     ↓         ↓
  Client X  Client Y

RFDR (Route Request) - Goes UPWARD only

  • Client sends seeking a destination
  • Each router forwards upstream until found or TTL expires
  • Carries requestPath tracking the route taken

RFDA (Route Announce) - Goes DOWNWARD only

  • Response to RFDR, follows requestPath back to requester
  • Announces found routes with metrics

RFDD (Route Disconnect) - Goes UPWARD, branch-consumed

  • Announces routes no longer available
  • Routers with alternate paths consume locally (don't forward)

RFDF (Route Flush) - Goes DOWNWARD all paths

  • Purges all knowledge about an entity
  • Forwarded to all downstream connections

RCA (Capacity Announce) - Neighbor-scope (TTL=1)

  • Announces capacity/load to direct neighbors
  • Used for load balancing

VPU Connection Flow

  1. Client connects via socket with:

    • addressCert (required) - proves identity
    • membershipCert (optional) - proves VPU membership
  2. VPU validates certificate chains against trusted roots

  3. VPU grants routing level:

    • full - Full routing (members)
    • limited - Basic routing (non-members)
  4. Messages flow bidirectionally through VPU

Core Modules

Module Purpose
unet_protocol.doh.js Main Doh module, orchestrates all components
unet_certs.js Certificate creation, signing, validation
unet_handshakes.js Message types and handshake state machine
unet_prefix_provider.js Prefix namespace management
unet_address_provider.js Address certificate issuance
unet_vpu_provider.js VPU routing hub implementation
unet_vpu_client.js Client for connecting to VPUs
unet_routing.js Routing table and path finding

API Endpoints

When unet_protocol is loaded, these routes are available:

Well-Known Discovery Endpoints

Route Method Purpose
/.well-known/unet/prefix-root-key.json GET Public key info for PREFIX_ROOT
/.well-known/unet/prefix-root.json GET Full PREFIX_ROOT certificate
/.well-known/unet/address-provider.json GET ADDRESS_PROVIDER certificate
/.well-known/unet/trusted-roots.json GET List of all trusted roots
/.well-known/unet/vpu-info.json GET VPU provider info and stats
/.well-known/unet/network-info.json GET Full network discovery info

Stats

  • GET /api/unet/stats - Get uNET status and statistics
  • GET /api/unet/vpu/stats - Get VPU-specific stats
  • GET /api/unet/vpu/connections - List connected nodes (extended info: address, isMember, userId, connectedAt, ip, type, connectionType, reachableVia, isRouter, primaryUpstream, upstreamCount, childCount)

Address Management

  • POST /api/unet/request-address - Request an address certificate
  • GET /api/unet/address/:address - Get address information

Provider Authorization

  • POST /api/unet/request-provider-cert - Request ADDRESS_PROVIDER authorization from PREFIX_ROOT

VPU Connection (Client)

  • POST /api/unet/vpu/connect - Connect to a VPU
  • POST /api/unet/vpu/disconnect - Disconnect from VPU

VPU Membership

  • POST /api/unet/vpu/request-membership - Request membership with user auth

Messaging

  • POST /api/unet/message - Send messages through VPU

RFD (Socket)

  • Socket event unet:rfd:connect - RFD connection handshake

Testing

  • POST /api/unet/test/broadcast - Send test broadcast to connected nodes

Dashboard

The Cloud Manager includes a uNET dashboard tab showing:

  • Overview - Identity, roles, VPU stats (connected nodes, members, routes)
  • Topology - Network visualization
  • Connections - Active RFD connections table
  • Messages - Real-time message activity log
  • Settings - Configuration panel

Real-time updates via socket broadcast (no polling required):

  • unet:state - Full state including vpuStats and vpuConnections
  • unet:connection - Connect/disconnect events with address
  • unet:message - Message activity

The dashboard automatically updates when:

  • Nodes connect or disconnect
  • Membership status changes
  • VPU stats change

Admin UI & Setup Wizards

The unet_admin module provides a dedicated admin interface at /unet-admin with:

Client Section

  • Overview - Guided wizard for client setup (address → membership → VPU connection)
  • VPUs - Manage VPU connections, view connection status
  • Settings - Client configuration

Client Wizard Steps:

  1. Get Address - Discover/specify address provider, optionally specify preferred address position
  2. Get Membership - Authenticate with VPU to obtain membership certificate
  3. Connect to VPU - Establish connection for message routing

Advanced Options:

  • Custom address provider endpoint (override discovered provider)
  • Preferred address ID (request specific position like mynode)
  • Address provider credentials (for providers with require_auth: true)

Providers Section

  • Overview - Summary of enabled provider roles
  • Identities - View/manage provider identities and certificates
  • Prefixes - Prefix provider management (if enabled)
  • Addresses - Address provider management (if enabled)
  • VPUs - VPU provider management with connection list
  • Settings - Provider configuration

Provider Wizards:

  • Prefix Provider Wizard - Setup as trust root, specify prefix provider endpoint
  • Address Provider Wizard - Get authorized prefix from prefix provider
  • VPU Provider Wizard - Get address and configure VPU settings

Each wizard guides through the setup process with real-time validation and capability queries to ensure proper configuration.

Socket Events

Server Broadcasts

Event Purpose
unet:state Full state including vpuStats and vpuConnections
unet:connection Connect/disconnect events with address
unet:message Message activity

Client Events

Event Purpose
unet:client:connection Client connection status changes
unet:rfd:connect RFD connection request
unet:rfdr Route For Destination Request (to VPU)
unet:rfda Route For Destination Announce (from VPU)
unet:rfdr:reject RFDR rejection
unet:ping / unet:pong Heartbeat keep-alive

Advanced Features

RFDR Phone-Home (Tree-Based Routing)

Clients can join VPUs through router intermediaries, enabling federated topology without direct connections to all VPUs.

Configuration:

unet:
  roles:
    client:
      vpu_connections:
        - https://router.deploydoh.com   # Connect through router
      vpu_memberships:
        - '1-3'                          # VPU address to phone-home to

How it works:

  1. Client connects to a router (another VPU client acting as intermediary)
  2. Client sends RFDR (Route For Destination Request) through router
  3. Router forwards request upstream to target VPU
  4. VPU validates membership through the chain
  5. VPU sends RFDA (Route For Destination Announce) back through router
  6. Messages now flow bidirectionally through the router

Provider Export/Import

Providers can be exported as gzipped tarballs for deployment across servers.

Export: Creates a portable archive containing:

  • Provider identity (keypair)
  • Certificates
  • Configuration

Import: Restores provider state on a new server, enabling:

  • Distributed deployment
  • Backup/restore
  • Multi-server setups with shared identity

Connection Status Tracking

The client tracks detailed connection status for each VPU:

{
  endpoint: 'https://vpu.example.com',
  vpuAddress: '1-2',
  lastHeartbeat: 1705123456789,
  lastCommunication: 1705123456789,
  lastError: null,
  reconnectAttempts: 0,
  isMember: true
}

Endpoint Mapping Cache:

  • Persists endpoint → VPU address mappings
  • Enables faster reconnection (skip discovery)
  • Updated when VPU address changes

Security Model

  1. Self-Documenting Provenance: Address format {prefix}-{position} encodes the entire trust chain - from any address you know who issued it (the Address Provider at {prefix}-1) without lookups
  2. Single Trust Anchor: One Prefix Root (0-1) as the global trust anchor
  3. Cryptographic Identity: Ed25519 key pairs for signing
  4. Certificate Chains: All certs validated back to the trusted root (0-1)
  5. Address Portability: Addresses are separate from VPU membership - switch VPUs while keeping your address
  6. Selective Disclosure: Nodes choose which credentials (address, memberships) to present
  7. Namespace Isolation: Different prefixes are independent address spaces, all under the same root
  8. Membership Control: VPUs control who gets full routing access via MEMBERSHIP certificates

Examples

Full Provider Stack (localhost)

# boot.pod.yaml
unet:
  enabled: true
  roles:
    prefix_provider:
      enabled: true
    address_provider:
      enabled: true
    vpu_provider:
      enabled: true
      require_membership: false
      allow_non_members: true
    client:
      enabled: true

Client Only (connect to external VPU)

# boot.pod.yaml
unet:
  enabled: true
  trusted_roots:
    - C: https://deploydoh.com
  roles:
    client:
      enabled: true
      vpu_connections:
        - https://vpu.deploydoh.com

Client with Federation (Router Mode)

# boot.pod.yaml
unet:
  enabled: true
  trusted_roots:
    - C: https://deploydoh.com
  roles:
    client:
      enabled: true
      vpu_connections:
        - https://router.deploydoh.com   # Connect through router
      vpu_memberships:
        - '1-2'                          # Phone-home to this VPU

Production VPU Provider

# boot.pod.yaml
unet:
  enabled: true
  roles:
    vpu_provider:
      enabled: true
      require_membership: true
      require_user_auth: true
      max_members: 1000
      max_connections: 5000
    client:
      enabled: true
      auto_reconnect: true
      heartbeat_interval: 30000

Reconnection Behavior

The VPU client implements robust reconnection:

  • Manual socket management (not socket.io's built-in)
  • Exponential backoff (5s → 10s → 20s → 40s → 60s max)
  • Full socket cleanup before reconnect
  • Re-authentication after reconnect
  • Stored membership certs are automatically loaded on reconnect

VPU Membership Persistence

VPU providers persist membership data to a database, ensuring memberships survive server restarts:

  • Memberships stored in unet.vpu_memberships table
  • Loaded automatically on VPU provider startup
  • Includes userId binding for user authentication validation
  • Members can reconnect after VPU restart without re-authenticating

Socket Disconnect Handling

When clients connect via socket, the VPU automatically:

  • Listens for socket disconnect events
  • Cleans up the node from connected nodes list
  • Broadcasts updated state to dashboard
  • Triggers unet:connection disconnect event

VPU Membership Authentication

VPU membership now requires user authentication by default. Users authenticate once with username/password to receive a MEMBERSHIP certificate, which is stored locally and used for subsequent connections.

Authentication Flow

Client                                 VPU Provider
   |                                        |
   | POST /api/unet/vpu/request-membership  |
   | { username, password, addressCert }    |
   |--------------------------------------->|
   |                                        | 1. Validate credentials (Users system)
   |                                        | 2. Issue MEMBERSHIP cert with userId
   |<---------------------------------------|
   | { success, membershipCert, vpuAddress }|
   |                                        |
   | (Store cert locally)                   |
   |                                        |
   | RFD Connect (Socket)                   |
   | { addressCert, membershipCert }        |
   |--------------------------------------->|
   |                                        | 1. Validate cert chains
   |                                        | 2. Check userId not suspended
   |<---------------------------------------|
   | { success, routing: 'full' }           |

User Binding

The MEMBERSHIP certificate contains the userId (username/email) in its claims. On every RFD connection, the VPU validates:

  • Certificate chain is valid (address cert → membership cert)
  • userId exists in Users system (user account not deleted)
  • User is not currently locked out (brute force protection)

Revocation Model: Validation happens at connection time, not via real-time events. If a user is deleted or locked out, their next connection attempt will be rejected. Existing connections remain active until they disconnect and try to reconnect.

CLI Commands

# Set the VPU endpoint in boot.pod.yaml
doh vpu endpoint <url>

# Join a VPU with user authentication (interactive)
doh vpu join
doh vpu join [<url>]

# Join with credentials (non-interactive)
doh vpu join -u <username> -p <password>
doh vpu join <url> -u <username> -p <password>

# Join VPU via router (federated mode)
doh vpu join <vpu-url> <router-url>
doh vpu join <vpu-url> <router-url> -u <username> -p <password>

# Check membership status
doh vpu status

# Reset all uNET data (identities, databases, settings)
doh unet-reset           # Interactive confirmation
doh unet-reset --confirm # Skip confirmation (scripting)

Examples:

# Set endpoint and join interactively
doh vpu endpoint https://deploydoh.com
doh vpu join

# Join directly with URL
doh vpu join https://deploydoh.com

# Join with credentials (scripting/CI)
doh vpu join https://deploydoh.com -u admin@site.com -p mypassword

# Join through a router (federated)
doh vpu join https://vpu.deploydoh.com https://router.deploydoh.com -u user@site.com -p pass

Configuration

# boot.pod.yaml or pod.yaml
unet:
  roles:
    vpu_provider:
      require_user_auth: true     # Require user auth (default: ON)
    client:
      vpu_connections:
        - https://deploydoh.com   # VPU endpoints to connect to

Authentication Options

VPU Provider (require_user_auth):

  • true (default): Membership requests require valid username/password credentials
  • false: Memberships can be issued without authentication

Address Provider (require_auth):

  • true (default): Address requests require valid username/password credentials
  • false: Addresses can be issued without authentication

When auth is required, credentials are passed in the request body and validated via the Users system.

# Open VPU (no auth required for membership)
unet:
  roles:
    vpu_provider:
      require_user_auth: false
      allow_non_members: true

# Open Address Provider (no auth required for addresses)
unet:
  roles:
    address_provider:
      require_auth: false

Files

doh_modules/unet/
├── README.md                    # This file
├── unet_protocol.doh.js         # Main Doh module
├── unet_certs.js                # Certificate system
├── unet_handshakes.js           # Message protocol
├── unet_prefix_provider.js      # Prefix provider
├── unet_address_provider.js     # Address provider
├── unet_vpu_provider.js         # VPU provider (with user auth)
├── unet_vpu_client.js           # VPU client
├── unet_vpu_anchor_cli.js       # VPU membership CLI (doh vpu)
├── unet_routing.js              # Routing table
├── unet_provider_export.js      # Provider tarball export/import
└── docs/
    ├── certificates.md          # Certificate system details
    ├── handshakes.md            # Protocol message reference
    └── providers.md             # Provider role details
Last updated: 2/9/2026