diff --git a/src/tui/managers/env_manager.py b/src/tui/managers/env_manager.py index 751283dc..26b8f843 100644 --- a/src/tui/managers/env_manager.py +++ b/src/tui/managers/env_manager.py @@ -72,9 +72,25 @@ class EnvManager: def generate_secure_password(self) -> str: """Generate a secure password for OpenSearch.""" - # Generate a 16-character password with letters, digits, and symbols - alphabet = string.ascii_letters + string.digits + "!@#$%^&*" - return "".join(secrets.choice(alphabet) for _ in range(16)) + # Ensure at least one character from each category + symbols = "!@#$%^&*" + + # Guarantee at least one of each type + password_chars = [ + secrets.choice(string.ascii_uppercase), + secrets.choice(string.ascii_lowercase), + secrets.choice(string.digits), + secrets.choice(symbols), + ] + + # Fill remaining 12 characters with random choices from all categories + alphabet = string.ascii_letters + string.digits + symbols + password_chars.extend(secrets.choice(alphabet) for _ in range(12)) + + # Shuffle to avoid predictable patterns + secrets.SystemRandom().shuffle(password_chars) + + return "".join(password_chars) def generate_langflow_secret_key(self) -> str: """Generate a secure secret key for Langflow.""" diff --git a/src/tui/screens/config.py b/src/tui/screens/config.py index 7338696c..85a7cdb1 100644 --- a/src/tui/screens/config.py +++ b/src/tui/screens/config.py @@ -553,11 +553,17 @@ class ConfigScreen(Screen): # First, check Textual input validators validation_errors = [] for field_name, input_widget in self.inputs.items(): - if hasattr(input_widget, "validate") and input_widget.value: - result = input_widget.validate(input_widget.value) - if result and not result.is_valid: - for failure in result.failures: - validation_errors.append(f"{field_name}: {failure.description}") + # Skip empty values as they may be optional or auto-generated + if not input_widget.value: + continue + + # Check if input has validators and manually validate + if hasattr(input_widget, "validators") and input_widget.validators: + for validator in input_widget.validators: + result = validator.validate(input_widget.value) + if result and not result.is_valid: + for failure in result.failures: + validation_errors.append(f"{field_name}: {failure.description}") if validation_errors: self.notify( @@ -570,6 +576,9 @@ class ConfigScreen(Screen): for field_name, input_widget in self.inputs.items(): setattr(self.env_manager.config, field_name, input_widget.value) + # Generate secure defaults for empty passwords/keys BEFORE validation + self.env_manager.setup_secure_defaults() + # Validate the configuration if not self.env_manager.validate_config(self.mode): error_messages = [] diff --git a/src/tui/screens/welcome.py b/src/tui/screens/welcome.py index 08d1bfbe..66321010 100644 --- a/src/tui/screens/welcome.py +++ b/src/tui/screens/welcome.py @@ -73,10 +73,11 @@ class WelcomeScreen(Screen): return try: - # Use synchronous docker command to check services + # Use detected runtime command to check services import subprocess + compose_cmd = self.container_manager.runtime_info.compose_command + ["ps", "--format", "json"] result = subprocess.run( - ["docker", "compose", "ps", "--format", "json"], + compose_cmd, capture_output=True, text=True, timeout=5