3. Layer 0: Identity
Identity is the foundation of the mesh. Each node MUST have a persistent, globally unique identity that other nodes can verify. Without stable identity, coupling decisions, lineage chains, and wake protocols cannot function.
3.1 Node Identity
| Field | Type | Requirement | Description |
|---|---|---|---|
| nodeId | UUID v7 | MUST | Globally unique, time-ordered, generated at first launch, persisted across sessions (RFC 9562) |
| name | string | MUST | Human-readable display name (UTF-8, 1–64 bytes, printable characters only) |
| keypair | Ed25519 | MUST | Cryptographic identity for message signing, peer verification, and key exchange |
3.1.1 nodeId
The nodeId MUST be a UUID v7 as defined in RFC 9562. UUID v7 encodes
a Unix timestamp in the high bits, providing natural time-ordering while retaining 74 bits of randomness for
global uniqueness. This aids debugging, log correlation, and conflict resolution without revealing device identity.
The nodeId MUST NOT change during the lifetime of
a node installation. If a node is uninstalled and reinstalled, a new nodeId is generated —
the node is a new identity on the mesh. Peers that tracked the old nodeId will not recognise it.
On the wire, the nodeId MUST be encoded as a lowercase hexadecimal string with hyphens
(e.g., 0192e4a2-7b5c-7def-8a3b-9c4d5e6f7a8b).
Implementations MUST use case-insensitive comparison when matching nodeIds.
Existing nodes with UUID v4 identities MAY continue to use them — peers MUST accept
both v4 and v7 formats.
3.1.2 name
The name field MUST be valid UTF-8, between 1 and 64 bytes inclusive.
The name MUST contain only printable characters (Unicode categories L, M, N, P, S, and Zs). Control characters
(U+0000–U+001F, U+007F–U+009F), null bytes, and lone surrogates MUST NOT appear.
The name is not required to be unique — nodeId is the sole unique identifier. The name is for
human display only and MUST NOT be used for peer identification or routing.
3.1.3 keypair
Each node MUST generate an Ed25519 keypair (RFC 8032) at first launch and persist it alongside the nodeId. The keypair serves three functions:
- —Peer verification — the public key MUST be included in the handshake frame. Peers SHOULD challenge the node to sign a nonce to prove possession of the private key.
- —Key exchange — Ed25519 keys are converted to X25519 for Diffie-Hellman shared secret derivation, used for end-to-end CMB encryption (Section 18.2.1).
- —Message signing — implementations SHOULD sign every CMB with the Ed25519 identity key (Section 18.3.1, schema §20.2); a receiver holding the author’s key MUST verify the signature. Unsigned CMBs are accepted only from legacy 1.0.x emitters.
The public key MUST be encoded as base64url (RFC 4648 Section 5) in all wire formats (handshake frames, DNS-SD TXT records). The private key MUST NOT leave the node.
3.2 One Agent, One Node
Every autonomous agent MUST present its own nodeId, backed by its own keypair — identities are never shared between agents. A cognitive node (Class 2, §17.2) additionally maintains its own coupling engine and its own memory store; a Class 1 Emitter (§17.1) needs neither.
This follows directly from the protocol design: SVAF field weights (αf) are per-node, coupling state is per-node, and memory stores are per-node. An agent that shares another node’s identity inherits that node’s coupling decisions and cannot independently evaluate incoming signals through its own domain lens. A research agent and a marketing agent need different field weights, different coupling thresholds, and different memory stores. They MUST be separate nodes.
Multiple nodes MAY run on the same device. Each maintains its own identity file, discovers peers via DNS-SD, and connects via TCP (LAN) or WebSocket (relay). Nodes on the same device discover each other the same way nodes on different devices do — there is no special local path.
3.3 Identity Persistence
Implementations MUST persist the nodeId, name, and keypair to stable storage at first launch.
The storage location and format are implementation-defined. Reference implementations
use ~/.sym/nodes/<name>/identity.json (Node.js)
and UserDefaults (Swift/iOS).
Implementations SHOULD store a creation timestamp alongside the identity for diagnostic purposes. Implementations SHOULD store the machine hostname for display in peer lists, but the hostname MUST NOT be used for identity or routing.
3.4 Identity Lifecycle
A node’s identity is created once and persists until the node is uninstalled. The following lifecycle events are defined:
| Event | Action | Consequence |
|---|---|---|
| First launch | Generate nodeId (UUID v7), keypair (Ed25519), persist | New identity on the mesh |
| Restart / reboot | Load from stable storage | Same identity, peers recognise it |
| Uninstall + reinstall | Generate fresh identity | New identity; old peers do not recognise it |
| Key compromise | Generate fresh identity | Old nodeId abandoned; treated as new node |
| Clone detection | Duplicate nodeId rejected (error 1005) | Second connection closed; first connection remains |
MMP does not define an identity rotation or revocation mechanism: a node whose key is
compromised MUST generate a fresh identity (new nodeId and keypair), and the old identity becomes
permanently orphaned. This is distinct from withdrawing a node’s authority — that is
role revocation (role-revoke, §6.6), which needs no new identity and
cascades through the grant chain. Implementations SHOULD document the identity limitation to operators.
3.5 Node Lifecycle Role
Each node has a lifecycleRole — participant (default), validator,
or anchor — that determines which CMB lifecycle transitions it may perform. A role is earned, not
asserted: its authority MUST be resolved from the signed role-grant chain rooting at the pinned anchor (§6.6),
bound to the node’s cryptographic identity. The lifecycleRole a node
advertises in its handshake is a discovery hint only; a receiver MUST NOT treat the advertised role as
authority (see §3.5.1).
| Role | Default | May produce | May advance lifecycle to |
|---|---|---|---|
| participant | Yes | CMBs (observed), remixes | observed, remixed |
| validator | No | CMBs, remixes, validation CMBs | observed, remixed, validated |
| anchor | No | CMBs, remixes, validation CMBs, canonization CMBs | observed, remixed, validated, canonical |
Only a node whose resolved role (§6.6) is validator or above may advance another CMB’s lifecycle to
validated; canonical is reserved to a
resolved anchor. A receiver MUST resolve the author’s role through the anchor-rooted grant chain —
never the createdBy field or the advertised handshake role — and MUST
ignore, for lifecycle advancement, any validation CMB whose author does not resolve to the required role (the CMB is
still stored as a normal remix). This applies equally to any authority-weighted treatment: a CMB’s admission
weight (§6.4) derives from the author’s resolved role, so a self-advertised role confers no elevation.
3.5.1 Role Progression
Lifecycle roles are not static. A participant node MAY be promoted to validator by an existing validator or anchor node. Promotion is a protocol frame, not an out-of-band configuration change.
| Transition | Granted by | Conditions |
|---|---|---|
| participant → validator | Existing validator or anchor | Node has produced CMBs that were remixed by peers (demonstrated quality). Granting node sends role-grant frame. |
| validator → anchor | Existing anchor | Node has validated CMBs that reached canonical state. Track record of quality validation. |
| Bootstrap (root of trust) | Out-of-band pin | The root anchor is pinned out-of-band (its nodeId + public key), not self-declared — an unverifiable “first node wins” is a partition/eclipse hole. All other authority descends from it by grant (§6.6). |
Promotion is upward (participant → validator → anchor) and demotion is defined: a
role-revoke frame (§6.6) pulls a granted role back down, and because a
node’s role is re-resolved through the chain, revoking a grantor cascades to everything it granted. Role
revocation is distinct from identity compromise: a node whose signing key is compromised still
MUST generate a fresh identity (§3.4) — key rotation is not defined here — whereas a node whose
authority is withdrawn is handled by role-revoke without a new identity.
A role-grant frame is signed by the grantor over the action, grantee,
conferred role, grantor, time, and (optionally) the grantee’s vouched key (§6.6, §7). A receiver MUST
verify the signature against the grantor’s key and confer the role only when the grantor’s own resolved
role outranks-or-equals it and the chain roots at the pinned anchor — a grant a node was not entitled to make
is stored but inert. Authority never rests on a self-asserted field; it is a signed fact resolvable to the root of
trust. See §6.5–§6.6 for the full lifecycle.
Q&A
Why UUID v7 instead of v4?
UUID v7 (RFC 9562) provides the same global uniqueness and privacy properties as v4, with an additional benefit: time-ordering. The embedded timestamp aids log correlation, debugging, and determining which node was created first — without revealing device identity. The 74 random bits provide sufficient collision resistance for any practical mesh size.
Why not use the public key hash as the nodeId?
Self-certifying identifiers (nodeId = hash of public key) are elegant but create a hard coupling between identity and key material. If the keypair needs rotation (algorithm upgrade, key compromise), the nodeId must also change, breaking all peer references and lineage chains. Separating nodeId from keypair allows future key rotation without identity disruption.
Why must every agent be its own node?
Coupling is per-node. SVAF field weights (αf) are per-node. Memory stores are per-node. An agent that shares another node’s identity inherits that node’s coupling decisions — it cannot independently evaluate incoming signals through its own domain lens. A research agent and a marketing agent on the same device need different field weights, different coupling thresholds, and different memory stores. They must be separate nodes.
What happens when two nodes have the same nodeId?
The connection state machine rejects duplicate nodeIds (error code 1005). The second connection is closed. This prevents impersonation and ensures each nodeId maps to exactly one active node.
Why is Ed25519 mandatory?
Without cryptographic identity, any node can claim any nodeId. A relay could impersonate peers (MITM), and peer gossip (Section 5.6) would propagate unverified claims. For autonomous AI agents making coupling decisions, authenticated identity is foundational — not optional.
Why are lifecycle roles identity-bound, not content-based?
If validation authority were determined by content (e.g. perspective field containing "founder"), any agent could spoof it. Binding roles to cryptographic identity means only nodes that have been explicitly promoted by existing validators can advance CMB lifecycle. The mesh knows who validated, not just what was said.
Why is role progression earned, not configured?
An agent that produces quality remixes — remixes that other agents cite and build upon — has demonstrated value to the mesh. Granting validation authority to such agents is a natural extension of their demonstrated competence. This prevents arbitrary role assignment and creates a meritocratic trust hierarchy that emerges from mesh activity.
Can a participant node dismiss a decision?
A participant can produce a CMB with lineage pointing to a decision, but receiving nodes MUST NOT treat it as validation. The CMB is stored as a normal remix — it does not advance the parent CMB’s lifecycle. Only validator or anchor nodes can validate or dismiss decisions in a way that removes them from the decision queue.