From 1d699db5325f1fe5602e5c06736992cce8672e97 Mon Sep 17 00:00:00 2001 From: stroblme Date: Thu, 20 Aug 2026 11:29:00 +0200 Subject: [PATCH] Do not publish the API schema from a production deployment The schema enumerates every endpoint an installation serves, including the paths HTTP trigger nodes mount at runtime, and api.fluksio.com was serving it - along with /docs - to anyone who asked. It now follows ENVIRONMENT, which is the rule the portal's backend already used. The generated client is built from a local run, so nothing in the workflow depends on the deployed host exposing it. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01XtBzdDyLsmDaF1W7DLYtYM --- backend/app/main.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/backend/app/main.py b/backend/app/main.py index 3e22667..df039e9 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -198,9 +198,18 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: await aclose() +# The schema enumerates every endpoint this installation serves, including the +# paths trigger nodes mount at runtime. That is exactly what a developer wants +# and exactly what an internet-facing deployment should not hand out, so it +# follows the environment — the same rule the portal's backend uses. The +# generated client is built from a local run, not from the deployed host. +_docs_enabled = settings.ENVIRONMENT != "production" + app = FastAPI( title=settings.PROJECT_NAME, - openapi_url=f"{settings.API_V1_STR}/openapi.json", + openapi_url=f"{settings.API_V1_STR}/openapi.json" if _docs_enabled else None, + docs_url="/docs" if _docs_enabled else None, + redoc_url="/redoc" if _docs_enabled else None, generate_unique_id_function=custom_generate_unique_id, lifespan=lifespan, )