Multi-User Mode

Multi-User Mode: Federated AD4M

Overview

By default, every AD4M user runs their own local node. But not everyone wants to—or can—run their own infrastructure. Multi-user mode lets a single AD4M executor serve multiple users, each with their own identity (DID) and fully isolated data. This enables federated network structures where a host operates an AD4M node on behalf of others, much like an email provider hosts mailboxes for its users.

From the perspective of AD4M apps, nothing changes. Apps use ad4m-connect to establish a connection, and ad4m-connect handles whether the executor is local or remote. This means existing AD4M apps work without any modification in a multi-user setup.

Why Multi-User?

  • Lower barrier to entry: Users who don't want to install or maintain software can simply connect to a hosted AD4M node.
  • Federated topology: Organizations, communities, or service providers can host AD4M nodes for their members—similar to how Matrix homeservers or email providers work.
  • Same agent autonomy: Each user still has their own DID, their own perspectives, and their own cryptographic identity. The host provides infrastructure, not control over data semantics.

Setting Up a Multi-User Host

All of the configuration described below can be done graphically in the AD4M Launcher under Settings.

1. Enable Multi-User Mode

Toggle multi-user mode in the Launcher settings,


or programmatically:

// Enable multi-user mode
await ad4m.runtime.setMultiUserEnabled(true);
 
// Check if multi-user is active
const enabled = await ad4m.runtime.multiUserEnabled();

2. Make the Node Publicly Reachable

For remote users to connect, the AD4M executor must be reachable over the network:

  • The host machine needs a public IP or domain name.
  • The executor's default port is 12000. TLS must run on a separate port, which can be configured in the Launcher settings.
  • If the host is behind a NAT or router, the relevant ports must be forwarded to the machine running the executor.
  • A TLS certificate must be configured to encrypt the connection between clients and the executor. Without TLS, credentials and data would travel in plaintext. The TLS port and certificate can be configured in the Launcher settings.

3. Configure Email Verification (Recommended)

If the host configures an email service via SMTP send settings (also in the Launcher settings), AD4M will use email-based verification for sign-up and login:

  1. A new user registers with their email address
  2. AD4M sends a verification code to that email
  3. The user enters the code to complete registration or login

This provides a secure, familiar authentication flow. If no SMTP service is configured, AD4M falls back to simple email + password authentication without email verification.

User Registration & Authentication

Sign-Up Flow

New users register through ad4m-connect, which presents the appropriate UI automatically:

// Behind the scenes, ad4m-connect calls:
await ad4m.agent.createUser("[email protected]", "securepassword");

Each new user receives their own Decentralized Identifier (DID), giving them a cryptographic identity independent of the host.

Login Flow

Returning users authenticate with their credentials:

await ad4m.agent.loginUser("[email protected]", "securepassword");

When email verification is enabled (SMTP configured), the login flow includes a verification step:

// Request login—triggers verification email
const result = await ad4m.agent.requestLoginVerification(
  "[email protected]",
  appInfo
);
// result.isExistingUser, result.requiresPassword, etc.
 
// User enters the code from their email
const jwt = await ad4m.agent.verifyEmailCode(
  "[email protected]",
  "123456",
  "login"
);

The returned JWT token is scoped to that specific user and used for all subsequent API calls.

Data Isolation

Each user's data is fully isolated within the shared executor:

  • Perspectives are user-scoped: A user can only see and modify their own perspectives. Attempting to access another user's perspective is denied.
  • Capability tokens are user-specific: Each JWT contains the user's DID, ensuring all operations are scoped to the correct identity.
  • Neighbourhoods work as usual: Users can still create, publish, and join Neighbourhoods for collaboration—the multi-user boundary is about local data, not shared spaces.

For App Developers: No Changes Required

If you're building an AD4M app, multi-user mode is transparent to you. The ad4m-connect library handles the entire connection flow—whether the user is running a local executor or connecting to a remote multi-user host:

import Ad4mConnect from "@coasys/ad4m-connect";
 
const ui = Ad4mConnect({
  appName: "My App",
  appDesc: "Works the same on local or hosted AD4M",
  appDomain: "myapp.example.com",
  capabilities: [{
    with: { domain: "*", pointers: ["*"] },
    can: ["*"]
  }],
});
 
ui.connect().then((client) => {
  // This client works identically whether connected to
  // a local single-user node or a remote multi-user host
});

When connecting to a remote multi-user host, ad4m-connect automatically presents the sign-up/login flow instead of the local capability handshake.

Administration

The host administrator can monitor and manage users:

// List all users with statistics
const users = await ad4m.runtime.listUsers();
// Returns: [{ email, did, lastSeen, perspectiveCount }, ...]

Admins can also manage capabilities on behalf of users:

// Request capability for a specific user
await ad4m.agent.requestCapabilityForUser(username, authInfo);
 
// Generate a JWT for a specific user
const jwt = await ad4m.agent.generateJwtForUser(username, requestId, rand);

Summary

AspectSingle-User (Default)Multi-User
Who runs the nodeEach userA host, for many users
IdentityOwn DIDOwn DID (unchanged)
Data isolationOnly one userPer-user scoping
App compatibilityStandardFully compatible, no changes
Connectionlocalhost:12000Remote URL with TLS
AuthenticationCapability handshakeEmail + password (optionally with email verification)
ConfigurationAD4M LauncherAD4M Launcher Settings