""" MeshBay Hub — FastAPI application factory. Usage: from meshbay_hub.app import create_app from meshbay_hub.config import load_config cfg = load_config() app = create_app(cfg) """ from contextlib import asynccontextmanager from pathlib import Path from fastapi import FastAPI from slowapi import _rate_limit_exceeded_handler from slowapi.errors import RateLimitExceeded from meshbay_hub import __version__ from meshbay_hub.auth import generate_hub_keypair, load_hub_keypair from meshbay_hub.config import HubConfig from meshbay_hub.db.engine import close_db, init_db from meshbay_hub.api.hub import router as hub_router from meshbay_hub.api.users import router as users_router, set_config as users_set_config from meshbay_hub.api.nodes import router as nodes_router from meshbay_hub.api.groups import router as groups_router from meshbay_hub.api.revocation import router as revocation_router from meshbay_hub.api.moderation import router as moderation_router from meshbay_hub.api.federation import router as federation_router from meshbay_hub.csam import csam_router from meshbay_hub.api.relay import router as relay_router from meshbay_hub.api.webapp import router as webapp_router from meshbay_hub.api.middleware import limiter def create_app(cfg: HubConfig | None = None) -> FastAPI: from meshbay_hub.config import load_config if cfg is None: cfg = load_config() @asynccontextmanager async def lifespan(app: FastAPI): # Startup await init_db(cfg.db.url) kp = cfg.identity.private_key_path if not kp.exists(): generate_hub_keypair(kp) load_hub_keypair(kp, cfg.identity.id) users_set_config(cfg) yield # Shutdown await close_db() app = FastAPI( title="MeshBay Hub", version=__version__, description="MeshBay identity authority and group registry", lifespan=lifespan, ) # Rate limiting app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) # Routers (webapp last — catches / before API routes) app.include_router(hub_router) app.include_router(users_router) app.include_router(nodes_router) app.include_router(groups_router) app.include_router(revocation_router) app.include_router(moderation_router) app.include_router(federation_router) app.include_router(csam_router) app.include_router(relay_router) app.include_router(webapp_router) return app