1use crate::types::UUID;
27use crate::Result;
28use async_trait::async_trait;
29use serde::{Deserialize, Serialize};
30use std::collections::HashMap;
31use std::sync::Arc;
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct LearningFeedback {
40 pub response_id: UUID,
42 pub score: f32,
44 pub text: Option<String>,
46 pub source: FeedbackSource,
48 pub timestamp: i64,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
54pub enum FeedbackSource {
55 User,
57 Evaluator,
59 System,
61 Expert,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct TrainingResult {
68 pub success: bool,
70 pub loss: Option<f32>,
72 pub examples_count: usize,
74 pub duration_secs: f64,
76 pub error: Option<String>,
78 pub metrics: HashMap<String, f64>,
80}
81
82#[async_trait]
87pub trait LearningProvider: Send + Sync {
88 fn name(&self) -> &str;
90
91 async fn collect_feedback(&self, feedback: LearningFeedback) -> Result<()>;
93
94 async fn get_feedback(&self, limit: usize) -> Result<Vec<LearningFeedback>>;
96
97 fn supports_training(&self) -> bool {
99 false
100 }
101
102 async fn train(&self) -> Result<TrainingResult> {
105 Ok(TrainingResult {
106 success: false,
107 loss: None,
108 examples_count: 0,
109 duration_secs: 0.0,
110 error: Some("Training requires enterprise license".to_string()),
111 metrics: HashMap::new(),
112 })
113 }
114
115 async fn enable_continual_learning(&self) -> Result<bool> {
117 Ok(false)
118 }
119
120 async fn load_adapter(&self, _adapter_name: &str) -> Result<bool> {
122 Ok(false)
123 }
124
125 async fn list_adapters(&self) -> Result<Vec<String>> {
127 Ok(vec![])
128 }
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct PiiFinding {
138 pub pii_type: PiiType,
140 pub start: usize,
142 pub end: usize,
144 pub matched_text: String,
146 pub severity: Severity,
148 pub confidence: f32,
150}
151
152#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
154pub enum PiiType {
155 Ssn,
157 Email,
159 Phone,
161 CreditCard,
163 IpAddress,
165 ApiKey,
167 Name,
169 Address,
171 DateOfBirth,
173 MedicalId,
175 Custom(String),
177}
178
179#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
181pub enum Severity {
182 Low,
184 Medium,
186 High,
188 Critical,
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
194pub enum ComplianceFramework {
195 Hipaa,
197 Gdpr,
199 Fda,
201 PciDss,
203 Soc2,
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct ComplianceCheckResult {
210 pub framework: ComplianceFramework,
212 pub compliant: bool,
214 pub findings: Vec<ComplianceFinding>,
216 pub recommendations: Vec<String>,
218 pub checked_at: i64,
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
224pub struct ComplianceFinding {
225 pub code: String,
227 pub description: String,
229 pub severity: Severity,
231 pub remediation: Option<String>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct AuditEntry {
238 pub id: UUID,
240 pub timestamp: i64,
242 pub actor: String,
244 pub action: String,
246 pub resource: String,
248 pub outcome: AuditOutcome,
250 pub context: HashMap<String, serde_json::Value>,
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
256pub enum AuditOutcome {
257 Success,
259 Failure,
261 Denied,
263}
264
265#[async_trait]
270pub trait ComplianceProvider: Send + Sync {
271 fn name(&self) -> &str;
273
274 async fn scan_pii(&self, text: &str) -> Result<Vec<PiiFinding>>;
278
279 fn redact(&self, text: &str) -> String;
281
282 fn supports_framework(&self, _framework: ComplianceFramework) -> bool {
286 false
287 }
288
289 async fn check_compliance(
291 &self,
292 _framework: ComplianceFramework,
293 _context: &str,
294 ) -> Result<Option<ComplianceCheckResult>> {
295 Ok(None)
296 }
297
298 async fn audit_log(&self, _entry: AuditEntry) -> Result<()> {
300 Ok(())
301 }
302
303 async fn get_audit_logs(
305 &self,
306 _start: i64,
307 _end: i64,
308 _limit: usize,
309 ) -> Result<Vec<AuditEntry>> {
310 Ok(vec![])
311 }
312
313 async fn run_audit(&self, _auditor: &str) -> Result<Option<ComplianceAuditReport>> {
315 Ok(None)
316 }
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct ComplianceAuditReport {
322 pub id: UUID,
324 pub auditor: String,
326 pub frameworks: Vec<ComplianceFramework>,
328 pub compliance_percentage: f32,
330 pub findings: HashMap<String, Vec<ComplianceFinding>>,
332 pub generated_at: i64,
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct NodeInfo {
343 pub id: String,
345 pub address: String,
347 pub status: NodeStatus,
349 pub resources: NodeResources,
351 pub last_heartbeat: i64,
353}
354
355#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
357pub enum NodeStatus {
358 Healthy,
360 Overloaded,
362 Unhealthy,
364 Draining,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
370pub struct NodeResources {
371 pub cpu_cores: f32,
373 pub memory_mb: u64,
375 pub gpu_devices: u32,
377}
378
379#[derive(Debug, Clone, Serialize, Deserialize)]
381pub struct DistributedTask {
382 pub id: UUID,
384 pub task_type: String,
386 pub payload: serde_json::Value,
388 pub requirements: NodeResources,
390 pub priority: i32,
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct DistributedTaskResult {
397 pub task_id: UUID,
399 pub executed_by: String,
401 pub success: bool,
403 pub result: Option<serde_json::Value>,
405 pub error: Option<String>,
407 pub duration_ms: u64,
409}
410
411#[async_trait]
416pub trait DistributedExecutor: Send + Sync {
417 fn name(&self) -> &str;
419
420 fn is_distributed(&self) -> bool {
422 false
423 }
424
425 async fn get_nodes(&self) -> Result<Vec<NodeInfo>> {
427 Ok(vec![])
428 }
429
430 async fn submit_task(&self, task: DistributedTask) -> Result<UUID>;
433
434 async fn get_task_result(&self, task_id: UUID) -> Result<Option<DistributedTaskResult>>;
436
437 async fn wait_for_task(
439 &self,
440 task_id: UUID,
441 timeout_ms: u64,
442 ) -> Result<Option<DistributedTaskResult>>;
443
444 async fn join_cluster(&self, _coordinator: &str) -> Result<bool> {
448 Ok(false)
449 }
450
451 async fn leave_cluster(&self) -> Result<bool> {
453 Ok(false)
454 }
455
456 async fn cluster_status(&self) -> Result<Option<ClusterStatus>> {
458 Ok(None)
459 }
460}
461
462#[derive(Debug, Clone, Serialize, Deserialize)]
464pub struct ClusterStatus {
465 pub name: String,
467 pub node_count: usize,
469 pub healthy_nodes: usize,
471 pub total_resources: NodeResources,
473 pub queued_tasks: usize,
475 pub running_tasks: usize,
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct PolicyRule {
486 pub id: String,
488 pub name: String,
490 pub rule_type: PolicyRuleType,
492 pub config: serde_json::Value,
494 pub enabled: bool,
496}
497
498#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
500pub enum PolicyRuleType {
501 RateLimit,
503 CostCap,
505 ContentFilter,
507 ToolPermission,
509 Custom,
511}
512
513#[derive(Debug, Clone, Serialize, Deserialize)]
515pub struct PolicyDecision {
516 pub allowed: bool,
518 pub reason: String,
520 pub matched_rules: Vec<String>,
522}
523
524#[async_trait]
529pub trait PolicyProvider: Send + Sync {
530 fn name(&self) -> &str;
532
533 fn is_enabled(&self) -> bool {
535 false
536 }
537
538 async fn check_policy(
540 &self,
541 _action: &str,
542 _context: &HashMap<String, serde_json::Value>,
543 ) -> Result<PolicyDecision> {
544 Ok(PolicyDecision {
545 allowed: true,
546 reason: "Policy engine not enabled".to_string(),
547 matched_rules: vec![],
548 })
549 }
550
551 async fn get_rules(&self) -> Result<Vec<PolicyRule>> {
553 Ok(vec![])
554 }
555
556 async fn set_rule(&self, _rule: PolicyRule) -> Result<bool> {
558 Ok(false)
559 }
560
561 async fn delete_rule(&self, _rule_id: &str) -> Result<bool> {
563 Ok(false)
564 }
565}
566
567#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct Identity {
574 pub id: UUID,
576 pub handle: String,
578 pub consents: Vec<ConsentScope>,
580 pub retention_days: i32,
582 pub created_at: i64,
584}
585
586#[derive(Debug, Clone, Serialize, Deserialize)]
588pub struct ConsentScope {
589 pub scope: String,
591 pub granted: bool,
593 pub granted_at: Option<i64>,
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize)]
599pub struct DataExportRequest {
600 pub id: UUID,
602 pub identity_id: UUID,
604 pub format: String,
606 pub status: DataRequestStatus,
608 pub download_url: Option<String>,
610}
611
612#[derive(Debug, Clone, Serialize, Deserialize)]
614pub struct DataDeletionRequest {
615 pub id: UUID,
617 pub identity_id: UUID,
619 pub status: DataRequestStatus,
621 pub completed_at: Option<i64>,
623}
624
625#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
627pub enum DataRequestStatus {
628 Pending,
630 InProgress,
632 Completed,
634 Failed,
636}
637
638#[async_trait]
643pub trait IdentityProvider: Send + Sync {
644 fn name(&self) -> &str;
646
647 fn is_enabled(&self) -> bool {
649 false
650 }
651
652 async fn get_identity(&self, _id: UUID) -> Result<Option<Identity>> {
654 Ok(None)
655 }
656
657 async fn update_consent(
659 &self,
660 _identity_id: UUID,
661 _scope: &str,
662 _granted: bool,
663 ) -> Result<bool> {
664 Ok(false)
665 }
666
667 async fn request_export(&self, _identity_id: UUID, _format: &str) -> Result<Option<UUID>> {
669 Ok(None)
670 }
671
672 async fn request_deletion(&self, _identity_id: UUID) -> Result<Option<UUID>> {
674 Ok(None)
675 }
676
677 async fn set_retention(&self, _identity_id: UUID, _days: i32) -> Result<bool> {
679 Ok(false)
680 }
681}
682
683pub struct BasicLearningProvider {
689 feedback: std::sync::RwLock<Vec<LearningFeedback>>,
690}
691
692impl BasicLearningProvider {
693 pub fn new() -> Self {
695 Self {
696 feedback: std::sync::RwLock::new(Vec::new()),
697 }
698 }
699}
700
701impl Default for BasicLearningProvider {
702 fn default() -> Self {
703 Self::new()
704 }
705}
706
707#[async_trait]
708impl LearningProvider for BasicLearningProvider {
709 fn name(&self) -> &str {
710 "basic-learning"
711 }
712
713 async fn collect_feedback(&self, feedback: LearningFeedback) -> Result<()> {
714 let mut store = self.feedback.write().unwrap();
715 store.push(feedback);
716 if store.len() > 1000 {
718 store.remove(0);
719 }
720 Ok(())
721 }
722
723 async fn get_feedback(&self, limit: usize) -> Result<Vec<LearningFeedback>> {
724 let store = self.feedback.read().unwrap();
725 Ok(store.iter().rev().take(limit).cloned().collect())
726 }
727}
728
729pub struct BasicComplianceProvider {
731 patterns: Vec<(PiiType, regex::Regex)>,
732}
733
734impl BasicComplianceProvider {
735 pub fn new() -> Self {
737 let patterns = vec![
738 (
739 PiiType::Ssn,
740 regex::Regex::new(r"\b\d{3}[-\s]?\d{2}[-\s]?\d{4}\b").unwrap(),
741 ),
742 (
743 PiiType::Email,
744 regex::Regex::new(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b").unwrap(),
745 ),
746 (
747 PiiType::Phone,
748 regex::Regex::new(r"\b(\+?1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b")
749 .unwrap(),
750 ),
751 (
752 PiiType::CreditCard,
753 regex::Regex::new(r"\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b").unwrap(),
754 ),
755 (
756 PiiType::ApiKey,
757 regex::Regex::new(r"\b(sk-[a-zA-Z0-9]{32,}|api[_-]?key[_-]?[a-zA-Z0-9]{16,})\b")
758 .unwrap(),
759 ),
760 ];
761 Self { patterns }
762 }
763}
764
765impl Default for BasicComplianceProvider {
766 fn default() -> Self {
767 Self::new()
768 }
769}
770
771#[async_trait]
772impl ComplianceProvider for BasicComplianceProvider {
773 fn name(&self) -> &str {
774 "basic-compliance"
775 }
776
777 async fn scan_pii(&self, text: &str) -> Result<Vec<PiiFinding>> {
778 let mut findings = Vec::new();
779
780 for (pii_type, pattern) in &self.patterns {
781 for m in pattern.find_iter(text) {
782 findings.push(PiiFinding {
783 pii_type: pii_type.clone(),
784 start: m.start(),
785 end: m.end(),
786 matched_text: m.as_str().to_string(),
787 severity: match pii_type {
788 PiiType::Ssn | PiiType::CreditCard | PiiType::ApiKey => Severity::Critical,
789 PiiType::Email | PiiType::Phone => Severity::Medium,
790 _ => Severity::Low,
791 },
792 confidence: 0.9,
793 });
794 }
795 }
796
797 Ok(findings)
798 }
799
800 fn redact(&self, text: &str) -> String {
801 let mut result = text.to_string();
802
803 for (pii_type, pattern) in &self.patterns {
804 let replacement = match pii_type {
805 PiiType::Ssn => "[SSN]",
806 PiiType::Email => "[EMAIL]",
807 PiiType::Phone => "[PHONE]",
808 PiiType::CreditCard => "[CREDIT_CARD]",
809 PiiType::ApiKey => "[API_KEY]",
810 _ => "[REDACTED]",
811 };
812 result = pattern.replace_all(&result, replacement).to_string();
813 }
814
815 result
816 }
817}
818
819pub struct ExtensionRegistry {
825 pub learning: Option<Arc<dyn LearningProvider>>,
827 pub compliance: Option<Arc<dyn ComplianceProvider>>,
829 pub distributed: Option<Arc<dyn DistributedExecutor>>,
831 pub policy: Option<Arc<dyn PolicyProvider>>,
833 pub identity: Option<Arc<dyn IdentityProvider>>,
835}
836
837impl ExtensionRegistry {
838 pub fn new() -> Self {
840 Self {
841 learning: Some(Arc::new(BasicLearningProvider::new())),
842 compliance: Some(Arc::new(BasicComplianceProvider::new())),
843 distributed: None,
844 policy: None,
845 identity: None,
846 }
847 }
848
849 pub fn empty() -> Self {
851 Self {
852 learning: None,
853 compliance: None,
854 distributed: None,
855 policy: None,
856 identity: None,
857 }
858 }
859
860 pub fn with_learning(mut self, provider: Arc<dyn LearningProvider>) -> Self {
862 self.learning = Some(provider);
863 self
864 }
865
866 pub fn with_compliance(mut self, provider: Arc<dyn ComplianceProvider>) -> Self {
868 self.compliance = Some(provider);
869 self
870 }
871
872 pub fn with_distributed(mut self, executor: Arc<dyn DistributedExecutor>) -> Self {
874 self.distributed = Some(executor);
875 self
876 }
877
878 pub fn with_policy(mut self, provider: Arc<dyn PolicyProvider>) -> Self {
880 self.policy = Some(provider);
881 self
882 }
883
884 pub fn with_identity(mut self, provider: Arc<dyn IdentityProvider>) -> Self {
886 self.identity = Some(provider);
887 self
888 }
889
890 pub fn has_enterprise_features(&self) -> bool {
892 self.learning
893 .as_ref()
894 .map(|l| l.supports_training())
895 .unwrap_or(false)
896 || self
897 .compliance
898 .as_ref()
899 .map(|c| c.supports_framework(ComplianceFramework::Hipaa))
900 .unwrap_or(false)
901 || self
902 .distributed
903 .as_ref()
904 .map(|d| d.is_distributed())
905 .unwrap_or(false)
906 || self.policy.as_ref().map(|p| p.is_enabled()).unwrap_or(false)
907 || self
908 .identity
909 .as_ref()
910 .map(|i| i.is_enabled())
911 .unwrap_or(false)
912 }
913}
914
915impl Default for ExtensionRegistry {
916 fn default() -> Self {
917 Self::new()
918 }
919}
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924
925 #[tokio::test]
926 async fn test_basic_learning_provider() {
927 let provider = BasicLearningProvider::new();
928
929 let feedback = LearningFeedback {
930 response_id: uuid::Uuid::new_v4(),
931 score: 0.8,
932 text: Some("Good response".to_string()),
933 source: FeedbackSource::User,
934 timestamp: chrono::Utc::now().timestamp(),
935 };
936
937 provider.collect_feedback(feedback.clone()).await.unwrap();
938
939 let collected = provider.get_feedback(10).await.unwrap();
940 assert_eq!(collected.len(), 1);
941 assert_eq!(collected[0].score, 0.8);
942 }
943
944 #[tokio::test]
945 async fn test_basic_compliance_provider() {
946 let provider = BasicComplianceProvider::new();
947
948 let text = "My SSN is 123-45-6789 and email is test@example.com";
950 let findings = provider.scan_pii(text).await.unwrap();
951
952 assert!(findings.iter().any(|f| f.pii_type == PiiType::Ssn));
953 assert!(findings.iter().any(|f| f.pii_type == PiiType::Email));
954
955 let redacted = provider.redact(text);
957 assert!(redacted.contains("[SSN]"));
958 assert!(redacted.contains("[EMAIL]"));
959 assert!(!redacted.contains("123-45-6789"));
960 }
961
962 #[tokio::test]
963 async fn test_training_not_available_in_consumer() {
964 let provider = BasicLearningProvider::new();
965
966 assert!(!provider.supports_training());
967
968 let result = provider.train().await.unwrap();
969 assert!(!result.success);
970 assert!(result.error.is_some());
971 }
972
973 #[test]
974 fn test_extension_registry() {
975 let registry = ExtensionRegistry::new();
976
977 assert!(registry.learning.is_some());
978 assert!(registry.compliance.is_some());
979 assert!(!registry.has_enterprise_features());
980 }
981}
982