import logging from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.routers import auth as auth_router from app.routers import techniques as techniques_router from app.routers import tests as tests_router from app.routers import evidence as evidence_router from app.routers import system as system_router from app.storage import ensure_bucket_exists from app.jobs.mitre_sync_job import start_scheduler, scheduler # ── Logging ─────────────────────────────────────────────────────────────── logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)-8s %(name)s — %(message)s", ) @asynccontextmanager async def lifespan(app: FastAPI): """Startup / shutdown logic.""" ensure_bucket_exists() start_scheduler() yield # Graceful shutdown of the background scheduler scheduler.shutdown(wait=False) app = FastAPI(title="Attack Coverage Platform", lifespan=lifespan) # ── CORS ────────────────────────────────────────────────────────────────── app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000", "http://localhost:5173"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ── Routers ────────────────────────────────────────────────────────────── app.include_router(auth_router.router, prefix="/api/v1") app.include_router(techniques_router.router, prefix="/api/v1") app.include_router(tests_router.router, prefix="/api/v1") app.include_router(evidence_router.router, prefix="/api/v1") app.include_router(system_router.router, prefix="/api/v1") @app.get("/health") def health(): return {"status": "ok"}