| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- """FastAPI application entry point."""
- import os
- import sys
- # Make the repository root importable so the single-source plan schema
- # (src.plan_schema) resolves when the backend runs from a checkout.
- _BACKEND_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- _REPO_ROOT = os.path.normpath(os.path.join(_BACKEND_DIR, "..", ".."))
- if _REPO_ROOT not in sys.path:
- sys.path.insert(0, _REPO_ROOT)
- from fastapi import FastAPI, Request, HTTPException
- from fastapi.middleware.cors import CORSMiddleware
- from .config import APP_NAME, APP_VERSION, APP_DESCRIPTION, CORS_ORIGINS
- from .database import init_db
- from .routers import projects, plans, experience, generation, analytics, ai, search, ai_plan, analysis, adaptive, tasks, monitor, reports, executor_monitor
- app = FastAPI(
- title=APP_NAME,
- version=APP_VERSION,
- description=APP_DESCRIPTION,
- )
- # CORS middleware (allow frontend dev server)
- app.add_middleware(
- CORSMiddleware,
- allow_origins=CORS_ORIGINS,
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
- # E4 fix: optional API key authentication middleware.
- # Enabled only when AFM_API_KEY is set in environment.
- _API_KEY = os.environ.get("AFM_API_KEY", "").strip()
- _PUBLIC_PATHS = ("/api/health", "/docs", "/openapi.json", "/redoc", "/")
- @app.middleware("http")
- async def api_key_auth(request: Request, call_next):
- """Optional API key authentication (E4 fix)."""
- if not _API_KEY:
- return await call_next(request)
- path = request.url.path
- if any(path.startswith(p) for p in _PUBLIC_PATHS):
- return await call_next(request)
- provided = request.headers.get("X-API-Key", "")
- if provided != _API_KEY:
- raise HTTPException(status_code=401, detail="Invalid or missing API key")
- return await call_next(request)
- # Include routers
- app.include_router(projects.router)
- app.include_router(plans.router)
- app.include_router(experience.router)
- app.include_router(generation.router)
- app.include_router(analytics.router)
- app.include_router(ai.router)
- app.include_router(search.router)
- app.include_router(ai_plan.router)
- app.include_router(analysis.router)
- app.include_router(adaptive.router)
- app.include_router(tasks.router)
- app.include_router(monitor.router)
- app.include_router(reports.router)
- app.include_router(executor_monitor.router)
- @app.on_event("startup")
- def on_startup():
- """Initialize database on startup."""
- init_db()
- @app.get("/api/health")
- def health_check():
- """Health check endpoint."""
- return {"status": "ok", "app": APP_NAME, "version": APP_VERSION}
- @app.get("/")
- def root():
- """Root endpoint - redirect to API docs."""
- return {
- "message": APP_NAME,
- "version": APP_VERSION,
- "docs": "/docs",
- "api_health": "/api/health",
- }
|