Skip to main content

GroupInfo

Struct GroupInfo 

Source
pub struct GroupInfo {
Show 28 fields pub members: BTreeSet<String>, pub display_names: HashMap<String, String>, pub membership_revision: u64, pub name: String, pub description: String, pub creator: AgentId, pub created_at: u64, pub updated_at: u64, pub mls_group_id: String, pub metadata_topic: String, pub chat_topic_prefix: String, pub policy: GroupPolicy, pub policy_revision: u64, pub roster_revision: u64, pub members_v2: BTreeMap<String, GroupMember>, pub join_requests: BTreeMap<String, JoinRequest>, pub discovery_card_topic: Option<String>, pub shared_secret: Option<Vec<u8>>, pub secret_epoch: u64, pub genesis: Option<GroupGenesis>, pub state_revision: u64, pub state_hash: String, pub prev_state_hash: Option<String>, pub security_binding: Option<String>, pub tags: Vec<String>, pub avatar_url: Option<String>, pub banner_url: Option<String>, pub withdrawn: bool,
}
Expand description

Metadata for a group.

Persisted as JSON. The legacy v1 layout used a flat members: BTreeSet plus a parallel display_names: HashMap. The v2 layout uses a structured members_v2: BTreeMap<String, GroupMember>. For migration, the v1 fields are deserialised (#[serde(default)]) but never written back (skip_serializing). Call GroupInfo::migrate_from_v1 at load time to fold any v1 data into v2.

Fields§

§members: BTreeSet<String>§display_names: HashMap<String, String>§membership_revision: u64§name: String§description: String§creator: AgentId§created_at: u64§updated_at: u64§mls_group_id: String§metadata_topic: String§chat_topic_prefix: String§policy: GroupPolicy§policy_revision: u64§roster_revision: u64§members_v2: BTreeMap<String, GroupMember>§join_requests: BTreeMap<String, JoinRequest>§discovery_card_topic: Option<String>§shared_secret: Option<Vec<u8>>

32-byte random secret for MlsEncrypted groups. None for SignedPublic or for stub entries created via card import (importer isn’t a member yet).

§secret_epoch: u64

Monotonic epoch for the shared secret. Incremented on rekey (ban/remove).

§genesis: Option<GroupGenesis>

Stable genesis record — establishes the group’s permanent group_id. Reconstructed from mls_group_id + creator + created_at when migrating pre-D.3 blobs (see GroupInfo::migrate_from_v1).

§state_revision: u64

Monotonic revision of the signed state-commit chain. 0 = genesis (no authority-signed commits yet); bumped on every accepted event.

§state_hash: String

Current state_hash — commitment to (group_id, revision, prev_hash, roster_root, policy_hash, public_meta_hash, security_binding, withdrawn). Recomputed by recompute_state_hash() after every mutation.

§prev_state_hash: Option<String>

Previous state_hash so receivers can verify chain linking. None at genesis.

§security_binding: Option<String>

Current security binding — for MlsEncrypted groups, a string of the form "gss:epoch=N" so roster/policy/epoch changes cannot silently drift apart. None for SignedPublic.

§tags: Vec<String>

Optional tags for public discovery (Phase C.2 will hash these into shard topics). Only meaningful for PublicDirectory groups.

§avatar_url: Option<String>

Optional avatar URL for public cards.

§banner_url: Option<String>

Optional banner URL for public cards.

§withdrawn: bool

Withdrawal/hidden supersession marker. Once set by a higher-revision signed commit, no further non-withdrawal actions may apply and subsequent public cards must carry the withdrawal flag.

Implementations§

Source§

impl GroupInfo

Source

pub fn new( name: String, description: String, creator: AgentId, mls_group_id: String, ) -> Self

Create a new GroupInfo with the given policy (defaults to private_secure).

Source

pub fn with_policy( name: String, description: String, creator: AgentId, mls_group_id: String, policy: GroupPolicy, ) -> Self

Create a new GroupInfo with an explicit policy.

Source

pub fn rotate_shared_secret(&mut self) -> (Vec<u8>, u64)

Rotate the group’s shared secret (called on ban/remove in MlsEncrypted groups). Returns the new secret and new epoch. Previous-epoch content encrypted by members still in the group is NOT decryptable at the new epoch — that’s forward secrecy across epochs.

Callers must arrange to distribute the new secret to remaining members (never to the departed/banned peer).

Phase D.3: also refreshes security_binding so the next state commit incorporates the new epoch into state_hash.

Source

pub fn stable_group_id(&self) -> &str

The stable group_id (Phase D.3). Falls back to mls_group_id for pre-D.3 groups where genesis has not yet been reconstructed.

Source

pub fn public_meta(&self) -> GroupPublicMeta

Snapshot of the public metadata that contributes to the state hash.

Source

pub fn recompute_state_hash(&mut self)

Recompute and store state_hash from the current fields. Called after every mutation; also called by constructors and the v1 migration path so new and migrated groups have a valid hash.

Source

pub fn seal_commit( &mut self, keypair: &AgentKeypair, now_ms: u64, ) -> Result<GroupStateCommit, ApplyError>

Seal the current (already-mutated) state into a signed commit.

  • bumps state_revision by 1,
  • records prev_state_hash = self.state_hash (pre-bump hash),
  • recomputes the new state_hash,
  • returns a signed state_commit::GroupStateCommit.

Callers must mutate the group first (e.g. add_member, ban_member, policy update) and then call seal_commit to produce the authority-signed commit that can be published and verified by peers.

Source

pub fn seal_withdrawal( &mut self, keypair: &AgentKeypair, now_ms: u64, ) -> Result<GroupStateCommit, ApplyError>

Mark the group as withdrawn and seal the terminal higher-revision commit. A withdrawn group is superseded immediately for public discovery purposes — peers holding stale public cards must drop them on receipt of this commit regardless of TTL.

Withdrawal is owner-authored; callers must check role before calling.

Source

pub fn apply_commit( &mut self, commit: &GroupStateCommit, action_kind: ActionKind, ) -> Result<(), ApplyError>

Accept a peer-authored signed commit on the apply-side.

Performs state_commit::validate_apply with the given action kind and, on success, updates the local chain fields (state_revision, state_hash, prev_state_hash, withdrawn) to mirror the commit. Domain-specific mutations (roster/policy/meta) are the caller’s responsibility and must be performed before calling this method, so the post-mutation recomputed hash matches commit.state_hash.

Source

pub fn finalize_applied_commit( &mut self, commit: &GroupStateCommit, ) -> Result<(), ApplyError>

Finalize a commit after the caller has already performed any action-specific pre-validation and mirrored the payload mutation into self.

This is the second half of D.4 apply-side handling: callers may need the pre-mutation roster view to validate signer authority (e.g. self-leave), then mutate local state, then verify the recomputed post-mutation hash matches the signed commit.

Source

pub fn secure_message_key(&self) -> Option<Vec<u8>>

Derive the per-message AEAD key from the group’s current shared secret. Returns None if the group has no shared secret (e.g., SignedPublic, or the caller hasn’t received a welcome yet).

Source

pub fn derive_message_key(secret: &[u8], epoch: u64, group_id: &str) -> Vec<u8>

Pure helper so both encryptor and decryptor derive the same key from (secret, epoch, group_id).

Source

pub fn migrate_from_v1(&mut self)

Migrate v1 (BTreeSet + display_names) data into v2 structured members. Also backfills Phase D.3 stable-genesis + state-hash fields for blobs written before D.3 landed. Idempotent: may be called multiple times.

Source

pub fn add_member( &mut self, agent_id_hex: String, role: GroupRole, added_by: Option<String>, display_name: Option<String>, )

Add or update a member. If the member already exists, updates state to Active.

Source

pub fn add_member_with_kem( &mut self, agent_id_hex: String, role: GroupRole, added_by: Option<String>, display_name: Option<String>, kem_public_key_b64: Option<String>, )

Add or update a member, optionally recording their ML-KEM-768 public key for future secure-share delivery. If kem_public_key_b64 is Some, it overwrites any previously-recorded value; None preserves the existing one.

Source

pub fn set_member_kem_public_key( &mut self, agent_id_hex: &str, kem_public_key_b64: String, )

Record a member’s ML-KEM-768 public key without changing any other state. Used when we learn a key for an existing member via a later event (e.g. JoinRequestCreated after a stub was already seeded).

Source

pub fn remove_member(&mut self, agent_id_hex: &str, removed_by: Option<String>)

Mark a member as Removed (soft delete — entry retained for audit).

Source

pub fn ban_member(&mut self, agent_id_hex: &str, banned_by: Option<String>)

Mark a member as Banned.

Source

pub fn unban_member(&mut self, agent_id_hex: &str)

Unban — transition Banned → Active (keeps current role).

Source

pub fn set_member_role(&mut self, agent_id_hex: &str, role: GroupRole)

Change a member’s role. Caller must verify caller’s authority first.

Source

pub fn has_active_member(&self, agent_id_hex: &str) -> bool

Check that a member is present and Active.

Source

pub fn has_member(&self, agent_id_hex: &str) -> bool

Legacy compat: true if active (matches old has_member semantics).

Source

pub fn caller_role(&self, agent_id_hex: &str) -> Option<GroupRole>

Returns the caller’s effective role if they are an active member.

Source

pub fn is_banned(&self, agent_id_hex: &str) -> bool

Returns true if the agent is currently banned.

Source

pub fn set_display_name(&mut self, agent_id_hex: &str, name: String)

Set a display name for a member. Member must exist.

Source

pub fn display_name(&self, agent_id_hex: &str) -> String

Get a member’s display name, falling back to truncated agent ID.

Source

pub fn active_members(&self) -> impl Iterator<Item = &GroupMember>

Iterator over currently active members.

Source

pub fn active_member_count(&self) -> usize

Count of currently active members.

Source

pub fn active_admin_count(&self) -> usize

Count of currently active Admins (including Owner).

Source

pub fn owner_agent_id(&self) -> Option<String>

Owner’s agent hex, if one exists.

Source

pub fn general_chat_topic(&self) -> String

Default chat topic for the group (“general” room).

Source

pub fn to_group_card(&self) -> Option<GroupCard>

Build a shareable discoverable GroupCard from this group’s state. Returns None if the group is Hidden.

The returned card carries the Phase D.3 state-commit binding (revision, state_hash, prev_state_hash, issued_at, expires_at, withdrawn) but is unsigned. Callers with the authority’s keypair should call GroupCard::sign before publishing to turn it into a verifiable public artifact.

Source

pub fn to_signed_group_card( &self, keypair: &AgentKeypair, ) -> Result<Option<GroupCard>, ApplyError>

Build and sign a GroupCard in one step.

Returns None if the group is Hidden AND not withdrawn. Callers publishing a withdrawal card must call seal_withdrawal() first to advance the state chain, then this helper to emit the terminal signed card.

Trait Implementations§

Source§

impl Clone for GroupInfo

Source§

fn clone(&self) -> GroupInfo

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for GroupInfo

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for GroupInfo

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for GroupInfo

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,