Skip to main content

Mountain/IPC/
TauriIPCServer.rs

1//! # TauriIPCServer - Mountain-Wind IPC Bridge
2//!
3//! **File Responsibilities:**
4//! This module serves as the core IPC (Inter-Process Communication) server for
5//! Mountain, establishing and managing the bidirectional communication bridge
6//! between Mountain's Rust backend and Wind's TypeScript frontend. It
7//! implements the Mountain counterpart to Wind's TauriIPCServer.ts, ensuring
8//! seamless integration across the language boundary.
9//!
10//! **Architectural Role in Wind-Mountain Connection:**
11//! The TauriIPCServer acts as the central Message router and communication
12//! orchestrator:
13//!
14//! 1. **Connection Management:**
15//!    - Establishes secure connections between Wind and Mountain
16//!    - Maintains connection health and auto-reconnects on failure
17//!    - Manages connection pooling for optimal resource usage
18//!    - Tracks connection state for monitoring and debugging
19//!
20//! 2. **Message Routing:**
21//!    - Routes incoming messages from Wind to appropriate handlers
22//!    - Broadcasts messages from Mountain to Wind subscribers
23//!    - Implements Message filtering and prioritization
24//!    - Supports point-to-point and publish-subscribe patterns
25//!
26//! 3. **Security Layer:**
27//!    - Validates all incoming messages for security
28//!    - Implements permission-based access control (RBAC)
29//!    - Provides AES-256-GCM encryption for sensitive data
30//!    - Logs all security events for audit trails
31//!
32//! 4. **Reliability Features:**
33//!    - Message queuing for offline scenarios
34//!    - Automatic retry with exponential backoff
35//!    - Graceful degradation when services unavailable
36//!    - Circuit breaker pattern for cascading failure prevention
37//!
38//! **Communication Patterns:**
39//!
40//! **1. Request-Response Pattern:**
41//! ```text
42//! // Wind sends request
43//! let result = app_handle.invoke_handler("command", args).await?;
44//!
45//! // Mountain processes and responds
46//! let response = handle_request().await;
47//! ipc.emit(response_channel, response).await;
48//! ```
49//!
50//! **2. Event Emission Pattern:**
51//! ```text
52//! // Mountain emits events to Wind subscribers
53//! app.emit("configuration-updated", new_config).await;
54//! app.emit("file-changed", file_event).await;
55//! ```
56//!
57//! **3. Broadcast Pattern:**
58//! ```rust
59//! // Broadcast to all subscribers on a channel
60//! for listener in listeners.get(channel) {
61//! 	listener(Message.clone()).await;
62//! }
63//! ```
64//!
65//! **Message Flow:**
66//! ```text
67//! Wind Frontend
68//! |
69//! | 4. Response
70//! v
71//! Tauri Bridge (JS Bridge)
72//! |
73//! | 1. IPC Invoke
74//! v
75//! TauriIPCServer (Rust)
76//! |
77//! | 2. Route & Validate
78//! v
79//! WindServiceHandlers
80//! |
81//! | 3. Execute
82//! v
83//! Mountain Services
84//! ```
85//!
86//! **Key Structures:**
87//!
88//! - **TauriIPCMessage:** Standard Message format for all IPC communication
89//! - **ConnectionStatus:** Tracks connection health and uptime
90//! - **ConnectionPool:** Manages concurrent IPC connections efficiently
91//! - **PermissionManager:** Implements role-based access control
92//! - **SecureMessageChannel:** Provides encryption for sensitive data
93//! - **MessageCompressor:** Gzip compression for large payloads
94//!
95//! **Defensive Coding Practices:**
96//!
97//! 1. **Input Validation:**
98//!    - All messages validated before processing
99//!    - Type checking for all serialized data
100//!    - Schema validation for complex payloads
101//!
102//! 2. **Error Handling:**
103//!    - Comprehensive error messages with context
104//!    - Error logging at appropriate levels
105//!    - Graceful handling of transient failures
106//!    - Automatic retry with backoff
107//!
108//! 3. **Timeout Management:**
109//!    - Configurable timeouts for all operations
110//!    - Timeout-based circuit breaking
111//!    - Graceful degradation on timeout
112//!
113//! 4. **Resource Management:**
114//!    - Connection pooling to prevent exhaustion
115//!    - Automatic cleanup of stale resources
116//!    - Memory-efficient Message queuing
117//!
118//! **Security Architecture:**
119//!
120//! - **Authentication:** User identity verification
121//! - **Authorization:** Permission-based access control (RBAC)
122//! - **Encryption:** AES-256-GCM for sensitive data
123//! - **Auditing:** Complete security event logging
124//! - **Threat Detection:** Anomaly monitoring and alerts
125//!
126//! **Performance Optimizations:**
127//!
128//! - **Message Compression:** Gzip for large payloads
129//! - **Connection Pooling:** Reuse connections efficiently
130//! - **Caching:** Cache frequently used data
131//! - **Batching:** Batch multiple messages for efficiency
132//! - **Async/Await:** Non-blocking I/O operations
133//!
134//! **Monitoring & Observability:**
135//!
136//! - **Connection Status:** Real-time health monitoring
137//! - **Performance Metrics:** Latency, throughput, error rates
138//! - **Audit Logs:** Complete Message and security event logging
139//! - **Health Checks:** Periodic health assessments
140//!
141//! **VSCode RPC Patterns (Study Reference):**
142//! This implementation draws inspiration from VSCode's RPC/IPC architecture:
143//! - Channel-based Message routing
144//! - Request-response correlation
145//! - Cancellation token support
146//! - Binary protocol Message serialization
147//! - Protocol versioning for compatibility
148
149use std::{
150	collections::HashMap,
151	io::{Read, Write},
152	sync::{Arc, Mutex},
153	time::Duration,
154};
155
156use base64::{Engine, engine::general_purpose};
157use flate2::{Compression, read::GzDecoder, write::GzEncoder};
158use ring::{
159	aead::{self, AES_256_GCM, LessSafeKey, UnboundKey},
160	hmac,
161	rand::{SecureRandom, SystemRandom},
162};
163use serde::{Deserialize, Serialize};
164use tauri::{AppHandle, Emitter, Manager};
165use tokio::{
166	sync::{Mutex as AsyncMutex, RwLock, Semaphore},
167	time::timeout,
168};
169
170use crate::dev_log;
171
172/// IPC Message structure matching Wind's ITauriIPCMessage interface
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct TauriIPCMessage {
175	pub channel:String,
176
177	pub data:serde_json::Value,
178
179	pub sender:Option<String>,
180
181	pub timestamp:u64,
182}
183
184/// Connection status Message
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct ConnectionStatus {
187	pub connected:bool,
188}
189
190/// Listener callback type
191type ListenerCallback = Box<dyn Fn(serde_json::Value) -> Result<(), String> + Send + Sync>;
192
193/// Mountain's IPC Server counterpart to Wind's TauriIPCServer
194#[derive(Clone)]
195pub struct TauriIPCServer {
196	app_handle:AppHandle,
197
198	listeners:Arc<Mutex<HashMap<String, Vec<ListenerCallback>>>>,
199
200	is_connected:Arc<Mutex<bool>>,
201
202	message_queue:Arc<Mutex<Vec<TauriIPCMessage>>>,
203}
204
205/// Message compression utility for optimizing IPC Message transfer
206pub struct MessageCompressor {
207	CompressionLevel:u32,
208
209	BatchSize:usize,
210}
211
212impl MessageCompressor {
213	/// Create a new Message compressor with specified parameters
214	pub fn new(CompressionLevel:u32, BatchSize:usize) -> Self { Self { CompressionLevel, BatchSize } }
215
216	/// Compress messages using Gzip for efficient transfer
217	pub fn compress_messages(&self, Messages:Vec<TauriIPCMessage>) -> Result<Vec<u8>, String> {
218		let SerializedMessages =
219			serde_json::to_vec(&Messages).map_err(|e| format!("Failed to serialize messages: {}", e))?;
220
221		let mut encoder = GzEncoder::new(Vec::new(), Compression::new(self.CompressionLevel));
222
223		encoder
224			.write_all(&SerializedMessages)
225			.map_err(|e| format!("Failed to compress messages: {}", e))?;
226
227		encoder.finish().map_err(|e| format!("Failed to finish compression: {}", e))
228	}
229
230	/// Decompress messages from compressed data
231	pub fn decompress_messages(&self, CompressedData:&[u8]) -> Result<Vec<TauriIPCMessage>, String> {
232		let mut decoder = GzDecoder::new(CompressedData);
233
234		let mut DecompressedData = Vec::new();
235
236		decoder
237			.read_to_end(&mut DecompressedData)
238			.map_err(|e| format!("Failed to decompress data: {}", e))?;
239
240		serde_json::from_slice(&DecompressedData).map_err(|e| format!("Failed to deserialize messages: {}", e))
241	}
242
243	/// Check if messages should be batched for compression
244	pub fn should_batch(&self, MessagesCount:usize) -> bool { MessagesCount >= self.BatchSize }
245}
246
247impl TauriIPCServer {
248	/// Create a new Tauri IPC Server instance
249	pub fn new(app_handle:AppHandle) -> Self {
250		dev_log!("ipc", "[TauriIPCServer] Initializing Mountain IPC Server");
251
252		Self {
253			app_handle,
254
255			listeners:Arc::new(Mutex::new(HashMap::new())),
256
257			is_connected:Arc::new(Mutex::new(false)),
258
259			message_queue:Arc::new(Mutex::new(Vec::new())),
260		}
261	}
262
263	/// Initialize the IPC server and set up event listeners
264	pub async fn initialize(&self) -> Result<(), String> {
265		dev_log!("ipc", "[TauriIPCServer] Setting up IPC listeners");
266
267		// Set up connection status
268		{
269			let mut is_connected = self
270				.is_connected
271				.lock()
272				.map_err(|e| format!("Failed to lock connection status: {}", e))?;
273
274			*is_connected = true;
275		}
276
277		// Notify Wind that Mountain is ready
278		self.send_connection_status(true)
279			.await
280			.map_err(|e| format!("Failed to send connection status: {}", e))?;
281
282		dev_log!("ipc", "[TauriIPCServer] IPC Server initialized successfully");
283
284		// Process any queued messages
285		self.process_message_queue().await;
286
287		Ok(())
288	}
289
290	/// Send a Message to the Wind frontend
291	pub async fn send(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
292		let Message = TauriIPCMessage {
293			channel:channel.to_string(),
294
295			data,
296
297			sender:Some("mountain".to_string()),
298
299			timestamp:std::time::SystemTime::now()
300				.duration_since(std::time::UNIX_EPOCH)
301				.unwrap_or_default()
302				.as_millis() as u64,
303		};
304
305		let is_connected = {
306			let guard = self
307				.is_connected
308				.lock()
309				.map_err(|e| format!("Failed to check connection status: {}", e))?;
310
311			*guard
312		};
313
314		if !is_connected {
315			// Queue the Message for later delivery
316			let mut queue = self
317				.message_queue
318				.lock()
319				.map_err(|e| format!("Failed to access Message queue: {}", e))?;
320
321			queue.push(Message);
322
323			dev_log!(
324				"ipc",
325				"[TauriIPCServer] Message queued (channel: {}, queue size: {})",
326				channel,
327				queue.len()
328			);
329
330			return Ok(());
331		}
332
333		// Send immediately
334		self.emit_message(&Message).await
335	}
336
337	/// Register a listener for incoming messages from Wind
338	pub fn on(&self, channel:&str, callback:ListenerCallback) -> Result<(), String> {
339		let mut listeners = self
340			.listeners
341			.lock()
342			.map_err(|e| format!("Failed to access listeners: {}", e))?;
343
344		listeners.entry(channel.to_string()).or_insert_with(Vec::new).push(callback);
345
346		dev_log!("ipc", "[TauriIPCServer] Listener registered for channel: {}", channel);
347
348		Ok(())
349	}
350
351	/// Remove a listener
352	pub fn off(&self, channel:&str, callback:&ListenerCallback) -> Result<(), String> {
353		let mut listeners = self
354			.listeners
355			.lock()
356			.map_err(|e| format!("Failed to access listeners: {}", e))?;
357
358		if let Some(channel_listeners) = listeners.get_mut(channel) {
359			channel_listeners.retain(|cb| !std::ptr::eq(cb as *const _, callback as *const _));
360
361			if channel_listeners.is_empty() {
362				listeners.remove(channel);
363			}
364		}
365
366		dev_log!("ipc", "[TauriIPCServer] Listener removed from channel: {}", channel);
367
368		Ok(())
369	}
370
371	/// Handle incoming messages from Wind
372	pub async fn IncomingMessage(&self, Message:TauriIPCMessage) -> Result<(), String> {
373		dev_log!("ipc", "[TauriIPCServer] Received Message on channel: {}", Message.channel);
374
375		let listeners = self
376			.listeners
377			.lock()
378			.map_err(|e| format!("Failed to access listeners: {}", e))?;
379
380		if let Some(channel_listeners) = listeners.get(&Message.channel) {
381			for callback in channel_listeners {
382				if let Err(e) = callback(Message.data.clone()) {
383					dev_log!(
384						"ipc",
385						"error: [TauriIPCServer] Error in listener for channel {}: {}",
386						Message.channel,
387						e
388					);
389				}
390			}
391		} else {
392			dev_log!("ipc", "[TauriIPCServer] No listeners found for channel: {}", Message.channel);
393		}
394
395		Ok(())
396	}
397
398	/// Send connection status to Wind
399	async fn send_connection_status(&self, connected:bool) -> Result<(), String> {
400		let status = ConnectionStatus { connected };
401
402		self.app_handle
403			.emit("vscode-ipc-status", status)
404			.map_err(|e| format!("Failed to emit connection status: {}", e))?;
405
406		dev_log!("ipc", "[TauriIPCServer] Connection status sent: {}", connected);
407
408		Ok(())
409	}
410
411	/// Emit a Message to Wind
412	async fn emit_message(&self, Message:&TauriIPCMessage) -> Result<(), String> {
413		self.app_handle
414			.emit("vscode-ipc-Message", Message)
415			.map_err(|e| format!("Failed to emit Message: {}", e))?;
416
417		dev_log!("ipc", "[TauriIPCServer] Message emitted on channel: {}", Message.channel);
418
419		Ok(())
420	}
421
422	/// Process queued messages
423	async fn process_message_queue(&self) {
424		let mut queue = match self.message_queue.lock() {
425			Ok(queue) => queue,
426
427			Err(e) => {
428				dev_log!("ipc", "error: [TauriIPCServer] Failed to access Message queue: {}", e);
429
430				return;
431			},
432		};
433
434		while let Some(Message) = queue.pop() {
435			if let Err(e) = self.emit_message(&Message).await {
436				dev_log!("ipc", "error: [TauriIPCServer] Failed to send queued Message: {}", e);
437
438				// Put the Message back in the queue
439				queue.insert(0, Message);
440
441				break;
442			}
443		}
444
445		dev_log!(
446			"ipc",
447			"[TauriIPCServer] Message queue processed, {} messages remaining",
448			queue.len()
449		);
450	}
451
452	/// Get connection status
453	pub fn get_connection_status(&self) -> Result<bool, String> {
454		let guard = self
455			.is_connected
456			.lock()
457			.map_err(|e| format!("Failed to get connection status: {}", e))?;
458
459		Ok(*guard)
460	}
461
462	/// Get queued Message count
463	pub fn get_queue_size(&self) -> Result<usize, String> {
464		let guard = self
465			.message_queue
466			.lock()
467			.map_err(|e| format!("Failed to get queue size: {}", e))?;
468
469		Ok(guard.len())
470	}
471
472	/// Cleanup resources
473	pub fn dispose(&self) -> Result<(), String> {
474		{
475			let mut listeners = self
476				.listeners
477				.lock()
478				.map_err(|e| format!("Failed to access listeners: {}", e))?;
479
480			listeners.clear();
481		}
482
483		{
484			let mut queue = self
485				.message_queue
486				.lock()
487				.map_err(|e| format!("Failed to access Message queue: {}", e))?;
488
489			queue.clear();
490		}
491
492		{
493			let mut is_connected = self
494				.is_connected
495				.lock()
496				.map_err(|e| format!("Failed to access connection status: {}", e))?;
497
498			*is_connected = false;
499		}
500
501		dev_log!("ipc", "[TauriIPCServer] IPC Server disposed");
502
503		Ok(())
504	}
505
506	/// Advanced: Validate Message permissions
507	pub async fn validate_message_permissions(&self, Message:&TauriIPCMessage) -> Result<(), String> {
508		let permission_manager = PermissionManager::new();
509
510		permission_manager.initialize_defaults().await;
511
512		let context = self.create_security_context(Message);
513
514		// Extract operation from channel name
515		let operation = Message.channel.replace("mountain_", "");
516
517		// Validate permission
518		permission_manager.validate_permission(&operation, &context).await
519	}
520
521	/// Advanced: Create security context from Message
522	fn create_security_context(&self, Message:&TauriIPCMessage) -> SecurityContext {
523		SecurityContext {
524			user_id:Message.sender.clone().unwrap_or("unknown".to_string()),
525
526			// Default role assigned to authenticated IPC connections
527			roles:vec!["user".to_string()],
528
529			permissions:vec![],
530
531			// IPC connections use loopback address for security (localhost only)
532			ip_address:"127.0.0.1".to_string(),
533
534			timestamp:std::time::SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(Message.timestamp),
535		}
536	}
537
538	/// Advanced: Log security event
539	pub async fn log_security_event(&self, event:SecurityEvent) {
540		let permission_manager = PermissionManager::new();
541
542		permission_manager.log_security_event(event).await;
543	}
544
545	/// Advanced: Record performance metrics
546	pub async fn record_performance_metrics(&self, channel:String, duration:std::time::Duration, success:bool) {
547		// This would integrate with the PerformanceDashboard
548		dev_log!(
549			"ipc",
550			"[TauriIPCServer] Performance recorded - Channel: {}, Duration: {:?}, Success: {}",
551			channel,
552			duration,
553			success
554		);
555	}
556
557	/// Advanced: Get security audit log
558	pub async fn get_security_audit_log(&self, limit:usize) -> Result<Vec<SecurityEvent>, String> {
559		let permission_manager = PermissionManager::new();
560
561		Ok(permission_manager.get_audit_log(limit).await)
562	}
563
564	/// Send compressed Message batch
565	pub async fn send_compressed_batch(&self, channel:&str, messages:Vec<TauriIPCMessage>) -> Result<(), String> {
566		// Configure compressor with balanced settings: level 6 (good compression/speed
567		// tradeoff) and batch size 10 (aggregate small messages for efficiency)
568		let compressor = MessageCompressor::new(6, 10);
569
570		let compressed_data = compressor
571			.compress_messages(messages)
572			.map_err(|e| format!("Failed to compress batch: {}", e))?;
573
574		let batch_message = TauriIPCMessage {
575			channel:"compressed_batch".to_string(),
576
577			data:serde_json::Value::String(general_purpose::STANDARD.encode(&compressed_data)),
578
579			sender:Some("mountain".to_string()),
580
581			timestamp:std::time::SystemTime::now()
582				.duration_since(std::time::UNIX_EPOCH)
583				.unwrap_or_default()
584				.as_millis() as u64,
585		};
586
587		self.send(channel, serde_json::to_value(batch_message).unwrap()).await
588	}
589
590	/// Handle compressed batch Message
591	pub async fn CompressedBatch(&self, Message:TauriIPCMessage) -> Result<(), String> {
592		let compressed_data_base64 = Message.data.as_str().ok_or("Compressed batch data must be a string")?;
593
594		let compressed_data = general_purpose::STANDARD
595			.decode(compressed_data_base64)
596			.map_err(|e| format!("Failed to decode base64: {}", e))?;
597
598		let compressor = MessageCompressor::new(6, 10);
599
600		let messages = compressor
601			.decompress_messages(&compressed_data)
602			.map_err(|e| format!("Failed to decompress batch: {}", e))?;
603
604		// Process each Message in the batch
605		for Message in messages {
606			self.IncomingMessage(Message).await?;
607		}
608
609		Ok(())
610	}
611
612	/// Send Message using connection pool
613	pub async fn send_with_pool(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
614		let pool = Arc::new(ConnectionPool::new(10, Duration::from_secs(30)));
615
616		let Handle = pool
617			.GetConnection()
618			.await
619			.map_err(|e| format!("Failed to get connection: {}", e))?;
620
621		let result = self.send(channel, data).await;
622
623		pool.ReleaseConnection(Handle).await;
624
625		result
626	}
627
628	/// Get connection pool statistics
629	pub async fn get_connection_stats(&self) -> Result<ConnectionStats, String> {
630		let pool = Arc::new(ConnectionPool::new(10, Duration::from_secs(30)));
631
632		Ok(pool.GetStats().await)
633	}
634
635	/// Send encrypted Message
636	pub async fn send_secure(&self, channel:&str, data:serde_json::Value) -> Result<(), String> {
637		let secure_channel =
638			SecureMessageChannel::new().map_err(|e| format!("Failed to create secure channel: {}", e))?;
639
640		let Message = TauriIPCMessage {
641			channel:channel.to_string(),
642
643			data,
644
645			sender:Some("mountain".to_string()),
646
647			timestamp:std::time::SystemTime::now()
648				.duration_since(std::time::UNIX_EPOCH)
649				.unwrap_or_default()
650				.as_millis() as u64,
651		};
652
653		let encrypted_message = secure_channel
654			.encrypt_message(&Message)
655			.map_err(|e| format!("Failed to encrypt Message: {}", e))?;
656
657		let encrypted_data = serde_json::to_value(encrypted_message)
658			.map_err(|e| format!("Failed to serialize encrypted Message: {}", e))?;
659
660		self.send("secure_message", encrypted_data).await
661	}
662
663	/// Handle encrypted Message
664	pub async fn SecureMessage(&self, encrypted_data:serde_json::Value) -> Result<(), String> {
665		let encrypted_message:EncryptedMessage = serde_json::from_value(encrypted_data)
666			.map_err(|e| format!("Failed to deserialize encrypted Message: {}", e))?;
667
668		let secure_channel =
669			SecureMessageChannel::new().map_err(|e| format!("Failed to create secure channel: {}", e))?;
670
671		let Message = secure_channel
672			.decrypt_message(&encrypted_message)
673			.map_err(|e| format!("Failed to decrypt Message: {}", e))?;
674
675		self.IncomingMessage(Message).await
676	}
677
678	/// Handle Message with permission validation
679	pub async fn MessageWithPermissions(&self, Message:TauriIPCMessage) -> Result<(), String> {
680		let permission_manager = PermissionManager::new();
681
682		let context = self.create_security_context(&Message);
683
684		// Extract operation from channel name
685		let operation = Message.channel.replace("mountain_", "");
686
687		// Validate permission
688		permission_manager.validate_permission(&operation, &context).await?;
689
690		// Process the Message
691		self.IncomingMessage(Message).await
692	}
693}
694
695/// Connection pool for IPC operations - manages concurrent connections
696/// efficiently
697///
698/// **Purpose:** Prevents connection exhaustion by pooling connections and
699/// reusing them **Features:** Health monitoring, automatic cleanup,
700/// configurable timeouts
701pub struct ConnectionPool {
702	MaxConnections:usize,
703
704	ConnectionTimeout:Duration,
705
706	Semaphore:Arc<Semaphore>,
707
708	ActiveConnection:Arc<AsyncMutex<HashMap<String, ConnectionHandle>>>,
709
710	HealthChecker:Arc<AsyncMutex<ConnectionHealthChecker>>,
711}
712
713/// Handle representing an active connection
714#[derive(Clone)]
715pub struct ConnectionHandle {
716	pub id:String,
717
718	pub created_at:std::time::Instant,
719
720	pub last_used:std::time::Instant,
721
722	pub health_score:f64,
723
724	pub error_count:usize,
725}
726
727impl ConnectionHandle {
728	/// Create a new connection Handle with health monitoring
729	pub fn new() -> Self {
730		Self {
731			id:uuid::Uuid::new_v4().to_string(),
732
733			created_at:std::time::Instant::now(),
734
735			last_used:std::time::Instant::now(),
736
737			health_score:100.0,
738
739			error_count:0,
740		}
741	}
742
743	/// Update health score based on operation success
744	pub fn update_health(&mut self, success:bool) {
745		if success {
746			self.health_score = (self.health_score + 10.0).min(100.0);
747
748			self.error_count = 0;
749		} else {
750			self.health_score = (self.health_score - 25.0).max(0.0);
751
752			self.error_count += 1;
753		}
754
755		self.last_used = std::time::Instant::now();
756	}
757
758	/// Check if connection is healthy
759	pub fn is_healthy(&self) -> bool { self.health_score > 50.0 && self.error_count < 5 }
760
761	/// Check if connection is alive (non-degraded, not expired).
762	pub fn is_alive(&self) -> bool { self.health_score > 0.0 && self.error_count < 10 }
763}
764
765impl ConnectionPool {
766	/// Create a new connection pool with specified parameters
767	pub fn new(MaxConnections:usize, ConnectionTimeout:Duration) -> Self {
768		Self {
769			MaxConnections,
770
771			ConnectionTimeout,
772
773			Semaphore:Arc::new(Semaphore::new(MaxConnections)),
774
775			ActiveConnection:Arc::new(AsyncMutex::new(HashMap::new())),
776
777			HealthChecker:Arc::new(AsyncMutex::new(ConnectionHealthChecker::new())),
778		}
779	}
780
781	/// Get a connection Handle from the pool with timeout
782	pub async fn GetConnection(&self) -> Result<ConnectionHandle, String> {
783		let _permit = timeout(self.ConnectionTimeout, self.Semaphore.acquire())
784			.await
785			.map_err(|_| "Connection timeout")?
786			.map_err(|e| format!("Failed to acquire connection: {}", e))?;
787
788		let Handle = ConnectionHandle::new();
789
790		{
791			let mut connections = self.ActiveConnection.lock().await;
792
793			connections.insert(Handle.id.clone(), Handle.clone());
794		}
795
796		// Start health monitoring for this connection
797		self.StartHealthMonitoring(&Handle.id).await;
798
799		Ok(Handle)
800	}
801
802	/// Release a connection Handle back to the pool
803	pub async fn ReleaseConnection(&self, Handle:ConnectionHandle) {
804		{
805			let mut connections = self.ActiveConnection.lock().await;
806
807			connections.remove(&Handle.id);
808		}
809
810		// The permit is released when dropped
811	}
812
813	/// Get connection statistics for monitoring
814	pub async fn GetStats(&self) -> ConnectionStats {
815		let connections = self.ActiveConnection.lock().await;
816
817		let healthy_connections = connections.values().filter(|h| h.is_healthy()).count();
818
819		ConnectionStats {
820			total_connections:connections.len(),
821
822			healthy_connections,
823
824			max_connections:self.MaxConnections,
825
826			available_permits:self.Semaphore.available_permits(),
827
828			connection_timeout:self.ConnectionTimeout,
829		}
830	}
831
832	/// Clean up stale connections
833	pub async fn CleanUpStaleConnections(&self) -> usize {
834		let mut connections = self.ActiveConnection.lock().await;
835
836		let now = std::time::Instant::now();
837
838		// Stale connections are those unused for 5 minutes (300 seconds)
839		let stale_threshold = Duration::from_secs(300);
840
841		let stale_ids:Vec<String> = connections
842			.iter()
843			.filter(|(_, Handle)| now.duration_since(Handle.last_used) > stale_threshold || !Handle.is_healthy())
844			.map(|(id, _)| id.clone())
845			.collect();
846
847		let stale_count = stale_ids.len();
848
849		for id in stale_ids {
850			connections.remove(&id);
851		}
852
853		stale_count
854	}
855
856	/// Start health monitoring for a connection
857	async fn StartHealthMonitoring(&self, connection_id:&str) {
858		let health_checker = self.HealthChecker.clone();
859
860		let active_connection = self.ActiveConnection.clone();
861
862		let connection_id = connection_id.to_string();
863
864		tokio::spawn(async move {
865			let mut interval = tokio::time::interval(Duration::from_secs(30));
866
867			loop {
868				interval.tick().await;
869
870				let checker = health_checker.lock().await;
871				let mut connections = match active_connection.try_lock() {
872					Ok(conns) => conns,
873					Err(_) => continue,
874				};
875
876				if let Some(Handle) = connections.get_mut(&connection_id) {
877					let is_healthy = checker.check_connection_health(Handle).await;
878					Handle.update_health(is_healthy);
879
880					if !Handle.is_healthy() {
881						dev_log!(
882							"ipc",
883							"Connection {} marked as unhealthy (score: {:.1})",
884							Handle.id,
885							Handle.health_score
886						);
887					}
888				} else {
889					// The connection has been removed from the pool, stop monitoring
890					break;
891				}
892			}
893		});
894	}
895}
896
897/// Connection health checker
898struct ConnectionHealthChecker {}
899
900impl ConnectionHealthChecker {
901	fn new() -> Self { Self {} }
902
903	/// Check connection health - returns true if the connection handle has a
904	/// live channel. No artificial sleep; this is called from an idle
905	/// background task so latency doesn't matter.
906	async fn check_connection_health(&self, Handle:&mut ConnectionHandle) -> bool { Handle.is_alive() }
907}
908
909/// Connection statistics
910#[derive(Debug, Clone, Default)]
911pub struct ConnectionStats {
912	pub total_connections:usize,
913
914	pub healthy_connections:usize,
915
916	pub max_connections:usize,
917
918	pub available_permits:usize,
919
920	pub connection_timeout:Duration,
921}
922
923/// Secure Message channel with encryption and authentication
924pub struct SecureMessageChannel {
925	encryption_key:LessSafeKey,
926
927	hmac_key:Vec<u8>,
928}
929
930impl SecureMessageChannel {
931	/// Create a new secure channel
932	pub fn new() -> Result<Self, String> {
933		let rng = SystemRandom::new();
934
935		// Generate encryption key
936		let mut encryption_key_bytes = vec![0u8; 32];
937
938		rng.fill(&mut encryption_key_bytes)
939			.map_err(|e| format!("Failed to generate encryption key: {}", e))?;
940
941		let unbound_key = UnboundKey::new(&AES_256_GCM, &encryption_key_bytes)
942			.map_err(|e| format!("Failed to create unbound key: {}", e))?;
943
944		let encryption_key = LessSafeKey::new(unbound_key);
945
946		// Generate HMAC key
947		let mut hmac_key = vec![0u8; 32];
948
949		rng.fill(&mut hmac_key)
950			.map_err(|e| format!("Failed to generate HMAC key: {}", e))?;
951
952		Ok(Self { encryption_key, hmac_key })
953	}
954
955	/// Encrypt and authenticate a Message
956	pub fn encrypt_message(&self, Message:&TauriIPCMessage) -> Result<EncryptedMessage, String> {
957		let serialized_message =
958			serde_json::to_vec(Message).map_err(|e| format!("Failed to serialize Message: {}", e))?;
959
960		// Generate nonce
961		let mut nonce = [0u8; 12];
962
963		SystemRandom::new()
964			.fill(&mut nonce)
965			.map_err(|e| format!("Failed to generate nonce: {}", e))?;
966
967		// Encrypt Message
968		let mut in_out = serialized_message.clone();
969
970		self.encryption_key
971			.seal_in_place_append_tag(aead::Nonce::assume_unique_for_key(nonce), aead::Aad::empty(), &mut in_out)
972			.map_err(|e| format!("Encryption failed: {}", e))?;
973
974		// Create HMAC
975		let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
976
977		let hmac_tag = hmac::sign(&hmac_key, &in_out);
978
979		Ok(EncryptedMessage { nonce:nonce.to_vec(), ciphertext:in_out, hmac_tag:hmac_tag.as_ref().to_vec() })
980	}
981
982	/// Decrypt and verify a Message
983	pub fn decrypt_message(&self, encrypted:&EncryptedMessage) -> Result<TauriIPCMessage, String> {
984		// Verify HMAC
985		let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
986
987		hmac::verify(&hmac_key, &encrypted.ciphertext, &encrypted.hmac_tag)
988			.map_err(|_| "HMAC verification failed".to_string())?;
989
990		// Decrypt Message
991		let mut in_out = encrypted.ciphertext.clone();
992
993		let nonce_slice:&[u8] = &encrypted.nonce;
994
995		let nonce_array:[u8; 12] = nonce_slice.try_into().map_err(|_| "Invalid nonce length".to_string())?;
996
997		let nonce = aead::Nonce::assume_unique_for_key(nonce_array);
998
999		self.encryption_key
1000			.open_in_place(nonce, aead::Aad::empty(), &mut in_out)
1001			.map_err(|e| format!("Decryption failed: {}", e))?;
1002
1003		// Remove authentication tag
1004		let plaintext_len = in_out.len() - AES_256_GCM.tag_len();
1005
1006		in_out.truncate(plaintext_len);
1007
1008		// Deserialize Message
1009		serde_json::from_slice(&in_out).map_err(|e| format!("Failed to deserialize Message: {}", e))
1010	}
1011
1012	/// Rotate encryption keys
1013	pub fn rotate_keys(&mut self) -> Result<(), String> {
1014		*self = Self::new()?;
1015		Ok(())
1016	}
1017}
1018
1019/// Encrypted Message structure
1020#[derive(Debug, Clone, Serialize, Deserialize)]
1021pub struct EncryptedMessage {
1022	nonce:Vec<u8>,
1023
1024	ciphertext:Vec<u8>,
1025
1026	hmac_tag:Vec<u8>,
1027}
1028
1029/// Advanced permission-based IPC Message handler
1030#[tauri::command]
1031pub async fn mountain_ipc_receive_message(app_handle:tauri::AppHandle, Message:TauriIPCMessage) -> Result<(), String> {
1032	dev_log!(
1033		"ipc",
1034		"[TauriIPCServer] Received IPC Message from Wind on channel: {}",
1035		Message.channel
1036	);
1037
1038	// Get the IPC server instance from application state
1039	if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1040		// Advanced security: Validate permissions before processing
1041		if let Err(e) = ipc_server.validate_message_permissions(&Message).await {
1042			dev_log!(
1043				"ipc",
1044				"error: [TauriIPCServer] Permission validation failed for channel {}: {}",
1045				Message.channel,
1046				e
1047			);
1048
1049			// Log security event
1050			ipc_server
1051				.log_security_event(SecurityEvent {
1052					event_type:SecurityEventType::PermissionDenied,
1053					user_id:Message.sender.clone().unwrap_or("unknown".to_string()),
1054					operation:Message.channel.clone(),
1055					timestamp:std::time::SystemTime::now(),
1056					details:Some(format!("Permission denied: {}", e)),
1057				})
1058				.await;
1059
1060			return Err(format!("Permission denied: {}", e));
1061		}
1062
1063		// Advanced monitoring: Track Message processing time
1064		let start_time = std::time::Instant::now();
1065
1066		let result = ipc_server.IncomingMessage(Message.clone()).await;
1067
1068		let duration = start_time.elapsed();
1069
1070		// Record performance metrics
1071		ipc_server
1072			.record_performance_metrics(Message.channel, duration, result.is_ok())
1073			.await;
1074
1075		result
1076	} else {
1077		Err("IPC Server not found in application state".to_string())
1078	}
1079}
1080
1081/// Tauri command handler for Wind to check connection status
1082///
1083/// **Command Registration:** Registered in Tauri's invoke_handler
1084/// Called by Wind using: `app.Handle.invoke('mountain_ipc_get_status')`
1085///
1086/// **Response Format:**
1087/// ```json
1088/// {
1089///   "connected": true
1090/// }
1091/// ```
1092#[tauri::command]
1093pub async fn mountain_ipc_get_status(app_handle:tauri::AppHandle) -> Result<ConnectionStatus, String> {
1094	if let Some(ipc_server) = app_handle.try_state::<TauriIPCServer>() {
1095		let connected = ipc_server
1096			.get_connection_status()
1097			.map_err(|e| format!("Failed to get connection status: {}", e))?;
1098
1099		Ok(ConnectionStatus { connected })
1100	} else {
1101		Err("IPC Server not found in application state".to_string())
1102	}
1103}
1104
1105/// Security context for permission validation
1106#[derive(Debug, Clone, Serialize, Deserialize)]
1107pub struct SecurityContext {
1108	pub user_id:String,
1109
1110	pub roles:Vec<String>,
1111
1112	pub permissions:Vec<String>,
1113
1114	pub ip_address:String,
1115
1116	pub timestamp:std::time::SystemTime,
1117}
1118
1119/// Permission manager for IPC operations
1120pub struct PermissionManager {
1121	roles:Arc<RwLock<HashMap<String, Role>>>,
1122
1123	permissions:Arc<RwLock<HashMap<String, Permission>>>,
1124
1125	audit_log:Arc<RwLock<Vec<SecurityEvent>>>,
1126}
1127
1128/// Security event for auditing
1129#[derive(Debug, Clone, Serialize, Deserialize)]
1130pub struct SecurityEvent {
1131	pub event_type:SecurityEventType,
1132
1133	pub user_id:String,
1134
1135	pub operation:String,
1136
1137	pub timestamp:std::time::SystemTime,
1138
1139	pub details:Option<String>,
1140}
1141
1142#[derive(Debug, Clone, Serialize, Deserialize)]
1143pub enum SecurityEventType {
1144	PermissionDenied,
1145
1146	AccessGranted,
1147
1148	ConfigurationChange,
1149
1150	SecurityViolation,
1151
1152	PerformanceAnomaly,
1153}
1154
1155/// Role definition for RBAC
1156#[derive(Debug, Clone, Serialize, Deserialize)]
1157pub struct Role {
1158	pub name:String,
1159
1160	pub permissions:Vec<String>,
1161
1162	pub description:String,
1163}
1164
1165/// Permission definition
1166#[derive(Debug, Clone, Serialize, Deserialize)]
1167pub struct Permission {
1168	pub name:String,
1169
1170	pub description:String,
1171
1172	pub category:String,
1173}
1174
1175impl PermissionManager {
1176	pub fn new() -> Self {
1177		Self {
1178			roles:Arc::new(RwLock::new(HashMap::new())),
1179
1180			permissions:Arc::new(RwLock::new(HashMap::new())),
1181
1182			audit_log:Arc::new(RwLock::new(Vec::new())),
1183		}
1184	}
1185
1186	/// Validate permission for an operation
1187	pub async fn validate_permission(&self, operation:&str, context:&SecurityContext) -> Result<(), String> {
1188		// Check if operation requires specific permissions
1189		let required_permissions = self.get_required_permissions(operation).await;
1190
1191		if required_permissions.is_empty() {
1192			return Ok(()); // No specific permissions required
1193		}
1194
1195		// Check if user has required permissions
1196		let mut user_permissions:Vec<String> = context.permissions.iter().cloned().collect();
1197
1198		for role in context.roles.iter() {
1199			let role_perms = self.get_role_permissions(role).await;
1200
1201			user_permissions.extend(role_perms);
1202		}
1203
1204		for required in required_permissions {
1205			if !user_permissions.contains(&required) {
1206				return Err(format!("Missing permission: {}", required));
1207			}
1208		}
1209
1210		// Log successful access
1211		self.log_security_event(SecurityEvent {
1212			event_type:SecurityEventType::AccessGranted,
1213			user_id:context.user_id.clone(),
1214			operation:operation.to_string(),
1215			timestamp:std::time::SystemTime::now(),
1216			details:Some(format!("Access granted for operation: {}", operation)),
1217		})
1218		.await;
1219
1220		Ok(())
1221	}
1222
1223	/// Get required permissions for an operation
1224	async fn get_required_permissions(&self, operation:&str) -> Vec<String> {
1225		// Define operation-to-permission mapping
1226		match operation {
1227			"file:write" | "file:delete" => vec!["file.write".to_string()],
1228
1229			"configuration:update" => vec!["config.update".to_string()],
1230
1231			"storage:set" => vec!["storage.write".to_string()],
1232
1233			"native:openExternal" => vec!["system.external".to_string()],
1234
1235			// Operations not in the mapping require no special permissions by default
1236			_ => Vec::new(),
1237		}
1238	}
1239
1240	/// Get permissions for a role
1241	async fn get_role_permissions(&self, role_name:&str) -> Vec<String> {
1242		let roles = self.roles.read().await;
1243
1244		roles.get(role_name).map(|role| role.permissions.clone()).unwrap_or_default()
1245	}
1246
1247	/// Log security event
1248	pub async fn log_security_event(&self, event:SecurityEvent) {
1249		let mut audit_log = self.audit_log.write().await;
1250
1251		audit_log.push(event);
1252
1253		// Keep only last 1000 events
1254		if audit_log.len() > 1000 {
1255			audit_log.remove(0);
1256		}
1257	}
1258
1259	/// Get security audit log
1260	pub async fn get_audit_log(&self, limit:usize) -> Vec<SecurityEvent> {
1261		let audit_log = self.audit_log.read().await;
1262
1263		audit_log.iter().rev().take(limit).cloned().collect()
1264	}
1265
1266	/// Initialize default roles and permissions
1267	pub async fn initialize_defaults(&self) {
1268		let mut permissions = self.permissions.write().await;
1269
1270		let mut roles = self.roles.write().await;
1271
1272		// Define standard permissions
1273		let standard_permissions = vec![
1274			("file.read", "Read file operations"),
1275			("file.write", "Write file operations"),
1276			("config.read", "Read configuration"),
1277			("config.update", "Update configuration"),
1278			("storage.read", "Read storage"),
1279			("storage.write", "Write storage"),
1280			("system.external", "Access external system resources"),
1281		];
1282
1283		for (name, description) in standard_permissions {
1284			permissions.insert(
1285				name.to_string(),
1286				Permission {
1287					name:name.to_string(),
1288					description:description.to_string(),
1289					category:"standard".to_string(),
1290				},
1291			);
1292		}
1293
1294		// Define standard roles
1295		let standard_roles = vec![
1296			("user", vec!["file.read", "config.read", "storage.read"]),
1297			(
1298				"developer",
1299				vec!["file.read", "file.write", "config.read", "storage.read", "storage.write"],
1300			),
1301			(
1302				"admin",
1303				vec![
1304					"file.read",
1305					"file.write",
1306					"config.read",
1307					"config.update",
1308					"storage.read",
1309					"storage.write",
1310					"system.external",
1311				],
1312			),
1313		];
1314
1315		for (name, role_permissions) in standard_roles {
1316			roles.insert(
1317				name.to_string(),
1318				Role {
1319					name:name.to_string(),
1320					permissions:role_permissions.iter().map(|p| p.to_string()).collect(),
1321					description:format!("{} role with standard permissions", name),
1322				},
1323			);
1324		}
1325	}
1326}