From e281678328d51ef56301f45f316aa891a546640e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 15:23:46 +1000 Subject: [PATCH] Let the browser send the Authelia cookie: CORS must allow credentials The UI calls the API with credentials: "include", because ai.yokogawa.tech and api.yokogawa.tech are different origins and the Authelia session cookie has to be attached explicitly. The CORS middleware never set allow_credentials, and a browser refuses a credentialed cross-origin request unless the response says Access-Control-Allow-Credentials: true. It fails at the preflight, so the real request is never sent: Access to fetch at '.../ask' has been blocked by CORS policy: the value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Every question from the UI would have failed at Phase 7 with "Could not reach the assistant" - the app's network-error branch, which says nothing about CORS and points at the wrong layer entirely. The API is fine; curl against it passes, because curl is not a browser and does not enforce this. Found driving the built UI in a browser. It is not reachable by any test that does not involve a browser, which is the useful part: the Phase 7 gate says an operator reaches the UI and gets an answer end to end, and that gate is the first thing that would have caught it - at the point where DNS, Caddy and Authelia are all new too, and any of them a plausible suspect. Co-Authored-By: Claude Opus 5 --- api/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/main.py b/api/main.py index 76c1a15..12d81fa 100644 --- a/api/main.py +++ b/api/main.py @@ -46,6 +46,11 @@ app = FastAPI( app.add_middleware( CORSMiddleware, allow_origins=["https://ai.yokogawa.tech"], + # The UI sends credentials: "include" so the browser attaches the Authelia + # session cookie. Without this the preflight fails and NO cross-origin call + # succeeds - the browser refuses a credentialed request unless the response + # says Access-Control-Allow-Credentials: true. + allow_credentials=True, allow_methods=["GET", "POST"], allow_headers=["Content-Type"], )