diff --git a/backend/src/cyclone/api.py b/backend/src/cyclone/api.py index 7a6d80a..4786028 100644 --- a/backend/src/cyclone/api.py +++ b/backend/src/cyclone/api.py @@ -301,13 +301,10 @@ app.add_middleware(SecurityHeadersMiddleware) # and are wired in here. (Kept as a top-level package rather than nested # under `cyclone.api` so the existing ``cyclone.api`` module path keeps # working — Python prefers packages over same-named modules.) -from cyclone.api_routers import acks, admin, claim_acks, health, ta1_acks # noqa: E402 +from cyclone.api_routers import routers # noqa: E402 -app.include_router(health.router) -app.include_router(acks.router, dependencies=[Depends(matrix_gate)]) -app.include_router(ta1_acks.router, dependencies=[Depends(matrix_gate)]) -app.include_router(claim_acks.router, dependencies=[Depends(matrix_gate)]) -app.include_router(admin.router, dependencies=[Depends(matrix_gate)]) +for _router in routers: + app.include_router(_router) @app.exception_handler(HTTPException) diff --git a/backend/src/cyclone/api_routers/__init__.py b/backend/src/cyclone/api_routers/__init__.py index 8df5940..5ca8320 100644 --- a/backend/src/cyclone/api_routers/__init__.py +++ b/backend/src/cyclone/api_routers/__init__.py @@ -1 +1,23 @@ -"""Resource-group routers. Imported and registered by ``cyclone.api``.""" +"""Per-resource FastAPI routers. + +`api.py` does `for r in routers: app.include_router(r)`. New +routers register themselves here in alphabetical order. Helpers +shared by 2+ routers live in `_shared.py` (private to the package). + +Every router except ``health`` declares its own +``APIRouter(dependencies=[Depends(matrix_gate)])`` — keep that +invariant here so adding a new router doesn't silently miss the gate. +""" +from fastapi import APIRouter + +from cyclone.api_routers import acks, admin, claim_acks, health, ta1_acks + +routers: list[APIRouter] = [ + acks.router, # gated + admin.router, # gated + claim_acks.router, # gated + health.router, # public — health probes must work pre-auth + ta1_acks.router, # gated +] + +__all__ = ["routers"] diff --git a/backend/src/cyclone/api_routers/_shared.py b/backend/src/cyclone/api_routers/_shared.py new file mode 100644 index 0000000..8140a5b --- /dev/null +++ b/backend/src/cyclone/api_routers/_shared.py @@ -0,0 +1,9 @@ +"""Cross-router helpers for the api_routers package. + +Private to the package (leading underscore). Only routers in this +package import from here. Helpers graduate here when at least two +routers need them — single-router helpers stay in the router that +uses them. + +Initially empty; helpers promote here as the SP36 refactor progresses. +""" diff --git a/backend/src/cyclone/api_routers/acks.py b/backend/src/cyclone/api_routers/acks.py index 14af7b0..c5e61a9 100644 --- a/backend/src/cyclone/api_routers/acks.py +++ b/backend/src/cyclone/api_routers/acks.py @@ -18,7 +18,7 @@ from __future__ import annotations import logging from typing import Any, AsyncIterator -from fastapi import APIRouter, HTTPException, Query, Request +from fastapi import APIRouter, Depends, HTTPException, Query, Request from fastapi.responses import StreamingResponse from cyclone import db @@ -28,12 +28,13 @@ from cyclone.api_helpers import ( tail_events, wants_ndjson, ) +from cyclone.auth.deps import matrix_gate from cyclone.parsers.models_999 import ParseResult999 from cyclone.parsers.serialize_999 import serialize_999 from cyclone.pubsub import EventBus from cyclone.store import store, to_ui_ack -router = APIRouter() +router = APIRouter(dependencies=[Depends(matrix_gate)]) log = logging.getLogger(__name__) diff --git a/backend/src/cyclone/api_routers/admin.py b/backend/src/cyclone/api_routers/admin.py index de0164a..9fcf362 100644 --- a/backend/src/cyclone/api_routers/admin.py +++ b/backend/src/cyclone/api_routers/admin.py @@ -12,12 +12,13 @@ format" from "bad checksum". """ from __future__ import annotations -from fastapi import APIRouter, Query +from fastapi import APIRouter, Depends, Query +from cyclone.auth.deps import matrix_gate from cyclone.npi import is_valid_npi, is_valid_tax_id, normalize_tax_id -router = APIRouter() +router = APIRouter(dependencies=[Depends(matrix_gate)]) @router.get("/api/admin/validate-provider") diff --git a/backend/src/cyclone/api_routers/claim_acks.py b/backend/src/cyclone/api_routers/claim_acks.py index 0c635f2..553a969 100644 --- a/backend/src/cyclone/api_routers/claim_acks.py +++ b/backend/src/cyclone/api_routers/claim_acks.py @@ -21,16 +21,17 @@ from __future__ import annotations import logging from typing import Any, AsyncIterator, Literal -from fastapi import APIRouter, HTTPException, Query, Request +from fastapi import APIRouter, Depends, HTTPException, Query, Request from fastapi.responses import JSONResponse, StreamingResponse from pydantic import BaseModel, Field from cyclone import db from cyclone.api_helpers import ndjson_line, tail_events +from cyclone.auth.deps import matrix_gate from cyclone.pubsub import EventBus from cyclone.store import store, to_ui_claim_ack -router = APIRouter() +router = APIRouter(dependencies=[Depends(matrix_gate)]) log = logging.getLogger(__name__) diff --git a/backend/src/cyclone/api_routers/ta1_acks.py b/backend/src/cyclone/api_routers/ta1_acks.py index f669287..d7364bd 100644 --- a/backend/src/cyclone/api_routers/ta1_acks.py +++ b/backend/src/cyclone/api_routers/ta1_acks.py @@ -16,15 +16,16 @@ from __future__ import annotations from typing import Any, AsyncIterator -from fastapi import APIRouter, HTTPException, Query, Request +from fastapi import APIRouter, Depends, HTTPException, Query, Request from fastapi.responses import StreamingResponse from cyclone.api_helpers import ndjson_line, tail_events +from cyclone.auth.deps import matrix_gate from cyclone import db from cyclone.pubsub import EventBus from cyclone.store import store, to_ui_ta1_ack -router = APIRouter() +router = APIRouter(dependencies=[Depends(matrix_gate)]) # SP25: ``_ta1_to_ui`` moved to ``cyclone.store.ui.to_ui_ta1_ack`` so