288 lines
11 KiB
Python
288 lines
11 KiB
Python
"""
|
|
Configuration management for HCFS API.
|
|
|
|
Handles environment-based configuration with validation and defaults.
|
|
"""
|
|
|
|
import os
|
|
from typing import List, Optional, Dict, Any
|
|
from pydantic import BaseSettings, Field, validator
|
|
from pathlib import Path
|
|
|
|
|
|
class DatabaseConfig(BaseSettings):
|
|
"""Database configuration settings."""
|
|
|
|
# SQLite settings
|
|
db_path: str = Field(default="hcfs_production.db", description="Path to SQLite database")
|
|
vector_db_path: str = Field(default="hcfs_vectors_production.db", description="Path to vector database")
|
|
|
|
# Connection settings
|
|
pool_size: int = Field(default=10, description="Database connection pool size")
|
|
max_overflow: int = Field(default=20, description="Maximum connection overflow")
|
|
pool_timeout: int = Field(default=30, description="Connection pool timeout in seconds")
|
|
|
|
# Performance settings
|
|
cache_size: int = Field(default=1000, description="Database cache size")
|
|
enable_wal_mode: bool = Field(default=True, description="Enable SQLite WAL mode")
|
|
synchronous_mode: str = Field(default="NORMAL", description="SQLite synchronous mode")
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_DB_"
|
|
|
|
|
|
class EmbeddingConfig(BaseSettings):
|
|
"""Embedding system configuration."""
|
|
|
|
# Model settings
|
|
model_name: str = Field(default="mini", description="Embedding model to use")
|
|
cache_size: int = Field(default=2000, description="Embedding cache size")
|
|
batch_size: int = Field(default=32, description="Batch processing size")
|
|
|
|
# Performance settings
|
|
max_workers: int = Field(default=4, description="Maximum worker threads")
|
|
timeout_seconds: int = Field(default=300, description="Operation timeout")
|
|
|
|
# Vector database settings
|
|
vector_dimension: int = Field(default=384, description="Vector dimension")
|
|
similarity_threshold: float = Field(default=0.0, description="Default similarity threshold")
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_EMBEDDING_"
|
|
|
|
|
|
class APIConfig(BaseSettings):
|
|
"""API server configuration."""
|
|
|
|
# Server settings
|
|
host: str = Field(default="0.0.0.0", description="Server host")
|
|
port: int = Field(default=8000, description="Server port")
|
|
workers: int = Field(default=1, description="Number of worker processes")
|
|
|
|
# Security settings
|
|
secret_key: str = Field(default="dev-secret-key-change-in-production", description="JWT secret key")
|
|
algorithm: str = Field(default="HS256", description="JWT algorithm")
|
|
token_expire_minutes: int = Field(default=30, description="JWT token expiration time")
|
|
|
|
# CORS settings
|
|
cors_origins: List[str] = Field(
|
|
default=["http://localhost:3000", "http://localhost:8080"],
|
|
description="Allowed CORS origins"
|
|
)
|
|
cors_credentials: bool = Field(default=True, description="Allow credentials in CORS")
|
|
|
|
# Rate limiting
|
|
rate_limit_requests: int = Field(default=100, description="Requests per minute")
|
|
rate_limit_burst: int = Field(default=20, description="Burst requests allowed")
|
|
|
|
# Feature flags
|
|
enable_auth: bool = Field(default=True, description="Enable authentication")
|
|
enable_websocket: bool = Field(default=True, description="Enable WebSocket support")
|
|
enable_metrics: bool = Field(default=True, description="Enable Prometheus metrics")
|
|
enable_docs: bool = Field(default=True, description="Enable API documentation")
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_API_"
|
|
|
|
|
|
class MonitoringConfig(BaseSettings):
|
|
"""Monitoring and observability configuration."""
|
|
|
|
# Logging settings
|
|
log_level: str = Field(default="INFO", description="Logging level")
|
|
log_format: str = Field(default="json", description="Log format (json/text)")
|
|
log_file: Optional[str] = Field(default=None, description="Log file path")
|
|
|
|
# Metrics settings
|
|
metrics_enabled: bool = Field(default=True, description="Enable metrics collection")
|
|
metrics_port: int = Field(default=9090, description="Metrics server port")
|
|
|
|
# Health check settings
|
|
health_check_interval: int = Field(default=30, description="Health check interval in seconds")
|
|
health_check_timeout: int = Field(default=5, description="Health check timeout")
|
|
|
|
# Tracing settings
|
|
tracing_enabled: bool = Field(default=False, description="Enable distributed tracing")
|
|
tracing_sample_rate: float = Field(default=0.1, description="Tracing sample rate")
|
|
jaeger_endpoint: Optional[str] = Field(default=None, description="Jaeger endpoint")
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_MONITORING_"
|
|
|
|
|
|
class RedisConfig(BaseSettings):
|
|
"""Redis configuration for caching and rate limiting."""
|
|
|
|
# Connection settings
|
|
host: str = Field(default="localhost", description="Redis host")
|
|
port: int = Field(default=6379, description="Redis port")
|
|
db: int = Field(default=0, description="Redis database number")
|
|
password: Optional[str] = Field(default=None, description="Redis password")
|
|
|
|
# Pool settings
|
|
max_connections: int = Field(default=20, description="Maximum Redis connections")
|
|
socket_timeout: int = Field(default=5, description="Socket timeout in seconds")
|
|
|
|
# Cache settings
|
|
default_ttl: int = Field(default=3600, description="Default cache TTL in seconds")
|
|
key_prefix: str = Field(default="hcfs:", description="Redis key prefix")
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_REDIS_"
|
|
|
|
|
|
class SecurityConfig(BaseSettings):
|
|
"""Security configuration."""
|
|
|
|
# Authentication
|
|
require_auth: bool = Field(default=True, description="Require authentication")
|
|
api_key_header: str = Field(default="X-API-Key", description="API key header name")
|
|
|
|
# Rate limiting
|
|
rate_limit_enabled: bool = Field(default=True, description="Enable rate limiting")
|
|
rate_limit_storage: str = Field(default="memory", description="Rate limit storage (memory/redis)")
|
|
|
|
# HTTPS settings
|
|
force_https: bool = Field(default=False, description="Force HTTPS in production")
|
|
hsts_max_age: int = Field(default=31536000, description="HSTS max age")
|
|
|
|
# Request validation
|
|
max_request_size: int = Field(default=10 * 1024 * 1024, description="Maximum request size in bytes")
|
|
max_query_params: int = Field(default=100, description="Maximum query parameters")
|
|
|
|
# Content security
|
|
allowed_content_types: List[str] = Field(
|
|
default=["application/json", "application/x-www-form-urlencoded", "multipart/form-data"],
|
|
description="Allowed content types"
|
|
)
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_SECURITY_"
|
|
|
|
|
|
class HCFSConfig(BaseSettings):
|
|
"""Main HCFS configuration combining all subsystem configs."""
|
|
|
|
# Environment
|
|
environment: str = Field(default="development", description="Environment (development/staging/production)")
|
|
debug: bool = Field(default=False, description="Enable debug mode")
|
|
|
|
# Application info
|
|
app_name: str = Field(default="HCFS API", description="Application name")
|
|
app_version: str = Field(default="2.0.0", description="Application version")
|
|
app_description: str = Field(default="Context-Aware Hierarchical Context File System API", description="App description")
|
|
|
|
# Configuration file path
|
|
config_file: Optional[str] = Field(default=None, description="Path to configuration file")
|
|
|
|
# Subsystem configurations
|
|
database: DatabaseConfig = Field(default_factory=DatabaseConfig)
|
|
embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
|
|
api: APIConfig = Field(default_factory=APIConfig)
|
|
monitoring: MonitoringConfig = Field(default_factory=MonitoringConfig)
|
|
redis: RedisConfig = Field(default_factory=RedisConfig)
|
|
security: SecurityConfig = Field(default_factory=SecurityConfig)
|
|
|
|
class Config:
|
|
env_prefix = "HCFS_"
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
|
|
@validator('environment')
|
|
def validate_environment(cls, v):
|
|
"""Validate environment value."""
|
|
allowed = ['development', 'staging', 'production']
|
|
if v not in allowed:
|
|
raise ValueError(f'Environment must be one of: {allowed}')
|
|
return v
|
|
|
|
@validator('debug')
|
|
def validate_debug_in_production(cls, v, values):
|
|
"""Ensure debug is disabled in production."""
|
|
if values.get('environment') == 'production' and v:
|
|
raise ValueError('Debug mode cannot be enabled in production')
|
|
return v
|
|
|
|
def is_production(self) -> bool:
|
|
"""Check if running in production environment."""
|
|
return self.environment == 'production'
|
|
|
|
def is_development(self) -> bool:
|
|
"""Check if running in development environment."""
|
|
return self.environment == 'development'
|
|
|
|
def get_database_url(self) -> str:
|
|
"""Get database URL."""
|
|
return f"sqlite:///{self.database.db_path}"
|
|
|
|
def get_redis_url(self) -> str:
|
|
"""Get Redis URL."""
|
|
if self.redis.password:
|
|
return f"redis://:{self.redis.password}@{self.redis.host}:{self.redis.port}/{self.redis.db}"
|
|
return f"redis://{self.redis.host}:{self.redis.port}/{self.redis.db}"
|
|
|
|
def load_from_file(self, config_path: str) -> None:
|
|
"""Load configuration from YAML file."""
|
|
import yaml
|
|
|
|
config_file = Path(config_path)
|
|
if not config_file.exists():
|
|
raise FileNotFoundError(f"Configuration file not found: {config_path}")
|
|
|
|
with open(config_file, 'r') as f:
|
|
config_data = yaml.safe_load(f)
|
|
|
|
# Update configuration
|
|
for key, value in config_data.items():
|
|
if hasattr(self, key):
|
|
setattr(self, key, value)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Convert configuration to dictionary."""
|
|
return self.dict()
|
|
|
|
def save_to_file(self, config_path: str) -> None:
|
|
"""Save configuration to YAML file."""
|
|
import yaml
|
|
|
|
config_data = self.to_dict()
|
|
|
|
with open(config_path, 'w') as f:
|
|
yaml.dump(config_data, f, default_flow_style=False, indent=2)
|
|
|
|
|
|
# Global configuration instance
|
|
config = HCFSConfig()
|
|
|
|
|
|
def get_config() -> HCFSConfig:
|
|
"""Get the global configuration instance."""
|
|
return config
|
|
|
|
|
|
def load_config(config_path: Optional[str] = None, **overrides) -> HCFSConfig:
|
|
"""Load configuration with optional file and overrides."""
|
|
global config
|
|
|
|
# Load from file if provided
|
|
if config_path:
|
|
config.load_from_file(config_path)
|
|
|
|
# Apply overrides
|
|
for key, value in overrides.items():
|
|
if hasattr(config, key):
|
|
setattr(config, key, value)
|
|
|
|
return config
|
|
|
|
|
|
def create_config_template(output_path: str = "hcfs_config.yaml") -> None:
|
|
"""Create a configuration template file."""
|
|
template_config = HCFSConfig()
|
|
template_config.save_to_file(output_path)
|
|
print(f"Configuration template created: {output_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Create configuration template
|
|
create_config_template() |