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 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-08-21 15:23:46 +10:00
parent e1499864d9
commit e281678328

View file

@ -46,6 +46,11 @@ app = FastAPI(
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=["https://ai.yokogawa.tech"], 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_methods=["GET", "POST"],
allow_headers=["Content-Type"], allow_headers=["Content-Type"],
) )