Configure group permissions and control who can perform actions in LibXMTP
LibXMTP uses a flexible policy system to control group permissions. This guide explains how to configure policies, manage admins, and enforce access control.
use xmtp_mls::groups::group_permissions::PreconfiguredPolicies;// All members can perform all actionslet policy_set = PreconfiguredPolicies::AllMembers.to_policy_set();// Only admins can perform restricted actionslet policy_set = PreconfiguredPolicies::AdminsOnly.to_policy_set();// Default policy (admin-controlled)let policy_set = PolicySet::default();
use xmtp_mls::groups::group_permissions::MembershipPolicy;pub enum MembershipPolicy { Allow, // Any member can perform Deny, // No one can perform AllowIfActorAdminOrSuperAdmin, // Only admins/super admins AllowIfActorSuperAdmin, // Only super admins}
use xmtp_mls::groups::group_permissions::MetadataPolicy;pub enum MetadataPolicy { Allow, // Any member can update Deny, // Field is immutable AllowIfActorAdminOrSuperAdmin, // Only admins can update AllowIfActorSuperAdmin, // Only super admins can update}
pub enum PermissionPolicy { Allow, // Any member can update policies Deny, // Policies are immutable AllowIfActorAdminOrSuperAdmin, // Only admins can update AllowIfActorSuperAdmin, // Only super admins can update }
use xmtp_mls::groups::intents::UpdateAdminListIntentData;// Add a member as admingroup.add_admin(inbox_id).await?;// Add as super admingroup.add_super_admin(inbox_id).await?;
// Remove admin status (member remains in group)group.remove_admin(inbox_id).await?;// Cannot remove super admin// group.remove_super_admin(inbox_id).await?; // Will fail!
use xmtp_mls::groups::intents::{PermissionUpdateType, PermissionPolicyOption};// Change who can add membersgroup.update_permission_policy( PermissionUpdateType::AddMember, PermissionPolicyOption::AdminOnly, MetadataField::GroupName, // Not used for membership policies).await?;// Change who can update group namegroup.update_permission_policy( PermissionUpdateType::UpdateMetadata, PermissionPolicyOption::Allow, MetadataField::GroupName,).await?;
// Actor's current state is checkedlet actor = CommitParticipant { inbox_id: sender_inbox_id, is_admin: metadata.admin_list.contains(&sender_inbox_id), is_super_admin: metadata.super_admin_list.contains(&sender_inbox_id),};// Policy evaluated with current contextlet allowed = policy.evaluate(&actor, &change);
// Public community - anyone can join and postlet community = client.create_group( Some(PreconfiguredPolicies::AllMembers.to_policy_set()), None,)?;// Moderated group - admin-controlledlet moderated = client.create_group( Some(PreconfiguredPolicies::AdminsOnly.to_policy_set()), None,)?;
4
Lock Critical Settings
5
Make important policies immutable:
6
let mut policy_set = PolicySet::default();policy_set.update_permissions_policy = PermissionPolicy::Deny;let group = client.create_group(Some(policy_set), None)?;// Policies can never be changed!
7
Validate Before Actions
8
Check permissions before attempting operations:
9
let permissions = group.permissions()?;let can_add = matches!( permissions.policies.add_member_policy, MembershipPolicy::Allow | MembershipPolicy::AllowIfActorAdminOrSuperAdmin);if can_add { group.add_members(&inbox_ids).await?;} else { println!("You don't have permission to add members");}
10
Document Policy Choices
11
Make policy decisions explicit:
12
// Good: Clear intentlet policy_set = if is_public_community { PreconfiguredPolicies::AllMembers.to_policy_set()} else { PreconfiguredPolicies::AdminsOnly.to_policy_set()};let group = client.create_group(Some(policy_set), None)?;