MESH ONLINECODENAME: Circus Maximus

Agent Identity

An agent that acts on your behalf needs an identity that is its own, yet provably traceable to you. Net does this with a delegation chain: a derived child identity plus a signed path back to a root.

Two different things are called "delegation." Permission tokens delegate authority to do something — a token holder passes a narrowed capability along. Delegation chains here derive who someone is — a child identity acting for a parent principal. They compose, but they answer different questions: a token says "you may," a chain says "you are acting for."

Derived child identities

A child identity is derived deterministically from a parent seed and a label:

code
let child_seed = derive_child_seed(&parent_seed, "gateway-eu");

Same parent plus same label always yields the same child, so an agent's identity survives a restart without anyone storing a second private key. The parent seed never leaves its holder.

DelegationChain builds the signed path:

MethodProduces
derive_gateway(..)A gateway identity under this root
derive_device(..)A device identity
extend_delegate(..)One more hop for a delegate
extend_to_subagent(..)A sub-agent acting under an agent

And to read one back: verify(), subjects(), leaf(), root(), expires_at(), len(). A chain has an expiry, so an agent identity is not permanent by default — it lapses unless renewed.

RevocationRegistry is the other half: a chain that verifies structurally can still be revoked, and the registry is what a verifier consults.

Device enrollment

Enrollment is how a new device joins under a root without either side pasting a private key. Three steps:

code
invite  →  join  →  approve
  • InviteToken::mint(root, rendezvous, ttl) — the operator mints a short-lived invite naming a rendezvous point. It encodes to a string you can transport out of band, and carries a root_fingerprint() so the joiner can confirm which root it's about to join.
  • JoinRequest::create(..) — the device generates its own keypair and self-signs a request. verify_self_signature() proves the request wasn't tampered with in transit.
  • Approve — the root issues the delegation chain, and the device now holds an identity it derived itself.

The device's private key is generated on the device and never transmitted. fingerprint(entity) gives the short human-comparable form for the out-of-band check that matters most — a human confirming the fingerprint they see matches the one the operator reads out.

Invites expire (is_expired(now)); enrollment failures surface as EnrollmentError.

Bindings

Rust, Python and Node/TypeScript all ship delegation and enrollment. The Rust SDK (net_sdk::{delegation, enrollment, devices}) is the single implementation the other two wrap — the bindings marshal, decide nothing, and hold no key material.

See also