phalanx_crypto/
group.rs

1//! Group management and encryption for Phalanx Protocol
2
3use crate::{
4    error::{PhalanxError, Result},
5    identity::{Identity, PublicKey},
6    message::{GroupMessage, MessageContent, MessageType},
7    protocol::{ProtocolVersion, HandshakeMessage, KeyRotationMessage},
8    crypto::{SymmetricKey, hash_multiple},
9    key_manager::{AdvancedKeyManager, KeySet, RotationPolicy},
10};
11use std::collections::{HashMap, HashSet};
12use std::time::{SystemTime, UNIX_EPOCH};
13use x25519_dalek::PublicKey as X25519PublicKey;
14
15#[cfg(feature = "serde")]
16use serde::{Serialize, Deserialize};
17
18/// Configuration for a Phalanx group
19#[derive(Debug, Clone)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21pub struct GroupConfig {
22    /// Maximum number of members allowed
23    pub max_members: usize,
24    /// Key rotation interval in seconds
25    pub key_rotation_interval: u64,
26    /// Whether messages are stored persistently
27    pub persistent_storage: bool,
28    /// Group visibility (public/private/invite-only)
29    pub visibility: GroupVisibility,
30    /// Admin permissions required for certain operations
31    pub admin_only_operations: Vec<GroupOperation>,
32}
33
34/// Group visibility levels
35#[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37pub enum GroupVisibility {
38    /// Anyone can discover and join
39    Public,
40    /// Discoverable but invite required
41    Private,
42    /// Completely hidden, invite only
43    InviteOnly,
44}
45
46/// Operations that can be restricted to admins
47#[derive(Debug, Clone, PartialEq, Eq)]
48#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49pub enum GroupOperation {
50    /// Adding new members
51    AddMember,
52    /// Removing members
53    RemoveMember,
54    /// Changing group settings
55    ChangeSettings,
56    /// Rotating encryption keys
57    RotateKeys,
58    /// Deleting messages
59    DeleteMessage,
60}
61
62/// Member role in the group
63#[derive(Debug, Clone, PartialEq, Eq)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65pub enum MemberRole {
66    /// Regular group member
67    Member,
68    /// Group administrator
69    Admin,
70    /// Group owner (highest privileges)
71    Owner,
72    /// Moderator (limited admin privileges)
73    Moderator,
74    /// Guest (read-only access)
75    Guest,
76}
77
78/// Member status in the group
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
81pub enum MemberStatus {
82    /// Active member
83    Active,
84    /// Temporarily muted
85    Muted,
86    /// Banned from participation
87    Banned,
88    /// Pending approval to join
89    Pending,
90    /// Temporarily suspended
91    Suspended,
92}
93
94/// Fine-grained permissions for group members
95#[derive(Debug, Clone, PartialEq, Eq)]
96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
97pub enum GroupPermission {
98    /// Can send messages
99    SendMessages,
100    /// Can delete own messages
101    DeleteOwnMessages,
102    /// Can delete any messages
103    DeleteAnyMessages,
104    /// Can invite new members
105    InviteMembers,
106    /// Can remove members
107    RemoveMembers,
108    /// Can modify group settings
109    ModifySettings,
110    /// Can manage member roles
111    ManageRoles,
112    /// Can initiate key rotation
113    RotateKeys,
114    /// Can view group audit logs
115    ViewAuditLogs,
116    /// Can manage group bans
117    ManageBans,
118    /// Can create channels/subgroups
119    CreateChannels,
120}
121
122/// Member presence information
123#[derive(Debug, Clone, PartialEq, Eq)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125pub enum MemberPresence {
126    /// Online and active
127    Online,
128    /// Away but available
129    Away,
130    /// Do not disturb
131    DoNotDisturb,
132    /// Offline
133    Offline,
134    /// Invisible (appears offline to others)
135    Invisible,
136}
137
138/// Information about a group member
139#[derive(Debug, Clone)]
140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
141pub struct GroupMember {
142    /// Member's public key
143    pub public_key: PublicKey,
144    /// Current ephemeral key for key exchange
145    pub ephemeral_key: Option<X25519PublicKey>,
146    /// Member's role in the group
147    pub role: MemberRole,
148    /// When the member joined
149    pub joined_at: u64,
150    /// Last seen timestamp
151    pub last_seen: Option<u64>,
152    /// Member nickname (optional)
153    pub nickname: Option<String>,
154    /// Member status
155    pub status: MemberStatus,
156    /// Custom permissions for this member
157    pub permissions: Vec<GroupPermission>,
158    /// Member's presence information
159    pub presence: MemberPresence,
160}
161
162/// Proof of membership for joining restricted groups
163#[derive(Debug, Clone)]
164#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
165pub struct MembershipProof {
166    /// Proof type identifier
167    pub proof_type: String,
168    /// Proof data (format depends on type)
169    pub proof_data: Vec<u8>,
170    /// Signature from an admin/inviter
171    pub signature: Option<ed25519_dalek::Signature>,
172}
173
174/// Audit log entry for group operations
175#[derive(Debug, Clone)]
176#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
177pub struct AuditLogEntry {
178    /// Timestamp of the action
179    pub timestamp: u64,
180    /// Member who performed the action
181    pub actor: [u8; 32],
182    /// Type of action performed
183    pub action: AuditAction,
184    /// Target of the action (if applicable)
185    pub target: Option<[u8; 32]>,
186    /// Additional context or details
187    pub details: Option<String>,
188}
189
190/// Types of auditable actions in a group
191#[derive(Debug, Clone, PartialEq, Eq)]
192#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
193pub enum AuditAction {
194    /// Member joined the group
195    MemberJoined,
196    /// Member left the group
197    MemberLeft,
198    /// Member was removed/kicked
199    MemberRemoved,
200    /// Member role was changed
201    RoleChanged,
202    /// Member was banned
203    MemberBanned,
204    /// Member was unbanned
205    MemberUnbanned,
206    /// Keys were rotated
207    KeysRotated,
208    /// Group settings changed
209    SettingsChanged,
210    /// Channel created
211    ChannelCreated,
212    /// Channel deleted
213    ChannelDeleted,
214    /// Message deleted
215    MessageDeleted,
216}
217
218/// Group channel/subgroup for topic-based organization
219#[derive(Debug, Clone)]
220#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
221pub struct GroupChannel {
222    /// Channel identifier
223    pub id: String,
224    /// Human-readable channel name
225    pub name: String,
226    /// Channel description
227    pub description: Option<String>,
228    /// Members with access to this channel
229    pub members: HashSet<[u8; 32]>,
230    /// Channel-specific permissions
231    pub permissions: HashMap<[u8; 32], Vec<GroupPermission>>,
232    /// Whether the channel is archived
233    pub archived: bool,
234    /// Channel creation timestamp
235    pub created_at: u64,
236    /// Last activity timestamp
237    pub last_activity: Option<u64>,
238}
239
240/// Ban entry for banned members
241#[derive(Debug, Clone)]
242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
243pub struct BanEntry {
244    /// When the ban was issued
245    pub banned_at: u64,
246    /// Who issued the ban
247    pub banned_by: [u8; 32],
248    /// Reason for the ban
249    pub reason: Option<String>,
250    /// Ban expiration (None for permanent)
251    pub expires_at: Option<u64>,
252    /// Type of ban
253    pub ban_type: BanType,
254}
255
256/// Types of bans
257#[derive(Debug, Clone, PartialEq, Eq)]
258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
259pub enum BanType {
260    /// Complete ban from group
261    Full,
262    /// Can view but not participate
263    ReadOnly,
264    /// Temporary suspension
265    Temporary,
266}
267
268/// The main Phalanx group for encrypted communication
269#[derive(Debug)]
270pub struct PhalanxGroup {
271    /// Group's unique identifier
272    group_id: [u8; 32],
273    /// Our identity in this group
274    identity: Identity,
275    /// Current group encryption key
276    group_key: SymmetricKey,
277    /// Group configuration
278    config: GroupConfig,
279    /// All group members
280    members: HashMap<[u8; 32], GroupMember>,
281    /// Message sequence counter
282    message_sequence: u64,
283    /// Key rotation sequence
284    key_sequence: u64,
285    /// Last key rotation time
286    last_key_rotation: u64,
287    /// Protocol version
288    version: ProtocolVersion,
289    /// Advanced key management system (temporarily commented out)
290    // key_manager: AdvancedKeyManager,
291    /// Group audit log
292    audit_log: Vec<AuditLogEntry>,
293    /// Group channels/subgroups
294    channels: HashMap<String, GroupChannel>,
295    /// Banned members list
296    banned_members: HashMap<[u8; 32], BanEntry>,
297}
298
299impl Default for GroupConfig {
300    fn default() -> Self {
301        Self {
302            max_members: 100,
303            key_rotation_interval: crate::constants::DEFAULT_KEY_ROTATION_INTERVAL,
304            persistent_storage: false,
305            visibility: GroupVisibility::Private,
306            admin_only_operations: vec![
307                GroupOperation::AddMember,
308                GroupOperation::RemoveMember,
309                GroupOperation::ChangeSettings,
310                GroupOperation::RotateKeys,
311            ],
312        }
313    }
314}
315
316impl PhalanxGroup {
317    /// Create a new Phalanx group
318    pub fn new(identity: Identity) -> Self {
319        Self::with_config(identity, GroupConfig::default())
320    }
321    
322    /// Get default permissions for a given role
323    fn default_permissions_for_role(role: &MemberRole) -> Vec<GroupPermission> {
324        use GroupPermission::*;
325        match role {
326            MemberRole::Owner => vec![
327                SendMessages, DeleteOwnMessages, DeleteAnyMessages, InviteMembers, 
328                RemoveMembers, ModifySettings, ManageRoles, RotateKeys, ViewAuditLogs,
329                ManageBans, CreateChannels
330            ],
331            MemberRole::Admin => vec![
332                SendMessages, DeleteOwnMessages, DeleteAnyMessages, InviteMembers,
333                RemoveMembers, ManageRoles, ViewAuditLogs, ManageBans, CreateChannels
334            ],
335            MemberRole::Moderator => vec![
336                SendMessages, DeleteOwnMessages, DeleteAnyMessages, ManageBans, ViewAuditLogs
337            ],
338            MemberRole::Member => vec![
339                SendMessages, DeleteOwnMessages
340            ],
341            MemberRole::Guest => vec![],
342        }
343    }
344    
345    /// Create a new group with custom configuration
346    pub fn with_config(identity: Identity, config: GroupConfig) -> Self {
347        let group_id = Self::generate_group_id(&identity.public_key());
348        let group_key = SymmetricKey::generate();
349        
350        let timestamp = SystemTime::now()
351            .duration_since(UNIX_EPOCH)
352            .map(|d| d.as_secs())
353            .unwrap_or(0);
354        
355        let mut members = HashMap::new();
356        let creator_member = GroupMember {
357            public_key: identity.public_key(),
358            ephemeral_key: None,
359            role: MemberRole::Owner,
360            joined_at: timestamp,
361            last_seen: Some(timestamp),
362            nickname: None,
363            status: MemberStatus::Active,
364            permissions: Self::default_permissions_for_role(&MemberRole::Owner),
365            presence: MemberPresence::Online,
366        };
367        
368        members.insert(identity.id(), creator_member);
369        
370        // Initialize key manager (simplified for now)
371        // let key_manager = AdvancedKeyManager::new().await.unwrap();
372        // TODO: Implement async constructor or simplify
373        
374        // Create initial audit log entry
375        let mut audit_log = Vec::new();
376        audit_log.push(AuditLogEntry {
377            timestamp,
378            actor: identity.id(),
379            action: AuditAction::MemberJoined,
380            target: Some(identity.id()),
381            details: Some("Group creator".to_string()),
382        });
383        
384        Self {
385            group_id,
386            identity,
387            group_key,
388            config,
389            members,
390            message_sequence: 0,
391            key_sequence: 0,
392            last_key_rotation: timestamp,
393            version: ProtocolVersion::current(),
394            // key_manager, // TODO: Re-enable when async issues are resolved
395            audit_log,
396            channels: HashMap::new(),
397            banned_members: HashMap::new(),
398        }
399    }
400    
401    /// Join an existing group using a handshake
402    pub fn join(
403        identity: Identity,
404        handshake: HandshakeMessage,
405        group_key: SymmetricKey,
406    ) -> Result<Self> {
407        let payload = handshake.verify_and_decrypt()?;
408        
409        let config = GroupConfig::default(); // TODO: Get from group info
410        
411        let timestamp = SystemTime::now()
412            .duration_since(UNIX_EPOCH)
413            .map(|d| d.as_secs())
414            .unwrap_or(0);
415        
416        let mut members = HashMap::new();
417        
418        // Add the joining member (self)
419        let member = GroupMember {
420            public_key: identity.public_key(),
421            ephemeral_key: Some(handshake.ephemeral_key),
422            role: MemberRole::Member,
423            joined_at: timestamp,
424            last_seen: Some(timestamp),
425            nickname: None,
426            status: MemberStatus::Active,
427            permissions: Self::default_permissions_for_role(&MemberRole::Member),
428            presence: MemberPresence::Online,
429        };
430        members.insert(identity.id(), member);
431        
432        // Add the sender of the handshake (group creator/inviter)
433        let sender = GroupMember {
434            public_key: handshake.sender_key.clone(),
435            ephemeral_key: Some(handshake.ephemeral_key),
436            role: MemberRole::Owner, // Assume sender is owner/admin
437            joined_at: timestamp, // We don't know actual join time
438            last_seen: Some(timestamp),
439            nickname: None,
440            status: MemberStatus::Active,
441            permissions: Self::default_permissions_for_role(&MemberRole::Owner),
442            presence: MemberPresence::Online,
443        };
444        members.insert(handshake.sender_key.id(), sender);
445        
446        Ok(Self {
447            group_id: payload.group_id,
448            identity,
449            group_key,
450            config,
451            members,
452            message_sequence: 0,
453            key_sequence: 0,
454            last_key_rotation: timestamp,
455            version: ProtocolVersion::current(),
456            // key_manager, // TODO: Re-enable when async issues are resolved
457            audit_log: Vec::new(),
458            channels: HashMap::new(),
459            banned_members: HashMap::new(),
460        })
461    }
462    
463    /// Get the group ID
464    pub fn group_id(&self) -> &[u8; 32] {
465        &self.group_id
466    }
467    
468    /// Get our identity
469    pub fn identity(&self) -> &Identity {
470        &self.identity
471    }
472    
473    /// Get group configuration
474    pub fn config(&self) -> &GroupConfig {
475        &self.config
476    }
477    
478    /// Get all group members
479    pub fn members(&self) -> &HashMap<[u8; 32], GroupMember> {
480        &self.members
481    }
482    
483    /// Get a specific member by their ID
484    pub fn get_member(&self, member_id: &[u8; 32]) -> Option<&GroupMember> {
485        self.members.get(member_id)
486    }
487    
488    /// Check if we're an admin or owner
489    pub fn is_admin(&self) -> bool {
490        if let Some(member) = self.members.get(&self.identity.id()) {
491            matches!(member.role, MemberRole::Admin | MemberRole::Owner)
492        } else {
493            false
494        }
495    }
496    
497    /// Check if we have a specific permission
498    pub fn has_permission(&self, permission: &GroupPermission) -> bool {
499        if let Some(member) = self.members.get(&self.identity.id()) {
500            member.permissions.contains(permission)
501        } else {
502            false
503        }
504    }
505    
506    /// Add a new member to the group
507    pub fn add_member(&mut self, member_key: PublicKey, role: MemberRole) -> Result<()> {
508        // Check permissions
509        if !self.has_permission(&GroupPermission::InviteMembers) {
510            return Err(PhalanxError::membership("No permission to add members"));
511        }
512        
513        // Check if member is banned
514        if self.banned_members.contains_key(&member_key.id()) {
515            return Err(PhalanxError::membership("Cannot add banned member"));
516        }
517        
518        // Check group size limit
519        if self.members.len() >= self.config.max_members {
520            return Err(PhalanxError::group("Group is at maximum capacity"));
521        }
522        
523        let timestamp = SystemTime::now()
524            .duration_since(UNIX_EPOCH)
525            .map(|d| d.as_secs())
526            .unwrap_or(0);
527        
528        let member = GroupMember {
529            public_key: member_key.clone(),
530            ephemeral_key: None,
531            role: role.clone(),
532            joined_at: timestamp,
533            last_seen: None,
534            nickname: None,
535            status: MemberStatus::Active,
536            permissions: Self::default_permissions_for_role(&role),
537            presence: MemberPresence::Online,
538        };
539        
540        let member_id = member_key.id();
541        self.members.insert(member_id, member);
542        
543        // Add to audit log
544        self.audit_log.push(AuditLogEntry {
545            timestamp,
546            actor: self.identity.id(),
547            action: AuditAction::MemberJoined,
548            target: Some(member_id),
549            details: Some(format!("Added with role: {:?}", role)),
550        });
551        
552        Ok(())
553    }
554    
555    /// Remove a member from the group
556    pub fn remove_member(&mut self, member_id: &[u8; 32]) -> Result<()> {
557        // Check permissions
558        if self.config.admin_only_operations.contains(&GroupOperation::RemoveMember) && !self.is_admin() {
559            return Err(PhalanxError::membership("Only admins can remove members"));
560        }
561        
562        // Can't remove yourself
563        if member_id == &self.identity.id() {
564            return Err(PhalanxError::membership("Cannot remove yourself"));
565        }
566        
567        // Can't remove the owner
568        if let Some(member) = self.members.get(member_id) {
569            if member.role == MemberRole::Owner {
570                return Err(PhalanxError::membership("Cannot remove group owner"));
571            }
572        }
573        
574        self.members.remove(member_id);
575        
576        // Trigger key rotation after member removal for security
577        self.rotate_keys()?;
578        
579        Ok(())
580    }
581    
582    /// Ban a member from the group
583    pub fn ban_member(&mut self, member_id: &[u8; 32], reason: Option<String>, duration: Option<u64>) -> Result<()> {
584        if !self.has_permission(&GroupPermission::ManageBans) {
585            return Err(PhalanxError::membership("No permission to ban members"));
586        }
587        
588        let timestamp = SystemTime::now()
589            .duration_since(UNIX_EPOCH)
590            .map(|d| d.as_secs())
591            .unwrap_or(0);
592        
593        // Remove from members if present
594        self.members.remove(member_id);
595        
596        // Add to banned list
597        let ban_entry = BanEntry {
598            banned_at: timestamp,
599            banned_by: self.identity.id(),
600            reason: reason.clone(),
601            expires_at: duration.map(|d| timestamp + d),
602            ban_type: BanType::Full,
603        };
604        
605        self.banned_members.insert(*member_id, ban_entry);
606        
607        // Add to audit log
608        self.audit_log.push(AuditLogEntry {
609            timestamp,
610            actor: self.identity.id(),
611            action: AuditAction::MemberBanned,
612            target: Some(*member_id),
613            details: reason,
614        });
615        
616        Ok(())
617    }
618    
619    /// Unban a member
620    pub fn unban_member(&mut self, member_id: &[u8; 32]) -> Result<()> {
621        if !self.has_permission(&GroupPermission::ManageBans) {
622            return Err(PhalanxError::membership("No permission to unban members"));
623        }
624        
625        self.banned_members.remove(member_id);
626        
627        let timestamp = SystemTime::now()
628            .duration_since(UNIX_EPOCH)
629            .map(|d| d.as_secs())
630            .unwrap_or(0);
631        
632        // Add to audit log
633        self.audit_log.push(AuditLogEntry {
634            timestamp,
635            actor: self.identity.id(),
636            action: AuditAction::MemberUnbanned,
637            target: Some(*member_id),
638            details: None,
639        });
640        
641        Ok(())
642    }
643    
644    /// Change a member's role
645    pub fn change_member_role(&mut self, member_id: &[u8; 32], new_role: MemberRole) -> Result<()> {
646        if !self.has_permission(&GroupPermission::ManageRoles) {
647            return Err(PhalanxError::membership("No permission to change member roles"));
648        }
649        
650        let member = self.members.get_mut(member_id)
651            .ok_or_else(|| PhalanxError::membership("Member not found"))?;
652        
653        let old_role = member.role.clone();
654        member.role = new_role.clone();
655        member.permissions = Self::default_permissions_for_role(&new_role);
656        
657        let timestamp = SystemTime::now()
658            .duration_since(UNIX_EPOCH)
659            .map(|d| d.as_secs())
660            .unwrap_or(0);
661        
662        // Add to audit log
663        self.audit_log.push(AuditLogEntry {
664            timestamp,
665            actor: self.identity.id(),
666            action: AuditAction::RoleChanged,
667            target: Some(*member_id),
668            details: Some(format!("{:?} -> {:?}", old_role, new_role)),
669        });
670        
671        Ok(())
672    }
673    
674    /// Set custom permissions for a member
675    pub fn set_member_permissions(&mut self, member_id: &[u8; 32], permissions: Vec<GroupPermission>) -> Result<()> {
676        if !self.has_permission(&GroupPermission::ManageRoles) {
677            return Err(PhalanxError::membership("No permission to set member permissions"));
678        }
679        
680        let member = self.members.get_mut(member_id)
681            .ok_or_else(|| PhalanxError::membership("Member not found"))?;
682        
683        member.permissions = permissions;
684        
685        Ok(())
686    }
687    
688    /// Create a new channel/subgroup
689    pub fn create_channel(&mut self, channel_id: String, name: String, description: Option<String>) -> Result<()> {
690        if !self.has_permission(&GroupPermission::CreateChannels) {
691            return Err(PhalanxError::membership("No permission to create channels"));
692        }
693        
694        if self.channels.contains_key(&channel_id) {
695            return Err(PhalanxError::group("Channel already exists"));
696        }
697        
698        let timestamp = SystemTime::now()
699            .duration_since(UNIX_EPOCH)
700            .map(|d| d.as_secs())
701            .unwrap_or(0);
702        
703        let channel = GroupChannel {
704            id: channel_id.clone(),
705            name,
706            description,
707            members: HashSet::new(),
708            permissions: HashMap::new(),
709            archived: false,
710            created_at: timestamp,
711            last_activity: None,
712        };
713        
714        let channel_id_for_audit = channel_id.clone();
715        self.channels.insert(channel_id, channel);
716        
717        // Add to audit log
718        self.audit_log.push(AuditLogEntry {
719            timestamp,
720            actor: self.identity.id(),
721            action: AuditAction::ChannelCreated,
722            target: None,
723            details: Some(format!("Channel: {}", channel_id_for_audit)),
724        });
725        
726        Ok(())
727    }
728    
729    /// Add member to a channel
730    pub fn add_member_to_channel(&mut self, channel_id: &str, member_id: &[u8; 32]) -> Result<()> {
731        if !self.has_permission(&GroupPermission::ManageRoles) {
732            return Err(PhalanxError::membership("No permission to manage channel membership"));
733        }
734        
735        // Verify member exists in group
736        if !self.members.contains_key(member_id) {
737            return Err(PhalanxError::membership("Member not found in group"));
738        }
739        
740        let channel = self.channels.get_mut(channel_id)
741            .ok_or_else(|| PhalanxError::group("Channel not found"))?;
742        
743        channel.members.insert(*member_id);
744        Ok(())
745    }
746    
747    /// Set member presence
748    pub fn set_presence(&mut self, presence: MemberPresence) -> Result<()> {
749        let member = self.members.get_mut(&self.identity.id())
750            .ok_or_else(|| PhalanxError::membership("Member not found"))?;
751        
752        member.presence = presence;
753        
754        let timestamp = SystemTime::now()
755            .duration_since(UNIX_EPOCH)
756            .map(|d| d.as_secs())
757            .unwrap_or(0);
758        member.last_seen = Some(timestamp);
759        
760        Ok(())
761    }
762    
763    /// Get audit log entries
764    pub fn get_audit_log(&self) -> Result<&Vec<AuditLogEntry>> {
765        if !self.has_permission(&GroupPermission::ViewAuditLogs) {
766            return Err(PhalanxError::membership("No permission to view audit logs"));
767        }
768        Ok(&self.audit_log)
769    }
770    
771    /// Advanced key rotation using the key manager
772    pub fn advanced_key_rotation(&mut self) -> Result<()> {
773        if !self.has_permission(&GroupPermission::RotateKeys) {
774            return Err(PhalanxError::membership("No permission to rotate keys"));
775        }
776        
777        // Simplified key rotation for now
778        self.group_key = SymmetricKey::generate();
779        self.key_sequence += 1;
780        
781        let timestamp = SystemTime::now()
782            .duration_since(UNIX_EPOCH)
783            .map(|d| d.as_secs())
784            .unwrap_or(0);
785        self.last_key_rotation = timestamp;
786        
787        // Add to audit log
788        self.audit_log.push(AuditLogEntry {
789            timestamp,
790            actor: self.identity.id(),
791            action: AuditAction::KeysRotated,
792            target: None,
793            details: Some(format!("Advanced rotation to version {}", self.key_sequence)),
794        });
795        
796        Ok(())
797    }
798    
799    /// Schedule automatic key rotation
800    pub fn schedule_key_rotation(&mut self, _policy: RotationPolicy) -> Result<()> {
801        if !self.has_permission(&GroupPermission::RotateKeys) {
802            return Err(PhalanxError::membership("No permission to schedule key rotation"));
803        }
804        
805        // TODO: Implement when key manager is re-enabled
806        Ok(())
807    }
808    
809    /// Get group health metrics
810    pub fn get_health_metrics(&self) -> GroupHealthMetrics {
811        let timestamp = SystemTime::now()
812            .duration_since(UNIX_EPOCH)
813            .map(|d| d.as_secs())
814            .unwrap_or(0);
815        
816        let active_members = self.members.values()
817            .filter(|m| {
818                if let Some(last_seen) = m.last_seen {
819                    timestamp - last_seen < 3600 // Active within last hour
820                } else {
821                    false
822                }
823            })
824            .count();
825        
826        let banned_count = self.banned_members.len();
827        let channel_count = self.channels.len();
828        
829        let key_rotation_health = if self.needs_key_rotation() {
830            HealthStatus::Warning
831        } else {
832            HealthStatus::Healthy
833        };
834        
835        GroupHealthMetrics {
836            total_members: self.members.len(),
837            active_members,
838            banned_members: banned_count,
839            channels: channel_count,
840            key_rotation_health,
841            last_activity: timestamp,
842        }
843    }
844    
845    /// Encrypt a message for the group
846    pub fn encrypt_message(&mut self, content: &MessageContent) -> Result<GroupMessage> {
847        self.message_sequence += 1;
848        
849        GroupMessage::new(
850            &self.identity,
851            MessageType::Text,
852            content,
853            self.message_sequence,
854            &self.group_key,
855        )
856    }
857    
858    /// Decrypt a group message
859    pub fn decrypt_message(&self, message: &GroupMessage) -> Result<MessageContent> {
860        // Verify sender is a group member
861        let sender_id = message.sender.id();
862        if !self.members.contains_key(&sender_id) {
863            return Err(PhalanxError::membership("Message from non-member"));
864        }
865        
866        message.decrypt(&self.group_key)
867    }
868    
869    /// Rotate group encryption keys
870    pub fn rotate_keys(&mut self) -> Result<KeyRotationMessage> {
871        // Check permissions
872        if self.config.admin_only_operations.contains(&GroupOperation::RotateKeys) && !self.is_admin() {
873            return Err(PhalanxError::membership("Only admins can rotate keys"));
874        }
875        
876        // Generate new group key
877        self.group_key = SymmetricKey::generate();
878        self.key_sequence += 1;
879        
880        // Update timestamp
881        self.last_key_rotation = SystemTime::now()
882            .duration_since(UNIX_EPOCH)
883            .map(|d| d.as_secs())
884            .unwrap_or(0);
885        
886        // Collect member keys for rotation message
887        let mut member_keys = Vec::new();
888        for member in self.members.values_mut() {
889            if let Some(ephemeral) = &member.ephemeral_key {
890                member_keys.push((member.public_key.clone(), *ephemeral));
891            }
892        }
893        
894        KeyRotationMessage::new(&self.identity, self.key_sequence, member_keys)
895    }
896    
897    /// Check if key rotation is needed
898    pub fn needs_key_rotation(&self) -> bool {
899        let current_time = SystemTime::now()
900            .duration_since(UNIX_EPOCH)
901            .map(|d| d.as_secs())
902            .unwrap_or(0);
903        
904        current_time - self.last_key_rotation >= self.config.key_rotation_interval
905    }
906    
907    /// Update member's last seen timestamp
908    pub fn update_member_activity(&mut self, member_id: &[u8; 32]) {
909        if let Some(member) = self.members.get_mut(member_id) {
910            let timestamp = SystemTime::now()
911                .duration_since(UNIX_EPOCH)
912                .map(|d| d.as_secs())
913                .unwrap_or(0);
914            member.last_seen = Some(timestamp);
915        }
916    }
917    
918    /// Set member nickname
919    pub fn set_member_nickname(&mut self, member_id: &[u8; 32], nickname: Option<String>) -> Result<()> {
920        let member = self.members.get_mut(member_id)
921            .ok_or_else(|| PhalanxError::membership("Member not found"))?;
922        
923        member.nickname = nickname;
924        Ok(())
925    }
926    
927    /// Generate a group ID from creator's public key
928    fn generate_group_id(creator_key: &PublicKey) -> [u8; 32] {
929        let timestamp = SystemTime::now()
930            .duration_since(UNIX_EPOCH)
931            .map(|d| d.as_millis() as u64)
932            .unwrap_or(0)
933            .to_be_bytes();
934        hash_multiple(&[
935            &creator_key.id(),
936            &timestamp,
937            b"PHALANX_GROUP_V1",
938        ])
939    }
940    
941    /// Create a handshake for joining this group
942    pub fn create_handshake(&self) -> Result<HandshakeMessage> {
943        HandshakeMessage::new(
944            &self.identity,
945            self.group_id,
946            vec!["phalanx/v1".to_string()],
947            "phalanx-client/1.0".to_string(),
948        )
949    }
950    
951    /// Create a handshake with encrypted group key for secure key sharing
952    pub fn create_handshake_with_group_key(&mut self, recipient_public_key: &PublicKey) -> Result<HandshakeMessage> {
953        HandshakeMessage::new_with_group_key(
954            &mut self.identity,
955            recipient_public_key,
956            self.group_id,
957            vec!["phalanx/v1".to_string()],
958            "phalanx-client/1.0".to_string(),
959            &self.group_key,
960        )
961    }
962    
963    /// Join a group by extracting the group key from a handshake message
964    pub fn join_with_handshake(
965        mut identity: Identity,
966        handshake: HandshakeMessage,
967    ) -> Result<Self> {
968        // Extract group key from handshake
969        let group_key = handshake.extract_group_key(&mut identity)?
970            .ok_or_else(|| PhalanxError::protocol("No group key in handshake message"))?;
971        
972        // Use the existing join method with the extracted key
973        Self::join(identity, handshake, group_key)
974    }
975    
976    /// Get group statistics
977    pub fn stats(&self) -> GroupStats {
978        let active_members = self.members.values()
979            .filter(|m| {
980                if let Some(last_seen) = m.last_seen {
981                    let now = SystemTime::now()
982                        .duration_since(UNIX_EPOCH)
983                        .map(|d| d.as_secs())
984                        .unwrap_or(0);
985                    now - last_seen < 3600 // Active within last hour
986                } else {
987                    false
988                }
989            })
990            .count();
991        
992        GroupStats {
993            total_members: self.members.len(),
994            active_members,
995            message_count: self.message_sequence,
996            key_rotation_count: self.key_sequence,
997            created_at: self.members.get(&self.identity.id())
998                .map(|m| m.joined_at)
999                .unwrap_or(0),
1000        }
1001    }
1002}
1003
1004/// Group statistics
1005#[derive(Debug, Clone)]
1006#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1007pub struct GroupStats {
1008    /// Total number of members
1009    pub total_members: usize,
1010    /// Number of recently active members
1011    pub active_members: usize,
1012    /// Total messages sent
1013    pub message_count: u64,
1014    /// Number of key rotations performed
1015    pub key_rotation_count: u64,
1016    /// Group creation timestamp
1017    pub created_at: u64,
1018}
1019
1020/// Group health metrics
1021#[derive(Debug, Clone)]
1022#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1023pub struct GroupHealthMetrics {
1024    /// Total number of members
1025    pub total_members: usize,
1026    /// Number of recently active members
1027    pub active_members: usize,
1028    /// Number of banned members
1029    pub banned_members: usize,
1030    /// Number of channels
1031    pub channels: usize,
1032    /// Key rotation health status
1033    pub key_rotation_health: HealthStatus,
1034    /// Last group activity timestamp
1035    pub last_activity: u64,
1036}
1037
1038/// Health status indicator
1039#[derive(Debug, Clone, PartialEq, Eq)]
1040#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1041pub enum HealthStatus {
1042    /// All systems healthy
1043    Healthy,
1044    /// Minor issues detected
1045    Warning,
1046    /// Critical issues detected
1047    Critical,
1048}
1049
1050#[cfg(test)]
1051mod tests {
1052    use super::*;
1053    use crate::message::MessageContent;
1054    
1055    #[test]
1056    fn test_group_creation() {
1057        let identity = Identity::generate();
1058        let group = PhalanxGroup::new(identity.clone());
1059        
1060        assert_eq!(group.members.len(), 1);
1061        assert!(group.members.contains_key(&identity.id()));
1062        assert!(group.is_admin()); // Creator is owner/admin
1063    }
1064    
1065    #[test]
1066    fn test_message_encryption_decryption() {
1067        let identity = Identity::generate();
1068        let mut group = PhalanxGroup::new(identity);
1069        
1070        let content = MessageContent::text("Hello, group!");
1071        let encrypted = group.encrypt_message(&content).unwrap();
1072        let decrypted = group.decrypt_message(&encrypted).unwrap();
1073        
1074        assert_eq!(decrypted.as_string().unwrap(), "Hello, group!");
1075    }
1076    
1077    #[test]
1078    fn test_member_management() {
1079        let admin = Identity::generate();
1080        let member = Identity::generate();
1081        
1082        let mut group = PhalanxGroup::new(admin);
1083        
1084        // Add member
1085        group.add_member(member.public_key(), MemberRole::Member).unwrap();
1086        assert_eq!(group.members.len(), 2);
1087        
1088        // Remove member
1089        group.remove_member(&member.id()).unwrap();
1090        // After removal, key rotation happens, so we just check member count
1091        assert_eq!(group.members.len(), 1);
1092    }
1093    
1094    #[test]
1095    fn test_key_rotation() {
1096        let identity = Identity::generate();
1097        let mut group = PhalanxGroup::new(identity);
1098        
1099        let old_sequence = group.key_sequence;
1100        let rotation_msg = group.rotate_keys().unwrap();
1101        
1102        assert_eq!(group.key_sequence, old_sequence + 1);
1103        assert!(rotation_msg.verify(&group.identity.public_key()).is_ok());
1104    }
1105    
1106    #[test]
1107    fn test_permissions() {
1108        let admin = Identity::generate();
1109        let member = Identity::generate();
1110        
1111        let mut group = PhalanxGroup::new(admin);
1112        
1113        // Add a regular member
1114        group.add_member(member.public_key(), MemberRole::Member).unwrap();
1115        
1116        // Change identity to the member (simulate member trying to add another member)
1117        group.identity = member;
1118        
1119        let new_member = Identity::generate();
1120        let result = group.add_member(new_member.public_key(), MemberRole::Member);
1121        
1122        // Should fail because regular members can't add other members
1123        assert!(result.is_err());
1124    }
1125}