Skip to main content

vector_core/community/
metadata.rs

1//! Control-plane metadata CONTENT structs (GROUP_PROTOCOL.md).
2//!
3//! `CommunityMetadata` (GroupRoot, vsk=0) and `ChannelMetadata` (vsk=2) are the decrypted content
4//! of real-npub-signed 3308 control editions, built by `roster::build_community_root_edition` /
5//! `build_channel_metadata_edition` and folded by the per-entity version chain.
6
7use serde::{Deserialize, Serialize};
8
9use super::{Community, CommunityImage};
10
11/// Community-level descriptor (the "GroupRoot" entity).
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct CommunityMetadata {
14    pub name: String,
15    /// Preferred relay set — also bootstrapped via the invite.
16    #[serde(default)]
17    pub relays: Vec<String>,
18    /// Short description / topic. `serde(default)` so older roots stay readable.
19    #[serde(default, skip_serializing_if = "Option::is_none")]
20    pub description: Option<String>,
21    /// Logo (encrypted blob ref — key rides in this ServerRoot-sealed content).
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub icon: Option<CommunityImage>,
24    /// Banner (encrypted blob ref).
25    #[serde(default, skip_serializing_if = "Option::is_none")]
26    pub banner: Option<CommunityImage>,
27    /// Owner attestation (signed event JSON) — lets members verify who the owner is via the
28    /// GroupRoot too (the invite bundle is the other carrier). `serde(default)` for old roots.
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub owner_attestation: Option<String>,
31}
32
33impl CommunityMetadata {
34    /// The GroupRoot descriptor for a Community — the content of its vsk=0 control edition.
35    pub fn of(community: &Community) -> Self {
36        CommunityMetadata {
37            name: community.name.clone(),
38            relays: community.relays.clone(),
39            description: community.description.clone(),
40            icon: community.icon.clone(),
41            banner: community.banner.clone(),
42            owner_attestation: community.owner_attestation.clone(),
43        }
44    }
45}
46
47/// Channel-level descriptor.
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49pub struct ChannelMetadata {
50    pub name: String,
51}