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