import os from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from api.database import engine from api.routers import decisions, extension_points, progress, state, tasks, technical_debt, topics, workstreams, workstream_dependencies from api.routers import domains, repos, contributions, sbom, policy, domain_goals, repo_goals, messages, capability_requests, tpsc @asynccontextmanager async def lifespan(app: FastAPI): yield await engine.dispose() app = FastAPI( title="Custodian State Hub", description="Local-first state API for the Custodian agent system.", version="0.6.0", lifespan=lifespan, ) _cors_env = os.getenv("CORS_ORIGINS", "http://localhost:3000,http://127.0.0.1:3000") _cors_origins = [o.strip() for o in _cors_env.split(",") if o.strip()] app.add_middleware( CORSMiddleware, allow_origins=_cors_origins, allow_methods=["GET", "POST", "PATCH", "DELETE", "PUT"], allow_headers=["Content-Type"], ) app.include_router(domains.router) app.include_router(repos.router) app.include_router(topics.router) app.include_router(workstreams.router) app.include_router(workstream_dependencies.router) app.include_router(tasks.router) app.include_router(decisions.router) app.include_router(extension_points.router) app.include_router(technical_debt.router) app.include_router(progress.router) app.include_router(domain_goals.router) app.include_router(repo_goals.router) app.include_router(contributions.router) app.include_router(sbom.router) app.include_router(messages.router) app.include_router(capability_requests.router) app.include_router(tpsc.router) app.include_router(state.router) app.include_router(policy.router) @app.get("/", include_in_schema=False) async def root(): return {"service": "state-hub", "docs": "/docs"}