from __future__ import annotations import asyncio import uvicorn from app.adapters import TrustedDnsResolver from app.api import create_app from app.config import ActiveConfig, validate_config from app.db import engine_and_sessions from app.file_pipeline import ClamAvInstream, DependencyFailure from app.repository import Repository from app.service import SafetyService from app.settings import BootstrapSettings, EmergencyMode from app.telemetry import init_telemetry, instrument_fastapi, shutdown_telemetry async def build_runtime() -> tuple[object, object]: settings = BootstrapSettings() assert settings.database_url and settings.service_token engine, sessions = engine_and_sessions(settings.database_url.get_secret_value()) repository = Repository(sessions) row = await repository.active_config() rules, detector, digest = validate_config(row.config, settings.artifacts_dir) if digest != row.config_sha256: raise RuntimeError("active config hash mismatch") config = ActiveConfig(row.version, row.config, rules, detector) mode = EmergencyMode.from_file(settings.mode_file) resolver = TrustedDnsResolver( [item.strip() for item in settings.dns_resolvers.split(",") if item.strip()] ) clamav = ClamAvInstream(settings.clamav_host, settings.clamav_port) if mode.mock: signatures_version = "unavailable" files_ready = False else: try: signatures_version = await clamav.signatures_version() files_ready = True except DependencyFailure: signatures_version = "unavailable" files_ready = False service = SafetyService( repository, config, mode, resolver, files_ready=files_ready, signatures_version=signatures_version, ) app = create_app(service, settings.service_token.get_secret_value()) instrument_fastapi(app) return app, engine async def serve() -> None: settings = BootstrapSettings() init_telemetry("api") engine = None try: app, engine = await build_runtime() server = uvicorn.Server( uvicorn.Config(app, host=settings.host, port=settings.port, proxy_headers=False) ) await server.serve() finally: if engine is not None: await engine.dispose() shutdown_telemetry() def run() -> None: asyncio.run(serve()) if __name__ == "__main__": run()