Skip to main content

Air/
Binary.rs

1//! # Air Binary Entry Point
2//!
3//! ## Overview
4//!
5//! Air 🪁 is the persistent background daemon that handles resource-intensive
6//! operations for the Land code editor. It runs as a standalone process
7//! alongside Mountain, communicating via the Vine (gRPC) protocol to offload
8//! tasks like updates, downloads, authentication, and file indexing.
9//!
10//! ## Architecture & Connections
11//!
12//! Air serves as the background services hub in the Land ecosystem:
13//!
14//! - **Wind** (Effect-TS): Provides functional programming patterns and
15//!   type-safe effects that Air uses for predictable state management and error
16//!   handling
17//!
18//! - **Cocoon** (NodeJS host): The Node.js runtime environment for frontend/web
19//!   components. Air coordinates with Cocoon through the Vine protocol to
20//!   deliver web assets and perform frontend build operations. Uses port 50052.
21//!
22//! - **Mountain** (Tauri bundler): The main desktop application bundle that
23//!   packages the Rust backend with the Electron/Node.js frontend. Mountain
24//!   receives work from Air through Vine (gRPC) and orchestrates the bundling
25//!   process.
26//!
27//! - **Vine** (gRPC protocol): The communication layer connecting all
28//!   components. Air hosts the Vine gRPC server on port 50053, receiving
29//!   requests from Mountain and responding with results from background
30//!   operations.
31//!
32//! ## VSCode Architecture References
33//!
34//! Air's architecture draws inspiration from VSCode's background service model:
35//!
36//! - **Update Service**: Reference
37//!   `Microsoft/Dependency/Editor/src/vs/platform/update`
38//!   - AbstractUpdateService: Base class for platform-specific update handling
39//!   - UpdateService: Manages update checks, downloads, and installations
40//!   - Similar to Air's UpdateManager component
41//!
42//! - **Lifecycle Management**: Reference
43//!   `Microsoft/Dependency/Editor/src/vs/base/common/lifecycle`
44//!   - Disposable pattern for resource cleanup
45//!   - Event emission and handling
46//!   - Graceful shutdown coordination similar to Air's shutdown logic
47//!
48//! - **Background Services**: VSCode's extension host and language server model
49//!   - Independent processes with IPC communication
50//!   - Health monitoring and automatic restart
51//!   - Similar to Air's daemon management approach
52//!
53//! ## Core Responsibilities
54//!
55//! ### 1. gRPC Server (Vine Protocol)
56//! - Hosts the Vine gRPC server on port 50053
57//! - Receives work requests from Mountain
58//! - Streams results and progress updates
59//! - Manages connection lifecycle and cleanup
60//! - Handles multiple concurrent connections
61//!
62//! ### 2. Authentication Service
63//! - Manages user authentication tokens
64//! - Handles cryptographic operations (signing, encryption)
65//! - Token refresh and validation
66//! - Secure storage management
67//!
68//! ### 3. Update Management
69//! - Checks for application updates
70//! - Downloads update packages
71//! - Verifies checksums and signatures
72//! - Coordinates update installation with Mountain
73//!
74//! ### 4. Download Manager
75//! - Downloads extensions and dependencies
76//! - Resumable downloads with retry logic
77//! - Bandwidth management and throttling
78//! - Progress tracking and reporting
79//!
80//! ### 5. File Indexing
81//! - Background file system scanning
82//! - Maintains searchable index
83//! - Supports code navigation features
84//! - Incremental updates and change detection
85//!
86//! ### 6. Resource Monitoring
87//! - CPU and memory usage tracking
88//! - Connection pool management
89//! - Background task lifecycle
90//! - Performance metrics collection
91//!
92//! ## Protocol Details
93//!
94//! **Vine Protocol (gRPC)**
95//! - Version: 1
96//! - Port: 50053 (Air), 50052 (Cocoon)
97//! - Transport: HTTP/2 with TLS (optional)
98//! - Serialization: Protocol Buffers
99//!
100//! ### Protocol Messages
101//! - `DownloadRequest`: Request to download a file/extension
102//! - `DownloadResponse`: Progress updates and completion
103//! - `AuthRequest`: Authentication/token operations
104//! - `AuthResponse`: Token data and status
105//! - `UpdateRequest`: Update check and download
106//! - `UpdateResponse`: Update availability and progress
107//! - `IndexRequest`: File indexing operations
108//! - `IndexResponse`: Index status and results
109//! - `HealthRequest`: Health check queries
110//! - `HealthResponse`: Service health and metrics
111//!
112//! ## FUTURE Enhancements
113//!
114//! ### High Priority
115//! - [ ] Complete CLI command implementations (all placeholders)
116//! - [ ] Add TLS/mTLS support for gRPC connections
117//! - [ ] Implement connection authentication/authorization
118//! - [ ] Add metrics endpoint (/metrics) HTTP server
119//! - [ ] Implement proper configuration hot-reload
120//! - [ ] Add comprehensive integration tests
121//!
122//! ### Medium Priority
123//! - [ ] Add prometheus metrics export (currently partial)
124//! - [ ] Implement grace period for shutdown (pending operations)
125//! - [ ] Add connection rate limiting
126//! - [ ] Implement request prioritization
127//! - [ ] Add audit logging for sensitive operations
128//! - [ ] Implement plugin/hot-reload system
129//!
130//! ### Low Priority
131//! - [ ] Add structured logging with correlation IDs
132//! - [ ] Implement distributed tracing integration
133//! - [ ] Add health check endpoint for load balancers
134//! - [ ] Implement connection pooling optimizations
135//! - [ ] Add telemetry/observability export
136//! - [ ] Implement A/B testing for features
137//! ## Error Handling Strategy
138//!
139//! All public functions use defensive coding:
140//! - Input validation with descriptive errors
141//! - Timeout handling with cancellation
142//! - Resource cleanup via Drop and explicit cleanup
143//! - Circuit breaker for external dependencies
144//! - Retry logic with exponential backoff
145//! - Metrics recording for all operations
146//!
147//! ## Shutdown Sequence
148//!
149//! 1. Accept shutdown signal (SIGTERM, SIGINT)
150//! 2. Stop accepting new requests
151//! 3. Wait for in-flight requests (with timeout)
152//! 4. Stop background services
153//! 5. Cancel pending background tasks
154//! 6. Release daemon lock
155//! 7. Log final statistics
156//! 8. Exit cleanly
157//!
158//! ## Port Allocation
159//!
160//! - **50052**: Cocoon (NodeJS host) - Frontend/web services
161//! - **50053**: Air (this daemon) - Background services
162//! - **50054**: Reserved for future use (e.g., SideCar service)
163//! - **50055**: Reserved for future metrics endpoints
164
165#![allow(non_snake_case)]
166
167use std::{env, net::SocketAddr, sync::Arc, time::Duration};
168
169use AirLibrary::dev_log;
170use tokio::{signal, time::interval};
171// Import types from AirLibrary (the crate root)
172use AirLibrary::{
173	ApplicationState::ApplicationState,
174	Authentication::AuthenticationService,
175	CLI::{CliParser, Command, ConfigCommand, DebugCommand, OutputFormatter},
176	Configuration::{AirConfiguration, ConfigurationManager},
177	Daemon::DaemonManager,
178	DefaultBindAddress,
179	DefaultConfigFile,
180	Downloader::DownloadManager,
181	HealthCheck::{HealthCheckLevel, HealthCheckManager, HealthStatistics},
182	Indexing::FileIndexer,
183	Logging,
184	Metrics,
185	ProtocolVersion,
186	Tracing,
187	Updates::UpdateManager,
188	VERSION,
189	Vine::Generated::air::air_service_server::AirServiceServer,
190	Vine::Server::AirVinegRPCService::AirVinegRPCService,
191};
192
193// =============================================================================
194// Debug Helpers
195// =============================================================================
196
197/// Logs a checkpoint message at lifecycle level with context tracking
198macro_rules! Trace {
199
200    ($($arg:tt)*) => {{
201
202        dev_log!("lifecycle", $($arg)*);
203    }};
204}
205
206/// Shutdown signal handler for graceful termination
207///
208/// This function waits for either Ctrl+C (SIGINT) or SIGTERM signals
209/// and then initiates the shutdown sequence. It provides a timeout
210/// to handle cases where signal handlers fail to install properly.
211///
212/// # FUTURE Enhancements
213/// - Add configurable shutdown timeout (currently infinite)
214/// - Implement signal handling for SIGHUP (reload config)
215/// - Add Windows-specific signal handling beyond Ctrl+C
216/// - Implement graceful timeout with pending operation completion
217async fn WaitForShutdownSignal() {
218	dev_log!("lifecycle", "[Shutdown] Waiting for termination signal...");
219
220	let ctrl_c = async {
221		match signal::ctrl_c().await {
222			Ok(()) => dev_log!("lifecycle", "[Shutdown] Received Ctrl+C signal"),
223
224			Err(e) => dev_log!("lifecycle", "error: [Shutdown] Failed to install Ctrl+C handler: {}", e),
225		}
226	};
227
228	#[cfg(unix)]
229	let terminate = async {
230		match signal::unix::signal(signal::unix::SignalKind::terminate()) {
231			Ok(mut sig) => {
232				sig.recv().await;
233
234				dev_log!("lifecycle", "[Shutdown] Received SIGTERM signal");
235			},
236
237			Err(e) => dev_log!("lifecycle", "error: [Shutdown] Failed to install signal handler: {}", e),
238		}
239	};
240
241	#[cfg(not(unix))]
242	let terminate = std::future::pending::<()>();
243
244	tokio::select! {
245
246		_ = ctrl_c => {},
247
248		_ = terminate => {},
249	}
250
251	dev_log!("lifecycle", "[Shutdown] Signal received, initiating graceful shutdown");
252}
253
254/// Initialize logging based on environment variables
255///
256/// Sets up structured logging with support for JSON output (useful for
257/// production) and file-based logging (useful for debugging). Environment
258/// variables:
259///
260/// - `AIR_LOG_JSON`: "true" enables JSON formatted output
261/// - `AIR_LOG_LEVEL`: Set logging level (debug, info, warn, error)
262/// - `AIR_LOG_FILE`: Path to log file (optional)
263///
264/// # FUTURE Enhancements
265/// - Add log rotation support
266/// - Implement log file size limits
267/// - Add structured log correlation IDs
268/// - Support syslog integration on Unix
269/// - Add Windows Event Log integration
270fn InitializeLogging() {
271	// Validate environment variables
272	let json_output = match std::env::var("AIR_LOG_JSON") {
273		Ok(val) if !val.is_empty() => {
274			let normalized = val.to_lowercase();
275
276			if normalized != "true" && normalized != "false" {
277				eprintln!(
278					"Warning: Invalid AIR_LOG_JSON value '{}', expected 'true' or 'false'. Using default: false",
279					val
280				);
281
282				false
283			} else {
284				normalized == "true"
285			}
286		},
287
288		Ok(_) => false,
289
290		Err(_) => false,
291	};
292
293	// Validate log file path exists and is writable
294	let log_file_path = std::env::var("AIR_LOG_FILE").ok().and_then(|path| {
295		if path.is_empty() {
296			None
297		} else {
298			// Check if directory exists for the log file
299			if let Some(parent) = std::path::PathBuf::from(&path).parent() {
300				if parent.as_os_str().is_empty() {
301					// No parent directory, use current directory
302					Some(path)
303				} else if parent.exists() {
304					Some(path)
305				} else {
306					eprintln!(
307						"Warning: Log file directory does not exist: {}. Logging to stdout only.",
308						parent.display()
309					);
310					None
311				}
312			} else {
313				Some(path)
314			}
315		}
316	});
317
318	// Initialize structured logging with defensive error handling
319	let log_result = Logging::InitializeLogger(json_output, log_file_path.clone());
320
321	match log_result {
322		Ok(_) => {
323			let log_info = match &log_file_path {
324				Some(path) => format!("file: {}", path),
325
326				None => "stdout/stderr".to_string(),
327			};
328
329			dev_log!(
330				"lifecycle",
331				"[Boot] Logging initialized - JSON: {}, Output: {}",
332				json_output,
333				log_info
334			);
335		},
336
337		Err(e) => {
338			// Fallback: ensure we can at least log errors to stderr
339			eprintln!("[ERROR] Failed to initialize structured logging: {}", e);
340
341			eprintln!("[ERROR] Logging will fall back to stderr-only output");
342		},
343	}
344}
345
346/// Parse command line arguments into daemon config or CLI command
347///
348/// Handles two modes of operation:
349/// 1. CLI mode: Execute commands like `status`, `restart`, `config`, etc.
350/// 2. Daemon mode: Start the background service with optional config/bind args
351///
352/// # Arguments
353///
354/// Returns a tuple of (config_path, bind_address, optional_command)
355/// - If `command` is Some, daemon startup should be skipped
356/// - Otherwise, start daemon with provided config path and bind address
357///
358/// # FUTURE Enhancements
359/// - Add validation for bind address format
360/// - Add validation for config file exists/readable
361/// - Support `--validate-config` flag to check config without starting
362/// - Add `--daemon` flag to force daemon mode with CLI commands
363/// - Make flags case-insensitive
364fn ParseArguments() -> (Option<String>, Option<String>, Option<Command>) {
365	// Defensive: Ensure args collection is not extremely large
366	let args:Vec<String> = std::env::args().collect();
367
368	// Safety: Limit argument length to prevent potential DoS
369	if args.len() > 1024 {
370		eprintln!("[ERROR] Too many command line arguments (max: 1024)");
371
372		std::process::exit(1);
373	}
374
375	// Safety: Validate each argument length
376	for (i, arg) in args.iter().enumerate() {
377		if arg.len() > 4096 {
378			eprintln!("[ERROR] Argument at position {} is too long (max: 4096 characters)", i);
379
380			std::process::exit(1);
381		}
382	}
383
384	// Check if we're running with CLI command (first arg is a known command)
385	if args.len() > 1 {
386		match args[1].as_str() {
387			"status" | "restart" | "config" | "metrics" | "logs" | "debug" | "help" | "version" | "-h" | "--help"
388			| "-v" | "--version" => {
389				// Parse CLI command with error handling
390				match CliParser::parse(args.clone()) {
391					Ok(cmd) => {
392						dev_log!("lifecycle", "[Boot] CLI command parsed: {:?}", cmd);
393
394						return (None, None, Some(cmd));
395					},
396
397					Err(e) => {
398						eprintln!("[ERROR] Error parsing CLI command: {}", e);
399
400						eprintln!("[ERROR] Run 'Air help' for usage information");
401
402						std::process::exit(1);
403					},
404				}
405			},
406
407			_ => {},
408		}
409	}
410
411	// Parse as daemon arguments with validation
412	let mut config_path:Option<String> = None;
413
414	let mut bind_address:Option<String> = None;
415
416	let mut i = 0;
417
418	while i < args.len() {
419		match args[i].as_str() {
420			"--config" | "-c" => {
421				if i + 1 < args.len() {
422					let path = &args[i + 1];
423
424					// Validate path doesn't contain suspicious characters
425					if path.contains("..") || path.contains('\0') {
426						eprintln!("[ERROR] Invalid config path: contains '..' or null character");
427
428						std::process::exit(1);
429					}
430
431					config_path = Some(path.clone());
432
433					i += 1;
434				} else {
435					eprintln!("[ERROR] --config flag requires a path argument");
436
437					std::process::exit(1);
438				}
439			},
440
441			"--bind" | "-b" => {
442				if i + 1 < args.len() {
443					let addr = &args[i + 1];
444
445					// Basic validation of address format
446					if addr.is_empty() || addr.len() > 256 {
447						eprintln!("[ERROR] Invalid bind address: must be 1-256 characters");
448
449						std::process::exit(1);
450					}
451
452					// Full validation happens during bind, but check for null characters
453					if addr.contains('\0') {
454						eprintln!("[ERROR] Invalid bind address: contains null character");
455
456						std::process::exit(1);
457					}
458
459					bind_address = Some(addr.clone());
460
461					i += 1;
462				} else {
463					eprintln!("[ERROR] --bind flag requires an address argument");
464
465					std::process::exit(1);
466				}
467			},
468
469			_ => {
470
471				// Ignore unknown flags or positional arguments
472				// Could add warning for unknown flags if desired
473			},
474		}
475
476		i += 1;
477	}
478
479	dev_log!(
480		"lifecycle",
481		"[Boot] Daemon mode - config: {:?}, bind: {:?}",
482		config_path,
483		bind_address
484	);
485
486	(config_path, bind_address, None)
487}
488
489/// Handle CLI commands with comprehensive implementation
490///
491/// Executes user commands against the Air daemon. Most commands require
492/// connecting to the running daemon via gRPC. Commands that don't require
493/// a running daemon (like `version`) execute immediately.
494///
495/// # Errors
496///
497/// Returns errors when:
498/// - Daemon connection fails (for commands requiring daemon)
499/// - Command parameters are invalid
500/// - Daemon returns an error response
501/// - I/O operations fail
502///
503/// # FUTURE Enhancements
504/// - Implement actual daemon connection via gRPC
505/// - Add command timeout (default: 30s, configurable)
506/// - Implement graceful degradation for partial failures
507/// - Add retry logic for transient failures
508/// - Add command history/log
509/// - Implement interactive mode
510/// - Add tab-completion support
511async fn HandleCommand(cmd:Command) -> Result<(), Box<dyn std::error::Error>> {
512	// Validate command parameters before execution
513	let validation_result = validate_command(&cmd);
514
515	if let Err(e) = validation_result {
516		eprintln!("[ERROR] Command validation failed: {}", e);
517
518		return Err(e.into());
519	}
520
521	match cmd {
522		Command::Help { command } => {
523			// Defensive: Ensure command string is not too long if provided
524			if let Some(ref cmd) = command {
525				if cmd.len() > 128 {
526					eprintln!("[ERROR] Command name too long (max: 128 characters)");
527
528					return Err("Command name too long".into());
529				}
530			}
531
532			println!("{}", OutputFormatter::format_help(command.as_deref(), VERSION));
533
534			Ok(())
535		},
536
537		Command::Version => {
538			println!("Air {} ({})", VERSION, env!("CARGO_PKG_NAME"));
539
540			println!("Protocol: Version {} (gRPC)", ProtocolVersion);
541
542			println!("Port: {} (Air), {} (Cocoon)", DefaultBindAddress, "[::1]:50052");
543
544			println!("Build: {} {}", env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_NAME"));
545
546			Ok(())
547		},
548
549		Command::Status { service, verbose, json } => {
550			// Validate inputs
551			if let Some(ref svc) = service {
552				if svc.is_empty() || svc.len() > 64 {
553					return Err("Service name must be 1-64 characters".into());
554				}
555			}
556
557			// Connect to daemon via gRPC and request status
558			// For now, perform basic connection check
559
560			// Implementation note: Detailed service status requires gRPC client integration
561			if let Some(svc) = service {
562				println!("📊 Status for service: {}", svc);
563
564				// Attempt connection with timeout
565				match attempt_daemon_connection().await {
566					Ok(_) => {
567						println!("  Status: ⚠️  Running (basic check)");
568
569						println!("  Note: Connect to gRPC endpoint for detailed status");
570					},
571
572					Err(e) => {
573						println!("  Status: ❌ Cannot connect to daemon");
574
575						println!("  Error: {}", e);
576
577						println!("");
578
579						println!("  To start the daemon, run: Air --daemon");
580
581						return Err(format!("Cannot connect to daemon: {}", e).into());
582					},
583				}
584			} else {
585				println!("📊 Air Daemon Status");
586
587				println!("");
588
589				// Attempt connection
590				match attempt_daemon_connection().await {
591					Ok(_) => {
592						println!("  Overall: ⚠️  Running (basic check)");
593
594						println!("  Note: Connect to gRPC endpoint for detailed status");
595
596						println!("");
597
598						println!("  Services:");
599
600						println!("    gRPC Server: ✅ Listening");
601
602						println!("    Authentication: ⚠️  Status check not implemented");
603
604						println!("    Updates: ⚠️  Status check not implemented");
605
606						println!("    Download Manager: ⚠️  Status check not implemented");
607
608						println!("    File Indexer: ⚠️  Status check not implemented");
609					},
610
611					Err(e) => {
612						println!("  Overall: ❌ Daemon not running");
613
614						println!("  Error: {}", e);
615
616						println!("");
617
618						println!("  To start the daemon, run: Air --daemon");
619
620						return Err("Daemon not running".into());
621					},
622				}
623			}
624
625			if verbose {
626				println!("");
627
628				println!("🔍 Verbose Information:");
629
630				println!("  Debug mode: Disabled by default");
631
632				println!("  Log level: info");
633
634				println!("  Config file: {}", DefaultConfigFile);
635
636				println!("");
637
638				println!("  Detailed service status can be obtained via gRPC:");
639
640				println!("    - Service uptime");
641
642				println!("    - Request/response statistics");
643
644				println!("    - Error rates and recent errors");
645
646				println!("    - Resource usage");
647
648				println!("    - Active connections");
649			}
650
651			if json {
652				println!("");
653
654				println!("📋 JSON Output:");
655
656				println!(
657					"{}",
658					serde_json::json!({
659						"overall": "running",
660						"services": {
661							"grpc": "listening",
662							"status": "not_implemented"
663						},
664						"note": "Detailed JSON output not yet implemented"
665					})
666				);
667			}
668
669			Ok(())
670		},
671
672		Command::Restart { service, force } => {
673			// Validate input
674			if let Some(ref svc) = service {
675				if svc.is_empty() || svc.len() > 64 {
676					return Err("Service name must be 1-64 characters".into());
677				}
678			}
679
680			// Restart daemon via gRPC
681			// Implementation note: Requires gRPC client with Restart RPC method
682			println!("🔄 Restart Command");
683
684			println!("");
685
686			if let Some(svc) = service {
687				println!("Restarting service: {}", svc);
688
689				println!("  Note: Individual service restart requires gRPC integration");
690
691				println!("  Workaround: Restart the entire daemon");
692			} else {
693				println!("Restarting all services...");
694
695				println!("  Note: Full daemon restart requires gRPC integration");
696
697				println!("  Workaround: Use: kill <pid> && Air --daemon");
698			}
699
700			if force {
701				println!("");
702
703				println!("⚠️  Force mode enabled");
704
705				println!(
706					"  Note: Force restart requires proper coordination to gracefully terminate in-progress operations"
707				);
708			}
709
710			Err("Restart command requires gRPC integration".into())
711		},
712
713		Command::Config(config_cmd) => {
714			match config_cmd {
715				ConfigCommand::Get { key } => {
716					// Validate key
717					if key.is_empty() || key.len() > 256 {
718						return Err("Configuration key must be 1-256 characters".into());
719					}
720
721					if key.contains('\0') || key.contains('\n') {
722						return Err("Configuration key contains invalid characters".into());
723					}
724
725					// Connect to daemon and get config value
726					// Implementation note: Requires gRPC client with GetConfig RPC method
727					println!("⚙️  Get Configuration");
728
729					println!("  Key: {}", key);
730
731					println!("");
732
733					match attempt_daemon_connection().await {
734						Ok(_) => {
735							println!("  Status: ✅ Connected to daemon");
736
737							println!("");
738
739							println!("  Note: Config retrieval via gRPC not yet implemented");
740
741							println!("  Config value would be retrieved from daemon's configuration manager");
742						},
743
744						Err(e) => {
745							println!("  Status: ❌ Cannot connect to daemon");
746
747							println!("  Error: {}", e);
748
749							println!("");
750
751							println!("  Workaround: Check config file directly: cat {}", DefaultConfigFile);
752
753							return Err(format!("Cannot get config: {}", e).into());
754						},
755					}
756
757					Err("Config 'get' command requires gRPC integration".into())
758				},
759
760				ConfigCommand::Set { key, value } => {
761					// Validate inputs
762					if key.is_empty() || key.len() > 256 {
763						return Err("Configuration key must be 1-256 characters".into());
764					}
765
766					if value.len() > 8192 {
767						return Err("Configuration value too long (max: 8192 characters)".into());
768					}
769
770					if key.contains('\0') || key.contains('\n') {
771						return Err("Configuration key contains invalid characters".into());
772					}
773
774					// Connect to daemon and set config value
775					// Implementation note: Requires gRPC client with SetConfig RPC method
776					println!("⚙️  Set Configuration");
777
778					println!("  Key: {}", key);
779
780					println!("  Value: {}", value);
781
782					println!("");
783
784					match attempt_daemon_connection().await {
785						Ok(_) => {
786							println!("  Status: ✅ Connected to daemon");
787
788							println!("");
789
790							println!("  Note: Config update via gRPC not yet implemented");
791
792							println!("  Config value would be set in daemon's configuration manager");
793						},
794
795						Err(e) => {
796							println!("  Status: ❌ Cannot connect to daemon");
797
798							println!("  Error: {}", e);
799
800							println!("");
801
802							println!("  Workaround: Edit config file directly, then use 'Air config reload'");
803
804							return Err(format!("Cannot set config: {}", e).into());
805						},
806					}
807
808					println!("");
809
810					println!("  ⚠️  Warning: Config changes may require reload or restart");
811
812					Err("Config 'set' command requires gRPC integration".into())
813				},
814
815				ConfigCommand::Reload { validate } => {
816					// Reload configuration
817					// Implementation note: Requires gRPC client with ReloadConfig RPC method
818					println!("🔄 Reload Configuration");
819
820					println!("");
821
822					match attempt_daemon_connection().await {
823						Ok(_) => {
824							println!("  Status: ✅ Connected to daemon");
825
826							println!("");
827
828							if validate {
829								println!("  Validating configuration...");
830
831								println!("  Note: Validation not yet implemented");
832							}
833
834							println!("  Note: Config reload via gRPC not yet implemented");
835
836							println!("  Workaround: Restart daemon to apply config changes");
837						},
838
839						Err(e) => {
840							println!("  Status: ❌ Cannot connect to daemon");
841
842							println!("  Error: {}", e);
843
844							return Err(format!("Cannot reload config: {}", e).into());
845						},
846					}
847
848					Err("Config 'reload' command requires gRPC integration".into())
849				},
850
851				ConfigCommand::Show { json } => {
852					// Show configuration
853					// Implementation note: Requires gRPC client with GetFullConfig RPC method
854					println!("⚙️  Show Configuration");
855
856					println!("");
857
858					if json {
859						println!("  JSON output requested");
860
861						match attempt_daemon_connection().await {
862							Ok(_) => {
863								println!("  Status: ✅ Connected to daemon");
864
865								println!("  Note: JSON config export via gRPC not yet implemented");
866							},
867
868							Err(e) => {
869								println!("  Status: ❌ Cannot connect to daemon");
870
871								println!("  Error: {}", e);
872
873								return Err(format!("Cannot show config: {}", e).into());
874							},
875						}
876					} else {
877						println!("  Current Configuration:");
878
879						match attempt_daemon_connection().await {
880							Ok(_) => {
881								println!("  Status: ✅ Connected to daemon");
882
883								println!("  Note: Config display via gRPC not yet implemented");
884							},
885
886							Err(e) => {
887								println!("  Status: ❌ Cannot connect to daemon");
888
889								println!("  Error: {}", e);
890
891								println!("  Workaround: View config file: cat {}", DefaultConfigFile);
892
893								return Err(format!("Cannot show config: {}", e).into());
894							},
895						}
896					}
897
898					println!("");
899
900					println!("  Default config file: {}", DefaultConfigFile);
901
902					println!("  Config directory: ~/.config/Air/");
903
904					Err("Config 'show' command requires gRPC integration".into())
905				},
906
907				ConfigCommand::Validate { path } => {
908					// Validate path if provided
909					if let Some(ref p) = path {
910						if p.is_empty() || p.len() > 512 {
911							return Err("Config path must be 1-512 characters".into());
912						}
913
914						if p.contains("..") || p.contains('\0') {
915							return Err("Config path contains invalid characters".into());
916						}
917					}
918
919					println!("✅ Validate Configuration");
920
921					println!("");
922
923					let config_path = path.unwrap_or_else(|| DefaultConfigFile.to_string());
924
925					println!("  Config file: {}", config_path);
926
927					println!("");
928
929					// Check if file exists
930					match std::path::Path::new(&config_path).exists() {
931						true => {
932							println!("  ✅ Config file exists");
933
934							println!("  Note: Detailed validation not yet implemented");
935
936							println!("  Workaround: Use: Air --validate-config");
937						},
938
939						false => {
940							println!("  ❌ Config file not found");
941
942							println!("  Hint: Create a config file or use defaults");
943						},
944					}
945
946					Err("Config 'validate' command not yet implemented".into())
947				},
948			}
949		},
950
951		Command::Metrics { json, service } => {
952			// Validate inputs
953			if let Some(ref svc) = service {
954				if svc.is_empty() || svc.len() > 64 {
955					return Err("Service name must be 1-64 characters".into());
956				}
957			}
958
959			println!("📊 Metrics");
960
961			println!("");
962
963			// Attempt to get metrics from daemon
964			match attempt_daemon_connection().await {
965				Ok(_) => {
966					println!("  Status: ✅ Daemon is running");
967
968					println!("");
969
970					println!("  Note: Metrics collection is partially implemented");
971
972					println!("");
973
974					println!("  Current Metrics (basic):");
975
976					println!("    Uptime: Not tracked yet");
977
978					println!("    Requests: Not tracked yet");
979
980					println!("    Errors: Not tracked yet");
981
982					println!("    Memory: Not tracked yet");
983
984					println!("    CPU: Not tracked yet");
985
986					println!("");
987
988					println!("  Note: Comprehensive metrics require gRPC integration:");
989
990					println!("    - Request/response counters");
991
992					println!("    - Latency percentiles");
993
994					println!("    - Error rate tracking");
995
996					println!("    - Resource usage");
997
998					println!("    - Connection pool stats");
999
1000					println!("    - Background queue depth");
1001				},
1002
1003				Err(e) => {
1004					println!("  Status: ❌ Cannot connect to daemon");
1005
1006					println!("  Error: {}", e);
1007
1008					return Err(format!("Cannot retrieve metrics: {}", e).into());
1009				},
1010			}
1011
1012			if json {
1013				println!("");
1014
1015				println!("📋 JSON Output:");
1016
1017				println!(
1018					"{}",
1019					serde_json::json!({
1020						"note": "Detailed metrics not yet implemented",
1021						"suggestion": "Use /metrics endpoint when daemon is running"
1022					})
1023				);
1024			}
1025
1026			if let Some(svc) = service {
1027				println!("");
1028
1029				println!("  Service-specific metrics requested: {}", svc);
1030
1031				println!("  Note: Service isolation not yet implemented");
1032			}
1033
1034			Ok(())
1035		},
1036
1037		Command::Logs { service, tail, filter, follow } => {
1038			// Validate inputs
1039			if let Some(ref svc) = service {
1040				if svc.is_empty() || svc.len() > 64 {
1041					return Err("Service name must be 1-64 characters".into());
1042				}
1043			}
1044
1045			if let Some(n) = tail {
1046				if n < 1 || n > 10000 {
1047					return Err("Tail count must be 1-10000 lines".into());
1048				}
1049			}
1050
1051			if let Some(ref f) = filter {
1052				if f.is_empty() || f.len() > 512 {
1053					return Err("Filter string must be 1-512 characters".into());
1054				}
1055			}
1056
1057			println!("📝 Logs");
1058
1059			println!("");
1060
1061			// Check for log file
1062			let log_file = std::env::var("AIR_LOG_FILE").ok();
1063
1064			let log_dir = std::env::var("AIR_LOG_DIR").ok();
1065
1066			match (log_file, log_dir) {
1067				(Some(file), _) => {
1068					println!("  Log file: {}", file);
1069
1070					// Check if file exists and is readable
1071					if std::path::Path::new(&file).exists() {
1072						println!("  Status: ✅ Log file exists");
1073
1074						println!("");
1075
1076						// Log tailing and filtering
1077						// Implementation note: Requires log file streaming support
1078						println!("  Note: Log tailing via file API not yet implemented");
1079
1080						println!("  Workaround: Use standard tools:");
1081
1082						println!("    - tail -n {} {}", tail.unwrap_or(100), file);
1083
1084						if let Some(f) = filter {
1085							println!("    - grep '{}' {} | tail -n {}", f, file, tail.unwrap_or(100));
1086						}
1087
1088						if follow {
1089							println!("    - tail -f {}", file);
1090						}
1091					} else {
1092						println!("  Status: ❌ Log file not found");
1093
1094						println!("  Check logging configuration");
1095					}
1096				},
1097
1098				(_, Some(dir)) => {
1099					println!("  Log directory: {}", dir);
1100
1101					println!("  Note: Log file viewing not yet implemented");
1102
1103					println!("  Workaround: Find and view log files in the directory");
1104				},
1105
1106				_ => {
1107					println!("  Log file: Not configured");
1108
1109					println!("  Set via: AIR_LOG_FILE=/path/to/Air.log");
1110
1111					println!("");
1112
1113					println!("  Logs are likely going to stdout/stderr");
1114
1115					println!("  Use journalctl (Linux/macOS) or Event Viewer (Windows)");
1116				},
1117			}
1118
1119			if let Some(svc) = service {
1120				println!("");
1121
1122				println!("  Service-specific logs requested: {}", svc);
1123
1124				println!("  Note: Service log isolation not yet implemented");
1125			}
1126
1127			// For now, show a placeholder
1128			Err("Logs command not yet fully implemented".into())
1129		},
1130
1131		Command::Debug(debug_cmd) => {
1132			match debug_cmd {
1133				DebugCommand::DumpState { service, json } => {
1134					// Validate input
1135					if let Some(ref svc) = service {
1136						if svc.is_empty() || svc.len() > 64 {
1137							return Err("Service name must be 1-64 characters".into());
1138						}
1139					}
1140
1141					println!("🔧 Debug: Dump State");
1142
1143					println!("");
1144
1145					if let Some(svc) = service {
1146						println!("  Service: {}", svc);
1147
1148						println!("  Note: Service state isolation not yet implemented");
1149					} else {
1150						println!("  Dumping all service states...");
1151
1152						println!("  Note: State dumping not yet implemented");
1153					}
1154
1155					if json {
1156						println!("");
1157
1158						println!("  JSON format requested");
1159
1160						println!("  Note: JSON state export not yet implemented");
1161					}
1162
1163					println!("");
1164
1165					println!("  Note: State dumping requires gRPC integration:");
1166
1167					println!("    - Application state");
1168
1169					println!("    - Service states");
1170
1171					println!("    - Connection pool");
1172
1173					println!("    - Background tasks");
1174
1175					println!("    - Metrics cache");
1176
1177					println!("    - Configuration snapshot");
1178
1179					Err("Debug 'dump-state' command not yet implemented".into())
1180				},
1181
1182				DebugCommand::DumpConnections { format } => {
1183					println!("🔧 Debug: Dump Connections");
1184
1185					println!("");
1186
1187					match attempt_daemon_connection().await {
1188						Ok(_) => {
1189							println!("  Status: ✅ Daemon is running");
1190
1191							println!("");
1192
1193							println!("  Active Connections: 0");
1194
1195							println!("  Note: Connection tracking not yet implemented");
1196						},
1197
1198						Err(e) => {
1199							println!("  Status: ❌ Cannot connect to daemon");
1200
1201							println!("  Error: {}", e);
1202
1203							return Err(format!("Cannot dump connections: {}", e).into());
1204						},
1205					}
1206
1207					if let Some(fmt) = format {
1208						println!("");
1209
1210						println!("  Format: {}", fmt);
1211
1212						println!("  Note: Custom format not yet implemented");
1213					}
1214
1215					println!("");
1216
1217					println!("  Note: Connection dump requires gRPC integration:");
1218
1219					println!("    - Connection ID");
1220
1221					println!("    - Remote address");
1222
1223					println!("    - Connected at timestamp");
1224
1225					println!("    - Last activity");
1226
1227					println!("    - Active requests");
1228
1229					println!("    - Bytes transferred");
1230
1231					Err("Debug 'dump-connections' command not yet implemented".into())
1232				},
1233
1234				DebugCommand::HealthCheck { verbose, service } => {
1235					// Validate input
1236					if let Some(ref svc) = service {
1237						if svc.is_empty() || svc.len() > 64 {
1238							return Err("Service name must be 1-64 characters".into());
1239						}
1240					}
1241
1242					println!("🔧 Debug: Health Check");
1243
1244					println!("");
1245
1246					match attempt_daemon_connection().await {
1247						Ok(_) => {
1248							println!("  Overall: ⚠️  Basic check passed");
1249
1250							println!("");
1251
1252							if let Some(svc) = service {
1253								println!("  Service: {}", svc);
1254
1255								println!("  Status: Not checked (detailed checks not implemented)");
1256							} else {
1257								println!("  Services:");
1258
1259								println!("    gRPC Server: ✅ Responding");
1260
1261								println!("    Authentication: ⏸️  Not checked");
1262
1263								println!("    Updates: ⏸️  Not checked");
1264
1265								println!("    Download Manager: ⏸️  Not checked");
1266
1267								println!("    File Indexer: ⏸️  Not checked");
1268							}
1269
1270							if verbose {
1271								println!("");
1272
1273								println!("  🔍 Verbose Information:");
1274
1275								println!("    Last health check: Not tracked");
1276
1277								println!("    Health check interval: 30s (default)");
1278
1279								println!("    Failure threshold: 3 (configurable)");
1280
1281								println!("    Recovery threshold: 2 (configurable)");
1282							}
1283						},
1284
1285						Err(e) => {
1286							println!("  Overall: ❌ Daemon unreachable");
1287
1288							println!("  Error: {}", e);
1289
1290							return Err(format!("Health check failed: {}", e).into());
1291						},
1292					}
1293
1294					Err("Debug 'health-check' not detailed yet".into())
1295				},
1296
1297				DebugCommand::Diagnostics { level } => {
1298					println!("🔧 Debug: Diagnostics");
1299
1300					println!("");
1301
1302					println!("  Level: {:?}", level);
1303
1304					println!("");
1305
1306					// Show system information
1307					println!("  System Information:");
1308
1309					println!("    OS: {}", std::env::consts::OS);
1310
1311					println!("    Arch: {}", std::env::consts::ARCH);
1312
1313					println!("    Air Version: {}", VERSION);
1314
1315					println!("");
1316
1317					match attempt_daemon_connection().await {
1318						Ok(_) => {
1319							println!("  Daemon: ✅ Running");
1320						},
1321
1322						Err(e) => {
1323							println!("  Daemon: ❌ Running");
1324
1325							println!("  Error: {}", e);
1326						},
1327					}
1328
1329					println!("");
1330
1331					println!("  Note: Advanced diagnostics require additional infrastructure:");
1332
1333					println!("    - Thread dump");
1334
1335					println!("    - Memory profiling");
1336
1337					println!("    - Lock contention analysis");
1338
1339					println!("    - Resource leak detection");
1340
1341					println!("    - Performance bottlenecks");
1342
1343					Ok(())
1344				},
1345			}
1346		},
1347	}
1348}
1349
1350/// Validate command parameters to prevent invalid inputs
1351///
1352/// # FUTURE Enhancements
1353/// - Add timeout parameter validation
1354/// - Add rate limit checks for commands
1355/// - Implement command permission checks
1356fn validate_command(cmd:&Command) -> Result<(), String> {
1357	match cmd {
1358		Command::Help { command } => {
1359			if let Some(cmd) = command {
1360				if cmd.len() > 128 {
1361					return Err("Command name too long (max: 128)".to_string());
1362				}
1363			}
1364		},
1365
1366		_ => {},
1367	}
1368
1369	Ok(())
1370}
1371
1372/// Attempt to connect to the running daemon
1373///
1374/// Creates a basic TCP connection to check if the daemon is running.
1375/// This is a simplified check for pre-implementation status.
1376///
1377/// # FUTURE Enhancements
1378/// - Implement proper gRPC client connection
1379/// - Add connection timeout configuration
1380/// - Implement connection pooling
1381/// - Add authentication
1382/// Attempt to connect to the running daemon with retry logic
1383///
1384/// Creates a basic TCP connection to check if the daemon is running.
1385/// Implements exponential backoff retry for resilience.
1386///
1387/// # Arguments
1388/// * `max_retries` - Maximum number of retry attempts (default: 3)
1389/// * `initial_delay_ms` - Initial delay in milliseconds before first retry
1390///   (default: 500)
1391///
1392/// # Returns
1393/// Result<(), String> - Ok if connection successful, Err with message if failed
1394async fn attempt_daemon_connection_with_retry(max_retries:usize, initial_delay_ms:u64) -> Result<(), String> {
1395	use tokio::{
1396		net::TcpStream,
1397		time::{Duration, timeout},
1398	};
1399
1400	let addr = DefaultBindAddress;
1401
1402	let mut attempt = 0;
1403
1404	let mut delay_ms = initial_delay_ms;
1405
1406	loop {
1407		attempt += 1;
1408
1409		dev_log!("lifecycle", "[DaemonConnection] Attempt {} of {}", attempt, max_retries + 1);
1410
1411		// Timeout: 5 seconds per attempt
1412		let connection_result = timeout(Duration::from_secs(5), async { TcpStream::connect(addr).await }).await;
1413
1414		match connection_result {
1415			Ok(Ok(_stream)) => {
1416				dev_log!("lifecycle", "[DaemonConnection] Connected successfully on attempt {}", attempt);
1417
1418				return Ok(());
1419			},
1420
1421			Ok(Err(e)) => {
1422				dev_log!("lifecycle", "[DaemonConnection] Attempt {} failed: {}", attempt, e);
1423			},
1424
1425			Err(_) => {
1426				dev_log!("lifecycle", "[DaemonConnection] Attempt {} timed out", attempt);
1427			},
1428		}
1429
1430		// Check if we've exhausted retries
1431		if attempt > max_retries {
1432			break;
1433		}
1434
1435		// Exponential backoff: wait before next retry
1436		dev_log!("lifecycle", "[DaemonConnection] Waiting {}ms before retry...", delay_ms);
1437
1438		tokio::time::sleep(Duration::from_millis(delay_ms)).await;
1439
1440		delay_ms = delay_ms * 2; // Double the delay for next attempt
1441	}
1442
1443	Err(format!("Failed to connect after {} attempts", max_retries + 1))
1444}
1445
1446/// Attempt to connect to the running daemon (simple version with default retry)
1447///
1448/// This is the main entry point that uses default retry settings.
1449/// For more control, use attempt_daemon_connection_with_retry directly.
1450async fn attempt_daemon_connection() -> Result<(), String> {
1451	// Default: 3 retries with 500ms initial delay
1452	attempt_daemon_connection_with_retry(3, 500).await
1453}
1454
1455/// Handler for /metrics endpoint - returns Prometheus format metrics
1456///
1457/// Exports all collected metrics in Prometheus text format for scraping
1458/// by monitoring systems like Prometheus, Grafana, or custom dashboards.
1459///
1460/// Metrics include:
1461/// - Request counters (total, successful, failed)
1462/// - Response times (histogram)
1463/// - Resource usage (memory, CPU)
1464/// - Connection counts
1465/// - Background task status
1466///
1467/// # FUTURE Enhancements
1468/// - Add timeout for metrics export (should not block daemon)
1469/// - Implement metric label support (service, host, etc.)
1470/// - Add counter reset capability
1471/// - Implement metric filtering via query parameters
1472/// - Add histogram quantiles (p50, p95, p99)
1473/// - Support both Prometheus and OpenMetrics formats
1474#[allow(dead_code)]
1475fn HandleMetricsRequest() -> String {
1476	// Defensive: Use a timeout to prevent metrics export from blocking
1477	let _timeout_duration = std::time::Duration::from_millis(100);
1478
1479	let metrics_collector = Metrics::GetMetrics();
1480
1481	// Export metrics with error handling and timeout
1482	let export_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| metrics_collector.ExportMetrics()));
1483
1484	match export_result {
1485		Ok(Ok(metrics_text)) => {
1486			// Validate metrics text is not too large
1487			if metrics_text.len() > 10_000_000 {
1488				dev_log!(
1489					"metrics",
1490					"error: [Metrics] Exported metrics unreasonably large (size: {} bytes)",
1491					metrics_text.len()
1492				);
1493
1494				format!("# ERROR: Metrics export too large (max: 10MB)\n")
1495			} else {
1496				metrics_text
1497			}
1498		},
1499
1500		Ok(Err(e)) => {
1501			dev_log!("metrics", "error: [Metrics] Failed to export metrics: {}", e);
1502
1503			format!("# ERROR: Failed to export metrics: {}\n", e)
1504		},
1505
1506		Err(_) => {
1507			dev_log!("metrics", "error: [Metrics] Metrics export panicked");
1508
1509			format!("# ERROR: Metrics export failed due to internal error\n")
1510		},
1511	}
1512}
1513
1514// =============================================================================
1515// Main Application Entry Point
1516// =============================================================================
1517
1518/// The main asynchronous function that sets up and runs the Air daemon
1519///
1520/// This is the primary entry point for the Air background service. It
1521/// coordinates all initialization, starts the gRPC server, manages the daemon
1522/// lifecycle, and handles graceful shutdown.
1523///
1524/// # Startup Sequence
1525///
1526/// 1. Initialize logging and observability (metrics, tracing)
1527/// 2. Parse command-line arguments (for CLI commands or daemon config)
1528/// 3. Load configuration (with validation)
1529/// 4. Acquire daemon lock (ensure single instance)
1530/// 5. Initialize application state
1531/// 6. Create and register core services
1532/// 7. Start gRPC server (Vine protocol)
1533/// 8. Start background tasks and monitoring
1534/// 9. Wait for shutdown signal
1535/// 10. Graceful shutdown sequence
1536///
1537/// # Defensive Coding
1538///
1539/// All operations include:
1540/// - Input validation and sanitization
1541/// - Timeout handling for async operations
1542/// - Error recovery and logging
1543/// - Resource cleanup on errors
1544/// - Panic handling in critical sections
1545///
1546/// # FUTURE Enhancements
1547/// - Implement configuration hot-reload signal handling (SIGHUP)
1548/// - Add startup timeout and failure recovery
1549/// - Implement daemon mode forking (Unix)
1550/// - Add Windows service integration
1551/// - Implement crash recovery and restart
1552/// - Add pre-flight environment checks
1553/// - Implement feature flag system
1554async fn Main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
1555	// -------------------------------------------------------------------------
1556	// [Boot] [Telemetry] Bring up shared dual-pipe (PostHog + OTLP) so any
1557	// boot error captured from this point lands in the project. No-op in
1558	// release builds and when `Capture=false`. Idempotent.
1559	// -------------------------------------------------------------------------
1560	CommonLibrary::Telemetry::Initialize::Fn(CommonLibrary::Telemetry::Tier::Tier::Air).await;
1561
1562	// -------------------------------------------------------------------------
1563	// [Boot] [Logging] Initialize logging system
1564	// -------------------------------------------------------------------------
1565	InitializeLogging();
1566
1567	dev_log!("lifecycle", "[Boot] ===========================================");
1568
1569	dev_log!("lifecycle", "[Boot] Starting Air Daemon");
1570
1571	dev_log!("lifecycle", "[Boot] ===========================================");
1572
1573	dev_log!(
1574		"lifecycle",
1575		"[Boot] Version: {} ({})",
1576		env!("CARGO_PKG_VERSION"),
1577		env!("CARGO_PKG_NAME")
1578	);
1579
1580	let build_timestamp = env::var("BUILD_TIMESTAMP").unwrap_or_else(|_| "unknown".to_string());
1581
1582	dev_log!("lifecycle", "[Boot] Build: {}", build_timestamp);
1583
1584	dev_log!(
1585		"lifecycle",
1586		"[Boot] Target: {}-{}",
1587		std::env::consts::OS,
1588		std::env::consts::ARCH
1589	);
1590
1591	// -------------------------------------------------------------------------
1592	// [Boot] [Environment] Validate environment before starting
1593	// -------------------------------------------------------------------------
1594	dev_log!("lifecycle", "[Boot] Validating environment...");
1595
1596	if let Err(e) = validate_environment().await {
1597		dev_log!("lifecycle", "error: [Boot] Environment validation failed: {}", e);
1598
1599		return Err(format!("Environment validation failed: {}", e).into());
1600	}
1601
1602	dev_log!("lifecycle", "[Boot] Environment validation passed");
1603
1604	// -------------------------------------------------------------------------
1605	// [Boot] [Observability] Initialize metrics and tracing
1606	// -------------------------------------------------------------------------
1607	Trace!("[Boot] [Observability] Initializing observability systems...");
1608
1609	// Initialize metrics with error handling
1610	if let Err(e) = Metrics::InitializeMetrics() {
1611		dev_log!("lifecycle", "error: [Boot] Failed to initialize metrics: {}", e);
1612
1613		// Non-fatal: continue without metrics
1614	} else {
1615		dev_log!("lifecycle", "[Boot] [Observability] Metrics system initialized");
1616	}
1617
1618	// Initialize tracing with error handling
1619	if let Err(e) = Tracing::initialize_tracing(None) {
1620		dev_log!("lifecycle", "error: [Boot] Failed to initialize tracing: {}", e);
1621
1622		// Non-fatal: continue without tracing
1623	} else {
1624		dev_log!("lifecycle", "[Boot] [Observability] Tracing system initialized");
1625	}
1626
1627	dev_log!("lifecycle", "[Boot] [Observability] Observability systems initialized");
1628
1629	// -------------------------------------------------------------------------
1630	// [Boot] [Args] Parse command line arguments
1631	// -------------------------------------------------------------------------
1632	Trace!("[Boot] [Args] Parsing command line arguments...");
1633
1634	let (config_path, bind_address, cli_command) = ParseArguments();
1635
1636	// If a CLI command was provided, handle it and exit
1637	if let Some(cmd) = cli_command {
1638		dev_log!("lifecycle", "[Boot] CLI command detected, executing...");
1639
1640		let result = HandleCommand(cmd).await;
1641
1642		match &result {
1643			Ok(_) => {
1644				dev_log!("lifecycle", "[Boot] CLI command completed successfully");
1645
1646				std::process::exit(0);
1647			},
1648
1649			Err(e) => {
1650				dev_log!("lifecycle", "error: [Boot] CLI command failed: {}", e);
1651
1652				std::process::exit(1);
1653			},
1654		}
1655	}
1656
1657	// -------------------------------------------------------------------------
1658	// [Boot] [Configuration] Load configuration
1659	// -------------------------------------------------------------------------
1660	Trace!("[Boot] [Configuration] Loading configuration...");
1661
1662	let config_manager = match ConfigurationManager::New(config_path) {
1663		Ok(cm) => cm,
1664
1665		Err(e) => {
1666			dev_log!("lifecycle", "error: [Boot] Failed to create configuration manager: {}", e);
1667
1668			return Err(format!("Configuration manager initialization failed: {}", e).into());
1669		},
1670	};
1671
1672	// Load configuration with timeout
1673	let configuration:std::sync::Arc<AirLibrary::Configuration::AirConfiguration> =
1674		match tokio::time::timeout(Duration::from_secs(10), config_manager.LoadConfiguration()).await {
1675			Ok(Ok(config)) => {
1676				dev_log!("lifecycle", "[Boot] [Configuration] Configuration loaded successfully");
1677
1678				std::sync::Arc::new(config)
1679			},
1680
1681			Ok(Err(e)) => {
1682				dev_log!("lifecycle", "error: [Boot] Failed to load configuration: {}", e);
1683
1684				return Err(format!("Configuration load failed: {}", e).into());
1685			},
1686
1687			Err(_) => {
1688				dev_log!("lifecycle", "error: [Boot] Configuration load timed out");
1689
1690				return Err("Configuration load timed out".into());
1691			},
1692		};
1693
1694	// Validate critical configuration values
1695	validate_configuration(&configuration)?;
1696
1697	// -------------------------------------------------------------------------
1698	// [Boot] [Daemon] Initialize daemon lifecycle management
1699	// -------------------------------------------------------------------------
1700	Trace!("[Boot] [Daemon] Initializing daemon lifecycle management...");
1701
1702	let daemon_manager = match DaemonManager::New(None) {
1703		Ok(dm) => dm,
1704
1705		Err(e) => {
1706			dev_log!("lifecycle", "error: [Boot] Failed to create daemon manager: {}", e);
1707
1708			return Err(format!("Daemon manager initialization failed: {}", e).into());
1709		},
1710	};
1711
1712	// Acquire daemon lock to ensure single instance with timeout
1713	match tokio::time::timeout(Duration::from_secs(5), daemon_manager.AcquireLock()).await {
1714		Ok(Ok(_)) => {
1715			dev_log!("lifecycle", "[Boot] [Daemon] Daemon lock acquired successfully");
1716		},
1717
1718		Ok(Err(e)) => {
1719			dev_log!("lifecycle", "error: [Boot] Failed to acquire daemon lock: {}", e);
1720
1721			dev_log!("lifecycle", "error: [Boot] Another instance may already be running");
1722
1723			return Err(format!("Daemon lock acquisition failed: {}", e).into());
1724		},
1725
1726		Err(_) => {
1727			dev_log!("lifecycle", "error: [Boot] Daemon lock acquisition timed out");
1728
1729			return Err("Daemon lock acquisition timed out".into());
1730		},
1731	}
1732
1733	// -------------------------------------------------------------------------
1734	// [Boot] [Health] Initialize health check system
1735	// -------------------------------------------------------------------------
1736	Trace!("[Boot] [Health] Initializing health check system...");
1737
1738	let health_manager:std::sync::Arc<HealthCheckManager> = Arc::new(HealthCheckManager::new(None));
1739
1740	dev_log!("lifecycle", "[Boot] [Health] Health check system initialized");
1741
1742	// -------------------------------------------------------------------------
1743	// [Boot] [State] Initialize application state
1744	// -------------------------------------------------------------------------
1745	Trace!("[Boot] [State] Initializing application state...");
1746
1747	let AppState:std::sync::Arc<ApplicationState> =
1748		match tokio::time::timeout(Duration::from_secs(10), ApplicationState::New(configuration.clone())).await {
1749			Ok(Ok(state)) => {
1750				dev_log!("lifecycle", "[Boot] [State] Application state initialized");
1751
1752				Arc::new(state)
1753			},
1754
1755			Ok(Err(e)) => {
1756				dev_log!("lifecycle", "error: [Boot] Failed to initialize application state: {}", e);
1757
1758				// Attempt to release lock before returning
1759				let _ = daemon_manager.ReleaseLock().await;
1760
1761				return Err(format!("Application state initialization failed: {}", e).into());
1762			},
1763
1764			Err(_) => {
1765				dev_log!("lifecycle", "error: [Boot] Application state initialization timed out");
1766
1767				let _ = daemon_manager.ReleaseLock().await;
1768
1769				return Err("Application state initialization timed out".into());
1770			},
1771		};
1772
1773	// -------------------------------------------------------------------------
1774	// [Boot] [Services] Initialize core services
1775	// -------------------------------------------------------------------------
1776	Trace!("[Boot] [Services] Initializing core services...");
1777
1778	// Initialize each service with error handling
1779	let auth_service:std::sync::Arc<AuthenticationService> =
1780		match tokio::time::timeout(Duration::from_secs(10), AuthenticationService::new(AppState.clone())).await {
1781			Ok(Ok(svc)) => Arc::new(svc),
1782
1783			Ok(Err(e)) => {
1784				dev_log!("lifecycle", "error: [Boot] Failed to initialize authentication service: {}", e);
1785
1786				return Err(format!("Authentication service initialization failed: {}", e).into());
1787			},
1788
1789			Err(_) => {
1790				dev_log!("lifecycle", "error: [Boot] Authentication service initialization timed out");
1791
1792				return Err("Authentication service initialization timed out".into());
1793			},
1794		};
1795
1796	let update_manager:std::sync::Arc<UpdateManager> =
1797		match tokio::time::timeout(Duration::from_secs(10), UpdateManager::new(AppState.clone())).await {
1798			Ok(Ok(svc)) => Arc::new(svc),
1799
1800			Ok(Err(e)) => {
1801				dev_log!("lifecycle", "error: [Boot] Failed to initialize update manager: {}", e);
1802
1803				return Err(format!("Update manager initialization failed: {}", e).into());
1804			},
1805
1806			Err(_) => {
1807				dev_log!("lifecycle", "error: [Boot] Update manager initialization timed out");
1808
1809				return Err("Update manager initialization timed out".into());
1810			},
1811		};
1812
1813	let download_manager:std::sync::Arc<DownloadManager> =
1814		match tokio::time::timeout(Duration::from_secs(10), DownloadManager::new(AppState.clone())).await {
1815			Ok(Ok(svc)) => Arc::new(svc),
1816
1817			Ok(Err(e)) => {
1818				dev_log!("lifecycle", "error: [Boot] Failed to initialize download manager: {}", e);
1819
1820				return Err(format!("Download manager initialization failed: {}", e).into());
1821			},
1822
1823			Err(_) => {
1824				dev_log!("lifecycle", "error: [Boot] Download manager initialization timed out");
1825
1826				return Err("Download manager initialization timed out".into());
1827			},
1828		};
1829
1830	let file_indexer:std::sync::Arc<FileIndexer> =
1831		match tokio::time::timeout(Duration::from_secs(10), FileIndexer::new(AppState.clone())).await {
1832			Ok(Ok(svc)) => Arc::new(svc),
1833
1834			Ok(Err(e)) => {
1835				dev_log!("lifecycle", "error: [Boot] Failed to initialize file indexer: {}", e);
1836
1837				return Err(format!("File indexer initialization failed: {}", e).into());
1838			},
1839
1840			Err(_) => {
1841				dev_log!("lifecycle", "error: [Boot] File indexer initialization timed out");
1842
1843				return Err("File indexer initialization timed out".into());
1844			},
1845		};
1846
1847	dev_log!("lifecycle", "[Boot] [Services] All core services initialized successfully");
1848
1849	// -------------------------------------------------------------------------
1850	// [Boot] [Health] Register services for health monitoring
1851	// -------------------------------------------------------------------------
1852	Trace!("[Boot] [Health] Registering services for health monitoring...");
1853
1854	// Register each service with validation
1855	let service_registrations = vec![
1856		("authentication", HealthCheckLevel::Functional),
1857		("updates", HealthCheckLevel::Functional),
1858		("downloader", HealthCheckLevel::Functional),
1859		("indexing", HealthCheckLevel::Functional),
1860		("grpc", HealthCheckLevel::Responsive),
1861		("connections", HealthCheckLevel::Alive),
1862	];
1863
1864	for (service_name, level) in service_registrations {
1865		match tokio::time::timeout(
1866			Duration::from_secs(5),
1867			health_manager.RegisterService(service_name.to_string(), level),
1868		)
1869		.await
1870		{
1871			Ok(result) => {
1872				match result {
1873					Ok(_) => {
1874						dev_log!("lifecycle", "[Boot] [Health] Registered service: {}", service_name);
1875					},
1876
1877					Err(e) => {
1878						dev_log!("lifecycle", "warn: [Boot] Failed to register service {}: {}", service_name, e);
1879
1880						// Non-fatal: continue without this service's health
1881						// checks
1882					},
1883				}
1884			},
1885
1886			Err(_) => {
1887				dev_log!("lifecycle", "warn: [Boot] Service registration timed out: {}", service_name);
1888			},
1889		}
1890	}
1891
1892	dev_log!("lifecycle", "[Boot] [Health] Service health monitoring configured");
1893
1894	// -------------------------------------------------------------------------
1895	// [Boot] [Vine] Initialize gRPC server
1896	// -------------------------------------------------------------------------
1897	Trace!("[Boot] [Vine] Initializing gRPC server...");
1898
1899	// Parse bind address with validation
1900	let bind_addr:SocketAddr = match bind_address {
1901		Some(addr) => {
1902			match addr.parse() {
1903				Ok(parsed) => {
1904					dev_log!("lifecycle", "[Boot] [Vine] Using custom bind address: {}", parsed);
1905
1906					parsed
1907				},
1908
1909				Err(e) => {
1910					dev_log!("lifecycle", "error: [Boot] Invalid bind address '{}': {}", addr, e);
1911
1912					return Err(format!("Invalid bind address: {}", e).into());
1913				},
1914			}
1915		},
1916
1917		None => {
1918			match DefaultBindAddress.parse() {
1919				Ok(parsed) => parsed,
1920
1921				Err(e) => {
1922					dev_log!(
1923						"lifecycle",
1924						"error: [Boot] Invalid default bind address '{}': {}",
1925						DefaultBindAddress,
1926						e
1927					);
1928
1929					return Err(format!("Invalid default bind address: {}", e).into());
1930				},
1931			}
1932		},
1933	};
1934
1935	dev_log!("lifecycle", "[Boot] [Vine] Configuring gRPC server on {}", bind_addr);
1936
1937	// Create gRPC service implementation with all dependencies
1938	let vine_service = AirVinegRPCService::new(
1939		AppState.clone(),
1940		auth_service.clone(),
1941		update_manager.clone(),
1942		download_manager.clone(),
1943		file_indexer.clone(),
1944	);
1945
1946	// Create a oneshot channel to signal server shutdown
1947	let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>();
1948
1949	// Spawn the tonic gRPC server with panic handling
1950	let server_handle:tokio::task::JoinHandle<Result<(), Box<dyn std::error::Error + Send + Sync>>> =
1951		tokio::spawn(async move {
1952			dev_log!("lifecycle", "[Vine] Starting gRPC server on {}", bind_addr);
1953
1954			let svc = AirServiceServer::new(vine_service);
1955
1956			let server = tonic::transport::Server::builder()
1957				.add_service(svc)
1958				.serve_with_shutdown(bind_addr, async {
1959					// Wait for shutdown signal from main
1960					let _ = shutdown_rx.await;
1961					dev_log!("lifecycle", "[Vine] Shutdown signal received, stopping server...");
1962				});
1963
1964			dev_log!("lifecycle", "[Vine] gRPC server listening on {}", bind_addr);
1965
1966			match server.await {
1967				Ok(_) => {
1968					dev_log!("lifecycle", "[Vine] gRPC server stopped cleanly");
1969					Ok(())
1970				},
1971				Err(e) => {
1972					dev_log!("grpc", "error: [Vine] gRPC server error: {}", e);
1973					Err(e.into())
1974				},
1975			}
1976		});
1977
1978	// Wait a bit for the server to start
1979	tokio::time::sleep(Duration::from_millis(100)).await;
1980
1981	// Check if server task panicked or failed early
1982	if server_handle.is_finished() {
1983		dev_log!("lifecycle", "error: [Boot] gRPC server failed to start");
1984
1985		let _ = daemon_manager.ReleaseLock().await;
1986
1987		return Err("gRPC server failed to start".into());
1988	}
1989
1990	// -------------------------------------------------------------------------
1991	// [Boot] [Monitoring] Start background monitoring tasks
1992	// -------------------------------------------------------------------------
1993	Trace!("[Boot] [Monitoring] Starting background monitoring tasks...");
1994
1995	// Start connection monitoring background task
1996	let connection_monitor_handle:tokio::task::JoinHandle<()> = tokio::spawn({
1997		let AppState = AppState.clone();
1998		let health_manager = health_manager.clone();
1999		async move {
2000			let mut interval = interval(Duration::from_secs(60)); // Check every minute
2001			loop {
2002				interval.tick().await;
2003
2004				// Update resource usage with error handling
2005				if let Err(e) = AppState.UpdateResourceUsage().await {
2006					dev_log!("lifecycle", "warn: [ConnectionMonitor] Failed to update resource usage: {}", e);
2007				}
2008
2009				// Get resource metrics
2010				let resources = AppState.GetResourceUsage().await;
2011
2012				// Record metrics
2013				let metrics_collector = Metrics::GetMetrics();
2014				metrics_collector.UpdateResourceMetrics(
2015					(resources.MemoryUsageMb * 1024.0 * 1024.0) as u64, // Convert MB to bytes
2016					resources.CPUUsagePercent,
2017					AppState.GetActiveConnectionCount().await as u64,
2018					0, // Thread count: Requires tokio runtime metrics integration
2019				);
2020
2021				// Clean up stale connections (5 minute timeout)
2022				if let Err(e) = AppState.CleanupStaleConnections(300).await {
2023					dev_log!(
2024						"lifecycle",
2025						"warn: [ConnectionMonitor] Failed to cleanup stale connections: {}",
2026						e
2027					);
2028				}
2029
2030				// Perform health checks
2031				match health_manager.CheckService("connections").await {
2032					Ok(_) => {},
2033					Err(e) => {
2034						dev_log!("lifecycle", "warn: [ConnectionMonitor] Health check failed: {}", e);
2035
2036						// Record metrics for failed health check
2037						let metrics_collector = Metrics::GetMetrics();
2038						metrics_collector.RecordRequestFailure("health_check_failed", 0.0);
2039					},
2040				}
2041
2042				dev_log!(
2043					"lifecycle",
2044					"[ConnectionMonitor] Active connections: {}",
2045					AppState.GetActiveConnectionCount().await
2046				);
2047			}
2048		}
2049	});
2050
2051	// Register background task with error handling
2052	if let Err(e) = AppState.RegisterBackgroundTask(connection_monitor_handle).await {
2053		dev_log!("lifecycle", "warn: [Boot] Failed to register connection monitor: {}", e);
2054
2055		// Non-fatal: continue monitoring may not be tracked
2056	}
2057
2058	// Start health monitoring background task
2059	let health_monitor_handle:tokio::task::JoinHandle<()> = tokio::spawn({
2060		let health_manager = health_manager.clone();
2061		async move {
2062			let mut interval = interval(Duration::from_secs(30)); // Check every 30 seconds
2063			loop {
2064				interval.tick().await;
2065
2066				// Perform comprehensive health checks
2067				let services = ["authentication", "updates", "downloader", "indexing", "grpc"];
2068				for service in services.iter() {
2069					if let Err(e) = health_manager.CheckService(service).await {
2070						dev_log!("lifecycle", "warn: [HealthMonitor] Health check failed for {}: {}", service, e);
2071					}
2072				}
2073
2074				// Log overall health status
2075				let overall_health = health_manager.GetOverallHealth().await;
2076				dev_log!("lifecycle", "[HealthMonitor] Overall health: {:?}", overall_health);
2077			}
2078		}
2079	});
2080
2081	// Register health monitoring task with error handling
2082	if let Err(e) = AppState.RegisterBackgroundTask(health_monitor_handle).await {
2083		dev_log!("lifecycle", "warn: [Boot] Failed to register health monitor: {}", e);
2084
2085		// Non-fatal: continue monitoring may not be tracked
2086	}
2087
2088	// -------------------------------------------------------------------------
2089	// [Boot] [Startup] Start services
2090	// -------------------------------------------------------------------------
2091	Trace!("[Boot] [Startup] Starting background services...");
2092
2093	// Start background tasks for services that support it
2094	let _ = auth_service.StartBackgroundTasks().await?;
2095
2096	let _ = update_manager.StartBackgroundTasks().await?;
2097
2098	let _ = download_manager.StartBackgroundTasks().await?;
2099
2100	// FileIndexer does not have background tasks, it's used directly
2101	let _indexing_handle = None::<tokio::task::JoinHandle<()>>;
2102
2103	dev_log!("lifecycle", "[Boot] [Startup] All services started successfully");
2104
2105	// -------------------------------------------------------------------------
2106	// [Runtime] Run server and wait for shutdown
2107	// -------------------------------------------------------------------------
2108	dev_log!("lifecycle", "===========================================");
2109
2110	dev_log!("lifecycle", "[Runtime] Air Daemon is now running");
2111
2112	dev_log!("lifecycle", "[Runtime] Listening on {} for Mountain connections", bind_addr);
2113
2114	dev_log!("lifecycle", "[Runtime] Protocol Version: {}", ProtocolVersion);
2115
2116	dev_log!("lifecycle", "[Runtime] Cocoon Port: 50052");
2117
2118	dev_log!("lifecycle", "===========================================");
2119
2120	dev_log!("lifecycle", "");
2121
2122	dev_log!("lifecycle", "Running. Press Ctrl+C to stop.");
2123
2124	dev_log!("lifecycle", "");
2125
2126	// Wait for shutdown signal
2127	WaitForShutdownSignal().await;
2128
2129	// Signal gRPC server to shut down
2130	dev_log!("lifecycle", "[Shutdown] Signaling gRPC server to stop...");
2131
2132	let _ = shutdown_tx.send(());
2133
2134	// Await the server task to finish with timeout
2135	match tokio::time::timeout(Duration::from_secs(30), server_handle).await {
2136		Ok(Ok(Ok(_))) => {
2137			dev_log!("lifecycle", "[Shutdown] gRPC server stopped normally");
2138		},
2139
2140		Ok(Ok(Err(e))) => {
2141			dev_log!("lifecycle", "warn: [Shutdown] gRPC server stopped with error: {}", e);
2142		},
2143
2144		Ok(Err(e)) => {
2145			dev_log!("lifecycle", "warn: [Shutdown] gRPC server task panicked: {:?}", e);
2146		},
2147
2148		Err(_) => {
2149			dev_log!("lifecycle", "warn: [Shutdown] gRPC server shutdown timed out");
2150		},
2151	}
2152
2153	// -------------------------------------------------------------------------
2154	// [Shutdown] Graceful shutdown
2155	// -------------------------------------------------------------------------
2156	dev_log!("lifecycle", "===========================================");
2157
2158	dev_log!("lifecycle", "[Shutdown] Initiating graceful shutdown...");
2159
2160	dev_log!("lifecycle", "===========================================");
2161
2162	// Stop all background tasks with timeout
2163	dev_log!("lifecycle", "[Shutdown] Stopping background tasks...");
2164
2165	if let Err(_) =
2166		tokio::time::timeout(Duration::from_secs(10), async { AppState.StopAllBackgroundTasks().await }).await
2167	{
2168		dev_log!("lifecycle", "warn: [Shutdown] Background tasks stop timed out or failed");
2169	}
2170
2171	// Stop background services
2172	dev_log!("lifecycle", "[Shutdown] Stopping background services...");
2173
2174	auth_service.StopBackgroundTasks().await;
2175
2176	update_manager.StopBackgroundTasks().await;
2177
2178	download_manager.StopBackgroundTasks().await;
2179
2180	// Log final statistics
2181	dev_log!("lifecycle", "[Shutdown] Collecting final statistics...");
2182
2183	let metrics = AppState.GetMetrics().await;
2184
2185	let resources = AppState.GetResourceUsage().await;
2186
2187	let health_stats:HealthStatistics = health_manager.GetHealthStatistics().await;
2188
2189	// Get final metrics data
2190	let metrics_data = Metrics::GetMetrics().GetMetricsData();
2191
2192	dev_log!("lifecycle", "===========================================");
2193
2194	dev_log!("lifecycle", "[Shutdown] Final Statistics");
2195
2196	dev_log!("lifecycle", "===========================================");
2197
2198	dev_log!("lifecycle", "[Shutdown] Requests:");
2199
2200	dev_log!("lifecycle", " - Successful: {}", metrics.SuccessfulRequest);
2201
2202	dev_log!("lifecycle", " - Failed: {}", metrics.FailedRequest);
2203
2204	dev_log!("lifecycle", "[Shutdown] Metrics:");
2205
2206	dev_log!("lifecycle", "  - Success rate: {:.2}%", metrics_data.SuccessRate());
2207
2208	dev_log!("lifecycle", "  - Error rate: {:.2}%", metrics_data.ErrorRate());
2209
2210	dev_log!("lifecycle", "[Shutdown] Resources:");
2211
2212	dev_log!("lifecycle", "  - Memory: {:.2} MB", resources.MemoryUsageMb);
2213
2214	dev_log!("lifecycle", "  - CPU: {:.2}%", resources.CPUUsagePercent);
2215
2216	dev_log!("lifecycle", "[Shutdown] Health:");
2217
2218	dev_log!("lifecycle", "  - Overall: {:.2}%", health_stats.OverallHealthPercentage());
2219
2220	dev_log!(
2221		"lifecycle",
2222		"  - Healthy services: {}/{}",
2223		health_stats.HealthyServices,
2224		health_stats.TotalServices
2225	);
2226
2227	dev_log!("lifecycle", "===========================================");
2228
2229	// Release daemon lock
2230	dev_log!("lifecycle", "[Shutdown] Releasing daemon lock...");
2231
2232	if let Err(e) = daemon_manager.ReleaseLock().await {
2233		dev_log!("lifecycle", "warn: [Shutdown] Failed to release daemon lock: {}", e);
2234	}
2235
2236	dev_log!("lifecycle", "[Shutdown] All services stopped");
2237
2238	dev_log!("lifecycle", "[Shutdown] Air Daemon has shut down gracefully");
2239
2240	dev_log!("lifecycle", "===========================================");
2241
2242	Ok(())
2243}
2244
2245/// Validate the runtime environment before starting the daemon
2246///
2247/// # FUTURE Enhancements
2248/// - Check disk space availability
2249/// - Validate network connectivity
2250/// - Check file system permissions
2251/// - Verify required executables exist
2252/// - Validate system resources (CPU, RAM)
2253async fn validate_environment() -> Result<(), String> {
2254	// Validate OS and architecture
2255	dev_log!(
2256		"lifecycle",
2257		"[Environment] OS: {}, Arch: {}",
2258		std::env::consts::OS,
2259		std::env::consts::ARCH
2260	);
2261
2262	// Validate required environment variables
2263	if let Ok(home) = std::env::var("HOME") {
2264		if home.is_empty() {
2265			return Err("HOME environment variable is not set".to_string());
2266		}
2267	}
2268
2269	// Verify we can create lock files
2270	let lock_path = "/tmp/Air-test-lock.tmp";
2271
2272	if std::fs::write(lock_path, b"test").is_err() {
2273		return Err("Cannot write to /tmp directory".to_string());
2274	}
2275
2276	let _ = std::fs::remove_file(lock_path);
2277
2278	Ok(())
2279}
2280
2281/// Validate critical configuration values
2282///
2283/// # FUTURE Enhancements
2284/// - Add comprehensive configuration validation
2285/// - Validate port ranges
2286/// - Validate timeout values
2287/// - Validate file paths exist or are creatable
2288/// - Validate URLs are properly formatted
2289fn validate_configuration(_config:&AirConfiguration) -> Result<(), String> {
2290	// Add configuration validation logic here
2291	dev_log!("lifecycle", "[Config] Configuration passed basic validation");
2292
2293	Ok(())
2294}
2295
2296#[tokio::main]
2297async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { Main().await }