Skip to content

Groups & Governance

Governance in Calimero is layered: a namespace scopes an application instance; groups (and subgroups) within it hold members with roles and capabilities and own contexts. This guide covers the pieces you’ll touch most. The exhaustive method list is in the admin API reference.

A namespace groups contexts and members under a shared upgrade policy.

const { namespaceId } = await sdk.admin.createNamespace({
applicationId,
upgradePolicy: 'Automatic', // or 'LazyOnAccess'
name: 'production',
});
const { namespaces } = await sdk.admin.listNamespaces();
const ns = await sdk.admin.getNamespace(namespaceId);
const identity = await sdk.admin.getNamespaceIdentity(namespaceId);

Invite and join:

const invitation = await sdk.admin.createNamespaceInvitation(namespaceId);
// on the joining node:
const { groupId, memberIdentity } = await sdk.admin.joinNamespace(namespaceId, {
invitation,
});
const info = await sdk.admin.getGroupInfo(groupId);
const { members } = await sdk.admin.listGroupMembers(groupId);
const { contexts } = await sdk.admin.listGroupContexts(groupId);
await sdk.admin.addGroupMembers(groupId, { /* members */ });
await sdk.admin.updateMemberRole(groupId, identity, { role: 'admin' });
await sdk.admin.removeGroupMembers(groupId, { /* identities */ });

Subgroups nest under a parent group:

const subgroups = await sdk.admin.listSubgroups(groupId);
await sdk.admin.createGroupInNamespace(namespaceId, { /* … */ });

A member’s permissions are a u32 bitmask. The SDK ships the bit constants and pure helpers to read and edit a mask — no bitwise operators at your call sites.

import { CAPABILITIES, hasCap, withCap, withoutCap } from '@calimero-network/mero-js';
// Read the current mask
const { capabilities } = await sdk.admin.getMemberCapabilities(groupId, identity);
// Test / add / remove bits
const canInvite = hasCap(capabilities, CAPABILITIES.CAN_INVITE_MEMBERS);
const next = withCap(capabilities, CAPABILITIES.MANAGE_MEMBERS);
const revoked = withoutCap(next, CAPABILITIES.MANAGE_APPLICATION);
// Persist
await sdk.admin.setMemberCapabilities(groupId, identity, { capabilities: next });

The bits:

Constant Value Grants
CAN_CREATE_CONTEXT 1 << 0 create contexts in the group
CAN_INVITE_MEMBERS 1 << 1 invite new members
CAN_JOIN_OPEN_SUBGROUPS 1 << 2 join open subgroups
MANAGE_MEMBERS 1 << 3 add/remove members, change roles
MANAGE_APPLICATION 1 << 4 manage the group’s application
CAN_CREATE_SUBGROUP 1 << 5 create subgroups
CAN_DELETE_SUBGROUP 1 << 6 delete subgroups
CAN_MANAGE_VISIBILITY 1 << 7 change subgroup visibility
CAN_MANAGE_METADATA 1 << 8 edit group/member/context metadata

Set the default mask new members receive, or read/change subgroup visibility:

await sdk.admin.setDefaultCapabilities(groupId, {
defaultCapabilities: withCap(0, CAPABILITIES.CAN_CREATE_CONTEXT),
});
const defaults = await sdk.admin.getDefaultCapabilities(groupId); // number
const visibility = await sdk.admin.getSubgroupVisibility(groupId); // string

Attach a small named key/value record to a group, member, or context:

await sdk.admin.setGroupMetadata(groupId, {
name: 'Production',
data: { region: 'eu', tier: 'gold' },
});
const meta = await sdk.admin.getGroupMetadata(groupId); // MetadataRecord | null
// meta.name, meta.data, meta.updatedAt, meta.updatedBy

The same pair exists for members (set/getMemberMetadata) and contexts (set/getContextMetadata).

A group can restrict which nodes may join to those running in an approved Trusted Execution Environment. The policy lists the allowed measurements.

await sdk.admin.setTeeAdmissionPolicy(groupId, {
allowedMrtd: ['<mrtd-hex>'],
allowedRtmr0: [],
allowedRtmr1: [],
allowedRtmr2: [],
allowedRtmr3: [],
allowedTcbStatuses: ['UpToDate'],
acceptMock: false, // true only for local/dev
});
const policy = await sdk.admin.getTeeAdmissionPolicy(groupId);

Nodes can also attest and verify quotes directly:

const info = await sdk.admin.getTeeInfo(); // { cloudProvider, osImage, mrtd }
const attestation = await sdk.admin.teeAttest({ nonce }); // { quoteB64, quote }
const verdict = await sdk.admin.teeVerifyQuote({ quoteB64, nonce });

For cloud-managed TEE redundancy, see high availability.

When an application ships a new version, drive the group upgrade and watch its progress:

await sdk.admin.upgradeGroup(groupId, { targetApplicationId, cascade: true });
const status = await sdk.admin.getGroupUpgradeStatus(groupId);
const migration = await sdk.admin.getMigrationStatus(namespaceId);
// migration.rollup.allMigrated === true when done