# ADR-052: Configuration System Architecture ## Status Accepted ## Context StarPunk v1.1.1 "Polish" introduces several configurable features to improve production readiness and user experience. Currently, configuration values are hardcoded throughout the application, making customization difficult. We need a consistent, simple approach to configuration management that: 1. Maintains backward compatibility 2. Provides sensible defaults 3. Follows Python best practices 4. Minimizes complexity 5. Supports environment-based configuration ## Decision We will implement a centralized configuration system using environment variables with fallback defaults, managed through a single configuration module. ### Configuration Architecture ``` Environment Variables (highest priority) ↓ Configuration File (optional, .env) ↓ Default Values (in code) ``` ### Configuration Module Structure Location: `starpunk/config.py` Categories: 1. **Search Configuration** - `SEARCH_ENABLED`: bool (default: True) - `SEARCH_TITLE_LENGTH`: int (default: 100) - `SEARCH_HIGHLIGHT_CLASS`: str (default: "highlight") - `SEARCH_MIN_SCORE`: float (default: 0.0) 2. **Performance Configuration** - `PERF_MONITORING_ENABLED`: bool (default: False) - `PERF_SLOW_QUERY_THRESHOLD`: float (default: 1.0 seconds) - `PERF_LOG_QUERIES`: bool (default: False) - `PERF_MEMORY_TRACKING`: bool (default: False) 3. **Database Configuration** - `DB_CONNECTION_POOL_SIZE`: int (default: 5) - `DB_CONNECTION_TIMEOUT`: float (default: 10.0) - `DB_WAL_MODE`: bool (default: True) - `DB_BUSY_TIMEOUT`: int (default: 5000 ms) 4. **Logging Configuration** - `LOG_LEVEL`: str (default: "INFO") - `LOG_FORMAT`: str (default: structured JSON) - `LOG_FILE_PATH`: str (default: None) - `LOG_ROTATION`: bool (default: False) 5. **Production Configuration** - `SESSION_TIMEOUT`: int (default: 86400 seconds) - `HEALTH_CHECK_DETAILED`: bool (default: False) - `ERROR_DETAILS_IN_RESPONSE`: bool (default: False) ### Implementation Pattern ```python # starpunk/config.py import os from typing import Any, Optional class Config: """Centralized configuration management""" @staticmethod def get_bool(key: str, default: bool = False) -> bool: """Get boolean configuration value""" value = os.environ.get(key, "").lower() if value in ("true", "1", "yes", "on"): return True elif value in ("false", "0", "no", "off"): return False return default @staticmethod def get_int(key: str, default: int) -> int: """Get integer configuration value""" try: return int(os.environ.get(key, default)) except (ValueError, TypeError): return default @staticmethod def get_float(key: str, default: float) -> float: """Get float configuration value""" try: return float(os.environ.get(key, default)) except (ValueError, TypeError): return default @staticmethod def get_str(key: str, default: str = "") -> str: """Get string configuration value""" return os.environ.get(key, default) # Configuration instances SEARCH_ENABLED = Config.get_bool("STARPUNK_SEARCH_ENABLED", True) SEARCH_TITLE_LENGTH = Config.get_int("STARPUNK_SEARCH_TITLE_LENGTH", 100) # ... etc ``` ### Environment Variable Naming Convention All StarPunk environment variables are prefixed with `STARPUNK_` to avoid conflicts: - `STARPUNK_SEARCH_ENABLED` - `STARPUNK_PERF_MONITORING_ENABLED` - `STARPUNK_DB_CONNECTION_POOL_SIZE` - etc. ## Rationale ### Why Environment Variables? 1. **Standard Practice**: Follows 12-factor app methodology 2. **Container Friendly**: Works well with Docker/Kubernetes 3. **No Dependencies**: Built into Python stdlib 4. **Security**: Sensitive values not in code 5. **Simple**: No complex configuration parsing ### Why Not Alternative Approaches? **YAML/TOML/INI Files**: - Adds parsing complexity - Requires file management - Not as container-friendly - Additional dependency **Database Configuration**: - Circular dependency (need config to connect to DB) - Makes deployment more complex - Not suitable for bootstrap configuration **Python Config Files**: - Security risk if user-editable - Import complexity - Not standard practice ### Why Centralized Module? 1. **Single Source**: All configuration in one place 2. **Type Safety**: Helper methods ensure correct types 3. **Documentation**: Self-documenting defaults 4. **Testing**: Easy to mock for tests 5. **Validation**: Can add validation logic centrally ## Consequences ### Positive 1. **Backward Compatible**: All existing deployments continue working with defaults 2. **Production Ready**: Ops teams can configure without code changes 3. **Simple Implementation**: ~100 lines of code 4. **Testable**: Easy to test different configurations 5. **Documented**: Configuration options clear in one file 6. **Flexible**: Can override any setting via environment ### Negative 1. **Environment Pollution**: Many environment variables in production 2. **No Validation**: Invalid values fall back to defaults silently 3. **No Hot Reload**: Requires restart to apply changes 4. **Limited Types**: Only primitive types supported ### Mitigations 1. Use `.env` files for local development 2. Add startup configuration validation 3. Log configuration values at startup (non-sensitive only) 4. Document all configuration options clearly ## Alternatives Considered ### 1. Pydantic Settings **Pros**: Type validation, .env support, modern **Cons**: New dependency, overengineered for our needs **Decision**: Too complex for v1.1.1 patch release ### 2. Click Configuration **Pros**: Already using Click, integrated CLI options **Cons**: CLI args not suitable for all config, complex precedence **Decision**: Keep CLI and config separate ### 3. ConfigParser (INI files) **Pros**: Python stdlib, familiar format **Cons**: File management complexity, not container-native **Decision**: Environment variables are simpler ### 4. No Configuration System **Pros**: Simplest possible **Cons**: No production flexibility, poor UX **Decision**: v1.1.1 specifically targets production readiness ## Implementation Notes 1. Configuration module loads at import time 2. Values are immutable after startup 3. Invalid values log warnings but use defaults 4. Sensitive values (tokens, keys) never logged 5. Configuration documented in deployment guide 6. Example `.env.example` file provided ## Testing Strategy 1. Unit tests mock environment variables 2. Integration tests verify default behavior 3. Configuration validation tests 4. Performance impact tests (configuration overhead) ## Migration Path No migration required - all configuration has sensible defaults that match current behavior. ## References - [The Twelve-Factor App - Config](https://12factor.net/config) - [Python os.environ](https://docs.python.org/3/library/os.html#os.environ) - [Docker Environment Variables](https://docs.docker.com/compose/environment-variables/) ## Document History - 2025-11-25: Initial draft for v1.1.1 release planning