"""FastAPI entrypoint.""" from __future__ import annotations from contextlib import asynccontextmanager from typing import AsyncIterator from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app import __version__ from app.api import routes_health, routes_ingestion, routes_search from app.api.security import install_api_key_auth from app.config import settings from app.logging_config import configure_logging, get_logger configure_logging() logger = get_logger(__name__) @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncIterator[None]: logger.info("api.startup", version=__version__, prefix=settings.app_api_prefix) # Best-effort bootstrap of MinIO buckets - non-fatal if it fails (health will reflect). try: from app.storage.minio_client import get_storage get_storage().ensure_buckets() except Exception as exc: # noqa: BLE001 logger.warning("api.startup.minio_bootstrap_failed", error=str(exc)) yield logger.info("api.shutdown") app = FastAPI( title="LegacyHUB", description="Hybrid lexical + semantic search over legacy PDF archives", version=__version__, lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], allow_headers=["*", "X-API-Key", "Authorization"], max_age=3600, ) install_api_key_auth(app) app.include_router(routes_health.router, prefix=settings.app_api_prefix) app.include_router(routes_ingestion.router, prefix=settings.app_api_prefix) app.include_router(routes_search.router, prefix=settings.app_api_prefix) @app.get("/") def root() -> dict[str, str]: return { "service": "LegacyHUB", "version": __version__, "api": settings.app_api_prefix, "docs": "/docs", }