pub struct GroupMember {
pub key: IdentityRef,
pub role: GroupRole,
pub joined_at: u64,
pub last_active: u64,
pub metadata: Vec<Metadata>,
}Expand description
Runtime information about an active group member.
GroupMember tracks the runtime state of a participant in a group. This includes
their role, activity timestamps, and member-specific metadata. It’s distinct from
the cryptographic identity and display identity managed by GroupMembership.
§📊 Member State vs Identity State
- GroupMember: Runtime participation state (roles, activity, metadata)
- GroupMembership: Identity management (aliases, display names, authorization)
- VerifyingKey: Cryptographic identity (authentication, message signing)
These three layers work together to provide comprehensive member management:
VerifyingKey → GroupMember (runtime state) + GroupMembership (identity state)§🔄 Lifecycle and State Transitions
- Initial Creation: When a key first participates, a
GroupMemberis created - Activity Updates:
GroupMember::last_activeupdated with each message - Role Changes:
GroupMember::roleupdated via role assignment events - Metadata Updates:
GroupMember::metadatacan store custom key-value data - Departure:
GroupMemberremoved when user leaves (but could rejoin later)
§💡 Usage Examples
§Tracking Member Activity
use zoe_app_primitives::{GroupMember, IdentityRef, events::roles::GroupRole};
use zoe_wire_protocol::KeyPair;
use std::collections::BTreeMap;
let member_key = KeyPair::generate(&mut rand::rngs::OsRng).public_key();
let join_time = 1234567890;
let mut member = GroupMember {
key: IdentityRef::Key(member_key),
role: GroupRole::Member,
joined_at: join_time,
last_active: join_time,
metadata: vec![],
};
// Update activity when they send a message
member.last_active = join_time + 3600; // 1 hour later
// Check how long they've been inactive
let current_time = join_time + 7200; // 2 hours later
let inactive_duration = current_time - member.last_active;
assert_eq!(inactive_duration, 3600); // 1 hour inactive§Role-Based Member Management
// Promote member to moderator
member.role = GroupRole::Moderator;
// Check permissions
use zoe_app_primitives::Permission;
assert!(member.role.has_permission(&Permission::AllMembers));
assert!(member.role.has_permission(&Permission::ModeratorOrAbove));§Custom Member Metadata
// Store custom metadata about the member using structured types
member.metadata.push(Metadata::Generic { key: "department".to_string(), value: "engineering".to_string() });
member.metadata.push(Metadata::Generic { key: "team".to_string(), value: "backend".to_string() });
member.metadata.push(Metadata::Generic { key: "timezone".to_string(), value: "UTC-8".to_string() });
member.metadata.push(Metadata::Email("member@company.com".to_string()));
// Query metadata
for meta in &member.metadata {
match meta {
Metadata::Generic { key, value } if key == "department" => {
println!("Member is in {} department", value);
}
Metadata::Email(email) => {
println!("Member email: {}", email);
}
_ => {}
}
}Fields§
§key: IdentityRefMember’s public key encoded as bytes for serialization compatibility
role: GroupRoleMember’s role in the group
joined_at: u64When they joined the group
last_active: u64When they were last active
metadata: Vec<Metadata>Member-specific metadata using structured types
Trait Implementations§
Source§impl Clone for GroupMember
impl Clone for GroupMember
Source§fn clone(&self) -> GroupMember
fn clone(&self) -> GroupMember
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for GroupMember
impl Debug for GroupMember
Source§impl<'de> Deserialize<'de> for GroupMember
impl<'de> Deserialize<'de> for GroupMember
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<GroupMember, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<GroupMember, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Source§impl Serialize for GroupMember
impl Serialize for GroupMember
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Serialize this value into the given Serde serializer. Read more
Auto Trait Implementations§
impl Freeze for GroupMember
impl RefUnwindSafe for GroupMember
impl Send for GroupMember
impl Sync for GroupMember
impl Unpin for GroupMember
impl UnwindSafe for GroupMember
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more