Spaces:
Paused
Paused
| """ | |
| Application Configuration Module | |
| Centralized configuration for middleware, routers, and application settings. | |
| Target: Keep this file under 500 lines total. | |
| """ | |
| import os | |
| from datetime import datetime | |
| from typing import Optional | |
| from fastapi import FastAPI | |
| from app.constants import API_VERSION | |
| from core.logging import logger | |
| # Router imports - organized by category | |
| CORE_ROUTERS = { | |
| "health": ("app.routers.health", "router"), | |
| "system": ("app.routers.system_routes", "router"), | |
| } | |
| STANDARD_ROUTERS = { | |
| "auth": ("app.modules.auth.router", "router"), | |
| "search": ("app.modules.search.router", "router"), | |
| "admin": ("app.modules.admin.router", "router"), | |
| "users": ("app.modules.users.router", "router"), | |
| "analytics": ("app.modules.analytics.router", "router"), | |
| "reporting": ("app.modules.reporting.router", "router"), | |
| "cases": ("app.modules.cases.router", "router"), | |
| "transactions": ("app.modules.transactions.router", "router"), | |
| "audit": ("app.modules.audit.router", "router"), | |
| "cost_optimization": ("app.routers.cost_optimization", "router"), | |
| "evidence": ("app.modules.evidence.router", "router"), | |
| "fraud": ("app.modules.fraud.router", "router"), | |
| "compliance": ("app.modules.compliance.router", "router"), | |
| "feature-flags": ("app.routers.feature_flags", "router"), | |
| "api-keys": ("app.routers.api_keys", "router"), | |
| } | |
| AI_INTELLIGENCE_ROUTERS = { | |
| "ai": ("app.routers.ai", "router"), | |
| "advanced_ai": ("app.routers.advanced_ai", "router"), | |
| } | |
| ADDITIONAL_ROUTERS = { | |
| "multimodal": ("app.routers.multimodal", "router"), | |
| "logging": ("app.routers.logging", "router"), | |
| "apm": ("app.routers.apm", "router"), | |
| "graph": ("app.routers.graph", "router"), | |
| "realtime_sync": ("app.routers.realtime_sync", "router"), | |
| "notifications": ("app.routers.notifications", "router"), | |
| "backup": ("app.routers.backup", "router"), | |
| "rules": ("app.routers.fraud_rules", "router"), | |
| "stats": ("app.routers.stats", "router"), | |
| "collaboration": ("app.routers.collaboration", "router"), | |
| "reconciliation": ("app.routers.reconciliation", "router"), | |
| "onboarding": ("app.routers.onboarding", "router"), | |
| "metadata": ("app.routers.metadata", "router"), | |
| "proof": ("app.routers.proof", "router"), | |
| "forensic_intel": ("app.routers.forensic_intelligence", "router"), | |
| "entities": ("app.routers.entities", "router"), | |
| "relationships": ("app.routers.entities", "relationships_router"), | |
| "csrf": ("app.routers.csrf", "router"), | |
| } | |
| ROADMAP_ROUTERS = { | |
| "collaboration_roadmap": ("app.routers.collaboration", "router"), | |
| "time_travel": ("app.routers.time_travel", "router"), | |
| "ai_voice": ("app.routers.ai_voice", "router"), | |
| } | |
| NEW_ROADMAP_ROUTERS = { | |
| "xai": ("app.routers.xai", "router"), | |
| "regulatory_rag": ("app.routers.regulatory_rag", "router"), | |
| "auth_biometric": ("app.routers.auth_biometric", "router"), | |
| "auth_social": ("app.routers.auth_social", "router"), | |
| "self_healing": ("app.routers.self_healing", "router"), | |
| } | |
| OPTIONAL_ROUTERS = { | |
| "projects": ("app.routers.projects", "router"), | |
| "alerts": ("app.routers.alerts", "router"), | |
| "metrics": ("app.routers.metrics", "router"), | |
| "streaming": ("app.routers.streaming", "router"), | |
| "websocket": ("app.routers.websocket", "router"), | |
| "diagnostics": ("app.routers.diagnostics", "router"), | |
| } | |
| # Middleware configuration | |
| MIDDLEWARE_CONFIG = { | |
| "security": { | |
| "HTTPSRedirectMiddleware": { | |
| "condition": lambda: ( | |
| os.getenv("ENVIRONMENT", "development").lower() not in ["development", "test"] | |
| and not os.getenv("SPACE_ID") | |
| and os.getenv("DISABLE_HTTPS_REDIRECT", "false").lower() != "true" | |
| ) | |
| }, | |
| "TrustedHostMiddleware": { | |
| "condition": lambda: os.getenv("ENVIRONMENT", "development").lower() != "development", | |
| "kwargs": {"allowed_hosts": ["*"]}, | |
| }, | |
| "SecurityHeadersMiddleware": {"condition": lambda: True}, | |
| "CSRFProtectionMiddleware": {"condition": lambda: os.getenv("TESTING") != "True"}, | |
| "ZeroTrustMiddleware": {}, | |
| }, | |
| "performance": { | |
| "CORSMiddleware": { | |
| "kwargs": { | |
| "allow_origins": lambda: _get_cors_origins(), | |
| "allow_credentials": True, | |
| "allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], | |
| "allow_headers": [ | |
| "Authorization", | |
| "Content-Type", | |
| "X-Requested-With", | |
| "Accept", | |
| "Accept-Encoding", | |
| "Accept-Language", | |
| ], | |
| "max_age": 86400, | |
| } | |
| }, | |
| "GZipMiddleware": {"kwargs": {"minimum_size": 1000}}, | |
| "PerformanceMonitoringMiddleware": {}, | |
| "APMMiddleware": {}, | |
| }, | |
| "monitoring": { | |
| "RequestIDMiddleware": {}, | |
| "DeprecatedEndpointMonitor": {}, | |
| "UnifiedRateLimitingMiddleware": {}, | |
| "InputValidationMiddleware": {}, | |
| "ErrorEnforcementMiddleware": {}, | |
| }, | |
| } | |
| def _get_cors_origins() -> list[str]: | |
| """Get CORS origins based on environment""" | |
| environment = os.getenv("ENVIRONMENT", "development").lower() | |
| # Check for environment variable override first | |
| cors_allowed_origins = os.getenv("CORS_ALLOWED_ORIGINS") | |
| if cors_allowed_origins: | |
| return [origin.strip() for origin in cors_allowed_origins.split(",")] | |
| if environment in ["development", "test"]: | |
| return [ | |
| "http://localhost:5173", | |
| "http://localhost:5174", | |
| "http://localhost:5175", | |
| "http://127.0.0.1:5173", | |
| "http://127.0.0.1:5174", | |
| "http://127.0.0.1:3000", | |
| "http://localhost:3000", | |
| ] | |
| else: | |
| # Production defaults - use wildcard for maximum compatibility | |
| # For stricter security, use CORS_ALLOWED_ORIGINS env var | |
| return ["*"] | |
| def _setup_core_routers(app: FastAPI): | |
| """Setup core routers (health, system)""" | |
| for name, (module_path, router_attr) in CORE_ROUTERS.items(): | |
| _import_and_include_router(app, module_path, router_attr, name, "") | |
| if name == "health": | |
| _import_and_include_router(app, module_path, router_attr, name, f"/api/{API_VERSION}") | |
| def _setup_standard_routers(app: FastAPI): | |
| """Setup standard API routers""" | |
| for name, (module_path, router_attr) in STANDARD_ROUTERS.items(): | |
| prefix = f"/api/{API_VERSION}/{name}" | |
| _import_and_include_router(app, module_path, router_attr, name, prefix) | |
| def _setup_ai_routers(app: FastAPI): | |
| """Setup AI & Intelligence routers""" | |
| for name, (module_path, router_attr) in AI_INTELLIGENCE_ROUTERS.items(): | |
| prefix = f"/api/{API_VERSION}/{name}" | |
| tags = ["AI Intelligence"] if name == "ai" else ["Advanced AI"] | |
| _import_and_include_router(app, module_path, router_attr, name, prefix, tags) | |
| def _setup_additional_routers(app: FastAPI): | |
| """Setup additional routers""" | |
| for name, (module_path, router_attr) in ADDITIONAL_ROUTERS.items(): | |
| prefix = f"/api/{API_VERSION}/{name}" | |
| _import_and_include_router(app, module_path, router_attr, name, prefix) | |
| def _setup_roadmap_routers(app: FastAPI): | |
| """Setup roadmap routers""" | |
| for name, (module_path, router_attr) in ROADMAP_ROUTERS.items(): | |
| prefix = ( | |
| f"/api/{API_VERSION}/{name}" if name != "collaboration_roadmap" else f"/api/{API_VERSION}/collaboration" | |
| ) | |
| tags = ["Roadmap"] if name != "collaboration_roadmap" else ["Collaboration (Roadmap)"] | |
| _import_and_include_router(app, module_path, router_attr, name, prefix, tags) | |
| def _setup_new_roadmap_routers(app: FastAPI): | |
| """Setup new roadmap routers""" | |
| for name, (module_path, router_attr) in NEW_ROADMAP_ROUTERS.items(): | |
| _import_and_include_router(app, module_path, router_attr, name, f"/api/{API_VERSION}") | |
| def _setup_optional_routers(app: FastAPI): | |
| """Setup optional routers with graceful error handling""" | |
| for name, (module_path, router_attr) in OPTIONAL_ROUTERS.items(): | |
| try: | |
| if name == "metrics": | |
| _import_and_include_router(app, module_path, router_attr, name, "") | |
| elif name in ["streaming", "websocket"]: | |
| _import_and_include_router(app, module_path, router_attr, name, f"/api/{API_VERSION}") | |
| else: | |
| prefix = f"/api/{API_VERSION}/{name}" | |
| _import_and_include_router(app, module_path, router_attr, name, prefix) | |
| except ImportError as e: | |
| logger.warning(f"Failed to import {name} router: {e}") | |
| def setup_routers(app: FastAPI): | |
| """Setup all application routers with proper organization""" | |
| _setup_core_routers(app) | |
| _setup_standard_routers(app) | |
| _setup_ai_routers(app) | |
| _setup_additional_routers(app) | |
| from app.routers.graph import shim_router as graph_shim_router | |
| app.include_router(graph_shim_router, prefix=f"/api/{API_VERSION}") | |
| _setup_semantic_search_router(app) | |
| _setup_roadmap_routers(app) | |
| _setup_new_roadmap_routers(app) | |
| _setup_optional_routers(app) | |
| def _import_and_include_router( | |
| app: FastAPI, | |
| module_path: str, | |
| router_attr: str, | |
| name: str, | |
| prefix: str = "", | |
| tags: Optional[list[str]] = None, | |
| ): | |
| """Import and include a router with error handling""" | |
| try: | |
| module = __import__(module_path, fromlist=[router_attr]) | |
| router = getattr(module, router_attr) | |
| app.include_router(router, prefix=prefix, tags=tags or [name.title()]) | |
| except ImportError as e: | |
| logger.error(f"Failed to import router {name} from {module_path}: {e}") | |
| def _setup_semantic_search_router(app: FastAPI): | |
| """Setup deprecated semantic search router with removal deadline""" | |
| from app.routers.semantic_search import router as semantic_search_router | |
| removal_deadline = datetime(2026, 2, 1) | |
| if datetime.now() < removal_deadline: | |
| app.include_router( | |
| semantic_search_router, | |
| prefix=f"/api/{API_VERSION}/semantic_search", | |
| tags=["Semantic Search (DEPRECATED)"], | |
| ) | |
| else: | |
| logger.warning("Semantic search router removal deadline reached - endpoints disabled") | |
| def setup_middleware(app: FastAPI): | |
| """Setup all application middleware with proper configuration""" | |
| # Setup exception handlers and error enforcement first | |
| import os | |
| env = os.getenv("ENVIRONMENT", "development").lower() | |
| debug_mode = env != "production" | |
| logger.info(f"Setting up middleware for environment: {env} (debug_mode={debug_mode})") | |
| from core.error_enforcement import setup_error_enforcement_middleware | |
| setup_error_enforcement_middleware(app, debug=debug_mode) | |
| # Setup unified rate limiting | |
| from core.unified_rate_limiting import RateLimitingMiddleware | |
| app.add_middleware(RateLimitingMiddleware) | |
| # Apply middleware in order | |
| for category, middlewares in MIDDLEWARE_CONFIG.items(): | |
| for middleware_name, config in middlewares.items(): | |
| # Skip unified rate limiting and error enforcement as they're already added | |
| if middleware_name in [ | |
| "UnifiedRateLimitingMiddleware", | |
| "ErrorEnforcementMiddleware", | |
| ]: | |
| continue | |
| # Check condition if present | |
| if "condition" in config and not config["condition"](): | |
| continue | |
| # Import and add middleware | |
| try: | |
| middleware_class = _import_middleware(middleware_name) | |
| kwargs = config.get("kwargs", {}) | |
| # Handle callable kwargs (like CORS origins) | |
| for key, value in kwargs.items(): | |
| if callable(value): | |
| kwargs[key] = value() | |
| app.add_middleware(middleware_class, **kwargs) | |
| except ImportError as e: | |
| logger.warning(f"Failed to import middleware {middleware_name}: {e}") | |
| # Add request logging middleware last | |
| from app.middleware_setup import request_logging_middleware | |
| app.middleware("http")(request_logging_middleware) | |
| def _import_middleware(middleware_name: str): | |
| """Import middleware class by name""" | |
| middleware_map = { | |
| "HTTPSRedirectMiddleware": "fastapi.middleware.httpsredirect", | |
| "TrustedHostMiddleware": "fastapi.middleware.trustedhost", | |
| "CORSMiddleware": "fastapi.middleware.cors", | |
| "GZipMiddleware": "fastapi.middleware.gzip", | |
| "SecurityHeadersMiddleware": "app.middleware_setup", | |
| "CSRFProtectionMiddleware": "core.csrf_protection", | |
| "ZeroTrustMiddleware": "app.middleware.security", | |
| "PerformanceMonitoringMiddleware": "core.performance", | |
| "APMMiddleware": "app.services.infrastructure.apm_service", | |
| "RequestIDMiddleware": "middleware.request_id", | |
| "DeprecatedEndpointMonitor": "app.middleware.deprecated_monitor", | |
| "UnifiedRateLimitingMiddleware": "core.unified_rate_limiting", | |
| "InputValidationMiddleware": "core.validation", | |
| "ErrorEnforcementMiddleware": "core.error_enforcement", | |
| } | |
| module_path = middleware_map.get(middleware_name) | |
| if not module_path: | |
| raise ImportError(f"Unknown middleware: {middleware_name}") | |
| module = __import__(module_path, fromlist=[middleware_name]) | |
| return getattr(module, middleware_name) | |
| # Application configuration | |
| class AppConfig: | |
| """Centralized application configuration""" | |
| ENVIRONMENT = os.getenv("ENVIRONMENT", "development").lower() | |
| IS_DEVELOPMENT = ENVIRONMENT == "development" | |
| # Security settings | |
| SECURITY_HEADERS = { | |
| "X-Content-Type-Options": "nosniff", | |
| "X-Frame-Options": "DENY", | |
| "X-XSS-Protection": "1; mode=block", | |
| "Strict-Transport-Security": "max-age=31536000; includeSubDomains", | |
| "Content-Security-Policy": ( | |
| "default-src 'self'; script-src 'self' 'unsafe-inline'; " | |
| "style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; " | |
| "font-src 'self' data:;" | |
| ), | |
| "Referrer-Policy": "strict-origin-when-cross-origin", | |
| } | |
| # Rate limiting settings | |
| RATE_LIMIT_SETTINGS = { | |
| "default": {"requests": 100, "window": 60}, | |
| "/api/v1/auth/login": {"requests": 5, "window": 300}, | |
| "/api/v1/auth/register": {"requests": 3, "window": 3600}, | |
| "/api/v1/evidence/upload": {"requests": 10, "window": 3600}, | |
| } | |
| def get_cors_config(cls) -> dict: | |
| """Get CORS configuration""" | |
| return { | |
| "allow_origins": _get_cors_origins(), | |
| "allow_credentials": True, | |
| "allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], | |
| "allow_headers": [ | |
| "Authorization", | |
| "Content-Type", | |
| "X-Requested-With", | |
| "Accept", | |
| "Accept-Encoding", | |
| "Accept-Language", | |
| ], | |
| "max_age": 86400, | |
| } | |
| # Export main setup functions | |
| __all__ = [ | |
| "setup_routers", | |
| "setup_middleware", | |
| "AppConfig", | |
| "MIDDLEWARE_CONFIG", | |
| "CORE_ROUTERS", | |
| "STANDARD_ROUTERS", | |
| "AI_INTELLIGENCE_ROUTERS", | |
| "ADDITIONAL_ROUTERS", | |
| ] | |