saorsa_core/identity/
enhanced.rs

1// Copyright 2024 Saorsa Labs Limited
2//
3// This software is dual-licensed under:
4// - GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)
5// - Commercial License
6//
7// For AGPL-3.0 license, see LICENSE-AGPL-3.0
8// For commercial licensing, contact: david@saorsalabs.com
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under these licenses is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
14//! Enhanced identity system with quantum threshold cryptography integration
15
16use crate::identity::manager::{IdentityManager, UserIdentity};
17use crate::quantum_crypto::ant_quic_integration::{
18    generate_ml_dsa_keypair, generate_ml_kem_keypair,
19};
20use crate::quantum_crypto::{CryptoCapabilities, QuantumPeerIdentity};
21use crate::threshold::{ParticipantInfo, ParticipantRole, ThresholdGroupManager};
22use serde::{Deserialize, Serialize};
23use std::collections::HashMap;
24use std::time::SystemTime;
25use thiserror::Error;
26
27/// Enhanced identity errors
28#[derive(Debug, Error)]
29pub enum EnhancedIdentityError {
30    #[error("Quantum crypto error: {0}")]
31    QuantumError(#[from] crate::quantum_crypto::QuantumCryptoError),
32
33    #[error("Threshold error: {0}")]
34    ThresholdError(#[from] crate::threshold::ThresholdError),
35
36    #[error("Organization error: {0}")]
37    OrganizationError(String),
38
39    #[error("Permission denied: {0}")]
40    PermissionDenied(String),
41
42    #[error("System time error: {0}")]
43    SystemTime(String),
44
45    #[error("Anyhow error: {0}")]
46    AnyhowError(#[from] anyhow::Error),
47}
48
49type Result<T> = std::result::Result<T, EnhancedIdentityError>;
50
51/// Enhanced identity with quantum and threshold capabilities
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct EnhancedIdentity {
54    /// Base user identity (backward compatible)
55    pub base_identity: UserIdentity,
56
57    /// Quantum-resistant peer identity
58    pub quantum_identity: QuantumPeerIdentity,
59
60    /// Threshold groups this user belongs to
61    pub threshold_groups: Vec<GroupMembership>,
62
63    /// Organizations this user belongs to
64    pub organizations: Vec<OrganizationMembership>,
65
66    /// Device registry for multi-device support
67    pub devices: DeviceRegistry,
68
69    /// Last sync timestamp
70    pub last_sync: SystemTime,
71}
72
73/// Group membership information
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct GroupMembership {
76    pub group_id: crate::quantum_crypto::types::GroupId,
77    pub role: ParticipantRole,
78    pub joined_at: SystemTime,
79    pub permissions: Vec<Permission>,
80}
81
82/// Organization membership
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct OrganizationMembership {
85    pub org_id: OrganizationId,
86    pub department: Option<DepartmentId>,
87    pub team: Option<TeamId>,
88    pub role: OrganizationRole,
89    pub joined_at: SystemTime,
90}
91
92/// Organization identifier
93#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
94pub struct OrganizationId(pub String);
95
96/// Department identifier
97#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
98pub struct DepartmentId(pub String);
99
100/// Team identifier
101#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
102pub struct TeamId(pub String);
103
104/// Organization role
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
106pub enum OrganizationRole {
107    Owner,
108    Admin,
109    Manager,
110    Member,
111    Guest,
112}
113
114/// Permission types
115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
116pub enum Permission {
117    // Chat permissions
118    ChatCreateChannel,
119    ChatDeleteChannel,
120    ChatInviteMembers,
121    ChatModerate,
122    ChatVoiceVideo,
123
124    // Discuss permissions
125    DiscussCreateCategory,
126    DiscussModerate,
127    DiscussPin,
128    DiscussWikiEdit,
129
130    // Project permissions
131    ProjectCreate,
132    ProjectDelete,
133    ProjectManageMembers,
134    ProjectUploadFiles,
135    ProjectApprove,
136
137    // Admin permissions
138    AdminManageRoles,
139    AdminViewAudit,
140    AdminManageOrg,
141}
142
143/// Device registry for multi-device support
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct DeviceRegistry {
146    /// Primary device ID (first device)
147    pub primary_device_id: DeviceId,
148
149    /// All registered devices
150    pub devices: HashMap<DeviceId, DeviceInfo>,
151
152    /// Device-specific keys (encrypted with master key)
153    pub device_keys: HashMap<DeviceId, EncryptedDeviceKey>,
154}
155
156/// Device identifier
157#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
158pub struct DeviceId(pub String);
159
160/// Device information
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct DeviceInfo {
163    pub name: String,
164    pub device_type: DeviceType,
165    pub last_seen: SystemTime,
166    pub added_at: SystemTime,
167    pub public_key: Vec<u8>,
168}
169
170/// Device type
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub enum DeviceType {
173    Desktop,
174    Mobile,
175    Tablet,
176    Web,
177}
178
179/// Encrypted device key
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct EncryptedDeviceKey {
182    pub encrypted_key: Vec<u8>,
183    pub nonce: Vec<u8>,
184}
185
186/// Organization structure
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct Organization {
189    pub id: OrganizationId,
190    pub name: String,
191    pub description: String,
192    pub root_group: crate::quantum_crypto::types::GroupId,
193    pub departments: Vec<Department>,
194    pub created_at: SystemTime,
195    pub settings: OrganizationSettings,
196}
197
198/// Department structure
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct Department {
201    pub id: DepartmentId,
202    pub name: String,
203    pub description: String,
204    pub manager_group: crate::quantum_crypto::types::GroupId,
205    pub teams: Vec<Team>,
206    pub parent_org: OrganizationId,
207}
208
209/// Team structure
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct Team {
212    pub id: TeamId,
213    pub name: String,
214    pub description: String,
215    pub lead_group: crate::quantum_crypto::types::GroupId,
216    pub member_group: crate::quantum_crypto::types::GroupId,
217    pub parent_dept: DepartmentId,
218}
219
220/// Organization settings
221#[derive(Debug, Clone, Serialize, Deserialize)]
222pub struct OrganizationSettings {
223    pub default_chat_encryption: bool,
224    pub require_2fa: bool,
225    pub session_timeout: std::time::Duration,
226    pub allowed_domains: Vec<String>,
227    pub features: OrganizationFeatures,
228}
229
230/// Organization features
231#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct OrganizationFeatures {
233    pub chat_enabled: bool,
234    pub discuss_enabled: bool,
235    pub projects_enabled: bool,
236    pub voice_video_enabled: bool,
237    pub ai_enabled: bool,
238}
239
240impl Default for OrganizationFeatures {
241    fn default() -> Self {
242        Self {
243            chat_enabled: true,
244            discuss_enabled: true,
245            projects_enabled: true,
246            voice_video_enabled: true,
247            ai_enabled: true,
248        }
249    }
250}
251
252/// Enhanced identity manager
253pub struct EnhancedIdentityManager {
254    /// Base identity manager
255    pub base_manager: IdentityManager,
256
257    /// Threshold group manager
258    pub group_manager: ThresholdGroupManager,
259
260    /// Organization registry
261    pub organizations: HashMap<OrganizationId, Organization>,
262}
263
264impl EnhancedIdentityManager {
265    /// Create new enhanced identity manager
266    pub fn new(base_manager: IdentityManager) -> Self {
267        // Create a temporary quantum identity for the group manager
268        let temp_quantum_identity = QuantumPeerIdentity {
269            peer_id: crate::quantum_crypto::types::PeerId(vec![0; 32]),
270            ml_dsa_public_key: vec![0; 32], // Placeholder Vec<u8>
271            ml_kem_public_key: vec![0; 32], // Placeholder Vec<u8>
272            frost_public_key: None,
273            capabilities: CryptoCapabilities::default(),
274            created_at: SystemTime::now(),
275        };
276
277        Self {
278            base_manager,
279            group_manager: ThresholdGroupManager::new(temp_quantum_identity),
280            organizations: HashMap::new(),
281        }
282    }
283
284    /// Create enhanced identity from base identity
285    pub async fn create_enhanced_identity(
286        &mut self,
287        base_identity: UserIdentity,
288        device_name: String,
289        device_type: DeviceType,
290    ) -> Result<EnhancedIdentity> {
291        // Generate quantum-resistant keys
292        let capabilities = CryptoCapabilities::default();
293        // Generate PQC keys using ant-quic directly
294        let (ml_dsa_pub, _ml_dsa_sec) = generate_ml_dsa_keypair()?;
295        let (ml_kem_pub, _ml_kem_sec) = generate_ml_kem_keypair()?;
296
297        // Create quantum peer identity
298        let peer_id =
299            crate::quantum_crypto::types::PeerId(base_identity.user_id.as_bytes().to_vec());
300
301        // Serialize the PQC public keys to bytes
302        // ant-quic 0.8.14 provides as_bytes() methods for key serialization
303        let ml_dsa_pub_bytes = ml_dsa_pub.as_bytes().to_vec();
304        let ml_kem_pub_bytes = ml_kem_pub.as_bytes().to_vec();
305
306        let quantum_identity = QuantumPeerIdentity {
307            peer_id,
308            ml_dsa_public_key: ml_dsa_pub_bytes,
309            ml_kem_public_key: ml_kem_pub_bytes,
310            frost_public_key: None, // Optional threshold key
311            capabilities,
312            created_at: SystemTime::now(),
313        };
314
315        // Update group manager with the new quantum identity
316        self.group_manager.local_identity = quantum_identity.clone();
317
318        // Create device registry
319        let device_id = DeviceId(format!(
320            "{}-{}",
321            base_identity.user_id,
322            SystemTime::now()
323                .duration_since(SystemTime::UNIX_EPOCH)
324                .map_err(|e| EnhancedIdentityError::SystemTime(format!(
325                    "System time error: {}",
326                    e
327                )))?
328                .as_secs()
329        ));
330
331        let device_info = DeviceInfo {
332            name: device_name,
333            device_type,
334            last_seen: SystemTime::now(),
335            added_at: SystemTime::now(),
336            public_key: vec![0u8; 32], // Placeholder - no legacy Ed25519 key for now
337        };
338
339        let mut devices = HashMap::new();
340        devices.insert(device_id.clone(), device_info);
341
342        let device_registry = DeviceRegistry {
343            primary_device_id: device_id,
344            devices,
345            device_keys: HashMap::new(),
346        };
347
348        Ok(EnhancedIdentity {
349            base_identity,
350            quantum_identity,
351            threshold_groups: Vec::new(),
352            organizations: Vec::new(),
353            devices: device_registry,
354            last_sync: SystemTime::now(),
355        })
356    }
357
358    /// Create new organization
359    pub async fn create_organization(
360        &mut self,
361        name: String,
362        description: String,
363        owner_identity: &EnhancedIdentity,
364    ) -> Result<Organization> {
365        // Create root threshold group for organization
366        let owner_info = ParticipantInfo {
367            participant_id: crate::quantum_crypto::types::ParticipantId(0),
368            public_key: owner_identity.quantum_identity.ml_dsa_public_key.clone(),
369            frost_share_commitment: crate::quantum_crypto::types::FrostCommitment(vec![0; 32]),
370            role: ParticipantRole::Leader {
371                permissions: crate::threshold::LeaderPermissions::default(),
372            },
373            status: crate::threshold::ParticipantStatus::Active,
374            joined_at: SystemTime::now(),
375            metadata: HashMap::new(),
376        };
377
378        let group_config = crate::threshold::GroupConfig {
379            threshold: 1,
380            participants: vec![owner_info],
381            metadata: crate::threshold::GroupMetadata {
382                name: format!("{name} Root Group"),
383                description: "Organization root authority".to_string(),
384                purpose: crate::threshold::GroupPurpose::Governance,
385                parent_group: None,
386                custom_data: HashMap::new(),
387            },
388        };
389
390        let root_group = self.group_manager.create_group(group_config).await?;
391
392        let org = Organization {
393            id: OrganizationId(uuid::Uuid::new_v4().to_string()),
394            name,
395            description,
396            root_group: root_group.group_id,
397            departments: Vec::new(),
398            created_at: SystemTime::now(),
399            settings: OrganizationSettings {
400                default_chat_encryption: true,
401                require_2fa: false,
402                session_timeout: std::time::Duration::from_secs(86400), // 24 hours
403                allowed_domains: Vec::new(),
404                features: OrganizationFeatures::default(),
405            },
406        };
407
408        self.organizations.insert(org.id.clone(), org.clone());
409
410        Ok(org)
411    }
412
413    /// Add user to organization
414    pub async fn add_user_to_organization(
415        &mut self,
416        user: &mut EnhancedIdentity,
417        org_id: &OrganizationId,
418        role: OrganizationRole,
419    ) -> Result<()> {
420        let _org = self.organizations.get(org_id).ok_or_else(|| {
421            EnhancedIdentityError::OrganizationError("Organization not found".to_string())
422        })?;
423
424        let membership = OrganizationMembership {
425            org_id: org_id.clone(),
426            department: None,
427            team: None,
428            role,
429            joined_at: SystemTime::now(),
430        };
431
432        user.organizations.push(membership);
433
434        Ok(())
435    }
436
437    /// Check permission for user in organization
438    pub fn check_permission(
439        &self,
440        user: &EnhancedIdentity,
441        org_id: &OrganizationId,
442        permission: Permission,
443    ) -> Result<()> {
444        let membership = user
445            .organizations
446            .iter()
447            .find(|m| &m.org_id == org_id)
448            .ok_or_else(|| {
449                EnhancedIdentityError::PermissionDenied("User not in organization".to_string())
450            })?;
451
452        // Check role-based permissions
453        let allowed = match (&membership.role, &permission) {
454            (OrganizationRole::Owner, _) => true,
455            (OrganizationRole::Admin, Permission::AdminManageOrg) => false,
456            (OrganizationRole::Admin, _) => true,
457            (OrganizationRole::Manager, Permission::AdminManageRoles) => false,
458            (OrganizationRole::Manager, Permission::AdminViewAudit) => false,
459            (OrganizationRole::Manager, Permission::AdminManageOrg) => false,
460            (OrganizationRole::Manager, _) => true,
461            (OrganizationRole::Member, perm) => matches!(
462                perm,
463                Permission::ChatCreateChannel
464                    | Permission::ChatInviteMembers
465                    | Permission::ChatVoiceVideo
466                    | Permission::DiscussWikiEdit
467                    | Permission::ProjectUploadFiles
468            ),
469            (OrganizationRole::Guest, perm) => matches!(perm, Permission::ChatVoiceVideo),
470        };
471
472        if allowed {
473            Ok(())
474        } else {
475            Err(EnhancedIdentityError::PermissionDenied(format!(
476                "Permission {:?} denied for role {:?}",
477                permission, membership.role
478            )))
479        }
480    }
481}