Core Concepts

Groups, contexts, roles, capabilities, and CRDTs for app builders

Namespaces

A namespace is a root group (a group with no parent). It is the application instance boundary and the identity scope for a node.

  • Each namespace gets its own Ed25519 keypair, auto-generated on first use and persisted in the datastore.
  • All subgroups and contexts within the namespace share the same node identity.
  • Different namespaces have different keys — identity isolation across application instances.
  • Subgroups inherit the namespace’s target_application_id; upgrading the root upgrades the entire tree.
  • The admin API exposes GET /admin-api/namespaces to list, query, and inspect namespace identity.
  • All groups within a namespace share a single governance DAG. Operations are either cleartext (RootOps: group creation, member join, key delivery) or encrypted (GroupOps: membership changes, capabilities).
  • New members receive group encryption keys via ECDH-wrapped KeyDelivery on the namespace DAG.

Groups

A group is a governance boundary within a namespace. It has members, an application (inherited from the namespace root), and one or more contexts. All membership management, access control, and upgrades happen at the group level via signed governance operations that propagate via P2P gossip.

  • Think of the group as where you vote, invite people, and upgrade the app.
  • Contexts live inside a group; they do not replace group governance.
  • Every group has at least one Admin who can always perform administrative actions.

Contexts

A context is a running instance of a WASM application with its own isolated state. State stays in sync across context members automatically, using CRDT-based replication.

  • Each context belongs to exactly one group.
  • Multiple contexts can run the same application (or different services from the same bundle) with independent state.
  • Joining a context requires group membership. By default (auto_join: true), joining a group auto-joins all its contexts.
  • For multi-service applications, each context specifies which service it runs via an optional service_name.

Services (multi-WASM bundles)

An application bundle (.mpk) can contain multiple named services, each with its own WASM binary and optional ABI.

  • Single-service bundles (one wasm field in the manifest) work as before — no service name needed.
  • Multi-service bundles declare a services array in the manifest, each with a name and WASM path.
  • When creating a context for a multi-service app, specify service_name to choose which WASM to run.
  • All services in a bundle share the same ApplicationId and upgrade atomically.
  • Example: a chat application with services user-mgmt, chat, and storage — each running in its own context with independent state.

Member roles

Roles define what a member can do inside a group. The platform enforces them consistently on every node.

Admin

Full control: all governance operations, member management, and state writes.

Member

Standard participant: read and write app state. Some operations still require explicit capabilities.

ReadOnly

Observer: can join and read state. Mutations are rejected locally and on remote peers.

Subgroups

Groups form a tree. A child group links to a parent.

Membership and admin inheritance

  • Membership inherits downward: a parent member is also a member of descendant groups.
  • Admin authority inherits for structural operations on the tree (add/remove members, manage subgroups).

Restricting access via subgroups

To restrict access to specific contexts, create a subgroup and add only the intended members. Contexts within that subgroup are only accessible to its direct members (and inherited parent members). This replaces the former per-context visibility/allowlist model with a simpler group-membership-based approach.

Capabilities

Beyond the base role, fine-grained capabilities gate specific actions.

  • Admins always pass capability checks.
  • Default capabilities can be configured per group and applied to new members automatically.

Flags

Each capability corresponds to a bit in the member’s capability set (shown conceptually below).

// conceptual bit layout (crates/context/config/src/lib.rs)
bit 0CAN_CREATE_CONTEXT
bit 1CAN_INVITE_MEMBERS
bit 2CAN_JOIN_OPEN_SUBGROUPS
bit 3MANAGE_MEMBERS
bit 4MANAGE_APPLICATION
bit 5CAN_CREATE_SUBGROUP
bit 6CAN_DELETE_SUBGROUP
bit 7CAN_MANAGE_VISIBILITY
bit 8CAN_MANAGE_METADATA

CAN_CREATE_CONTEXT

Bit 0. Register new contexts in this group.

CAN_INVITE_MEMBERS

Bit 1. Issue invitations for new members.

CAN_JOIN_OPEN_SUBGROUPS

Bit 2. Be inherited as a member of Open subgroups beneath this group (granted to non-admins by default; admins revoke it per-member as a deny-list).

MANAGE_MEMBERS

Bit 3. Add or remove non-admin members and set their roles.

MANAGE_APPLICATION

Bit 4. Set the target application and handle migration.

CAN_CREATE_SUBGROUP

Bit 5. Create a subgroup directly under the namespace root (the creator becomes its owner/admin). Honored only at root level — the apply-time check must be verifiable by every namespace member.

CAN_DELETE_SUBGROUP

Bit 6. Cascade-delete a subgroup and its subtree. (A subgroup’s owner and namespace admins can also delete it.)

CAN_MANAGE_VISIBILITY

Bit 7. Flip a subgroup’s visibility (OpenRestricted) without full admin on it.

CAN_MANAGE_METADATA

Bit 8. Set the name/data metadata record of this group, its members, or its registered contexts. (A member may always set their own member metadata without this bit.)

Context access

Context access is determined entirely by group membership. Any member of a group can join any context within that group. To restrict access to a subset of contexts, create a subgroup and register those contexts there — only subgroup members (direct or inherited) can join them.

By default, auto_join: true causes joining a group to automatically subscribe to all its contexts. Context membership is implicit from group membership — no separate governance op is required.

CRDT state

All application state uses CRDTs for conflict-free synchronization. State changes produce deltas that are broadcast via gossip. Every node converges to the same logical state even when messages arrive in different orders.

Built-in types

Pick the structure that fits your app; the runtime handles merging.

UnorderedMap

Key-value map with last-write-wins per key.

Vector

Ordered, append-only list of elements.

Counter

Distributed counter (G-Counter style, per-node slots).

LwwRegister

Single value with last-write-wins by timestamp.

ReplicatedGrowableArray (RGA)

Character-level text CRDT for collaborative editing.

What “converge” means for your app

Peers may receive updates in different orders. CRDT rules guarantee that once all deltas are applied, every replica shows the same logical state. You design against the data types above instead of inventing your own merge logic.

Cross-context communication

xcall is a fire-and-forget call from one context’s WASM into another context on the same node.

  • Calls are queued while your handler runs and execute after the current commit completes.
  • There is no return value; treat it like an async notification.
  • The target context processes the call as its own member.

When to use it

Good fits: secondary indexes, notifications, audit logs, or any work that should not block the caller’s transaction on a synchronous response.

Same-node scope

xcall is intentionally local to one node. For replication or network-wide effects, use normal context state and sync; use xcall for coordination between contexts co-located on that peer.