@@ -18,6 +18,7 @@ source "$ENV_FILE"
1818set +a
1919
2020: " ${DEEPSQL_BACKEND_PORT:= 8080} "
21+ : " ${DEEPSQL_FRONTEND_PORT:= 3000} "
2122: " ${DB_PASSWORD:= postgres} "
2223: " ${DEEPSQL_INITIAL_ADMIN_EMAIL:= } "
2324: " ${DEEPSQL_INITIAL_ADMIN_PASSWORD:= } "
@@ -87,7 +88,19 @@ trap 'rm -f "$cookie_jar"' EXIT
8788login_json=" "
8889login_deadline=$(( SECONDS + 120 ))
8990while (( SECONDS < login_deadline )) ; do
90- if login_json=" $( curl -fsS -c " $cookie_jar " -H ' Content-Type: application/json' -X POST " $base /auth/login" -d " {\" email\" :\" ${DEEPSQL_SMOKE_EMAIL} \" ,\" password\" :\" ${DEEPSQL_SMOKE_PASSWORD} \" }" 2> /dev/null) " ; then
91+ # Login through the frontend proxy so the cookie jar matches the Host the
92+ # browser (and /agent-api auth_request) will use. A jar filled against
93+ # :8080 alone has made nginx's auth_request return 401 even when /auth/me
94+ # on the backend would succeed with the same cookie.
95+ if login_json=" $( curl -fsS -c " $cookie_jar " -H ' Content-Type: application/json' \
96+ -X POST " http://localhost:${DEEPSQL_FRONTEND_PORT} /api/auth/login" \
97+ -d " {\" email\" :\" ${DEEPSQL_SMOKE_EMAIL} \" ,\" password\" :\" ${DEEPSQL_SMOKE_PASSWORD} \" }" 2> /dev/null) " ; then
98+ break
99+ fi
100+ # Fall back to hitting the backend directly (older installs / no frontend).
101+ if login_json=" $( curl -fsS -c " $cookie_jar " -H ' Content-Type: application/json' \
102+ -X POST " $base /auth/login" \
103+ -d " {\" email\" :\" ${DEEPSQL_SMOKE_EMAIL} \" ,\" password\" :\" ${DEEPSQL_SMOKE_PASSWORD} \" }" 2> /dev/null) " ; then
91104 break
92105 fi
93106 echo " Waiting for the backend to accept logins..."
@@ -227,10 +240,13 @@ if [[ "$DEEPSQL_SMOKE_AGENT" == "1" ]]; then
227240 fi
228241
229242 # Browser path through nginx: profile switch must not 403 (Host/Origin CSRF).
243+ # Do NOT send Origin here — that trips the agent's browser CSRF gate, which
244+ # expects X-Hermes-CSRF-Token (the React Agent tab fetches that from
245+ # /api/auth/status). Smoke validates the nginx auth_request + trusted-header
246+ # path the way non-browser clients (and our curl diagnostics) do.
230247 switch_code=" $( curl -sS -o /tmp/deepsql-agent-switch.json -w ' %{http_code}' \
231248 -b " $cookie_jar " -c " $cookie_jar " \
232249 -H ' Content-Type: application/json' \
233- -H " Origin: http://localhost:${DEEPSQL_FRONTEND_PORT} " \
234250 -X POST " http://localhost:${DEEPSQL_FRONTEND_PORT} /agent-api/api/profile/switch" \
235251 -d ' {"name":"u-admin"}' || true) "
236252 if [[ " $switch_code " != " 200" ]]; then
@@ -246,22 +262,21 @@ if [[ "$DEEPSQL_SMOKE_AGENT" == "1" ]]; then
246262 switch_code=" $( curl -sS -o /tmp/deepsql-agent-switch.json -w ' %{http_code}' \
247263 -b " $cookie_jar " -c " $cookie_jar " \
248264 -H ' Content-Type: application/json' \
249- -H " Origin: http://localhost:${DEEPSQL_FRONTEND_PORT} " \
250265 -X POST " http://localhost:${DEEPSQL_FRONTEND_PORT} /agent-api/api/profile/switch" \
251266 -d " {\" name\" :\" ${profile} \" }" || true) "
252267 else
253268 profile=" u-admin"
254269 fi
255270 if [[ " $switch_code " != " 200" ]]; then
256271 echo " Error: /agent-api/api/profile/switch → HTTP ${switch_code} (expected 200)." >&2
257- echo " Common cause: nginx Host header dropping :${DEEPSQL_FRONTEND_PORT} (CSRF)." >&2
272+ echo " Common cause: nginx Host header dropping :${DEEPSQL_FRONTEND_PORT} (CSRF)," >&2
273+ echo " or DEEPSQL_AGENT_TRUSTED_PROXY_CIDRS missing the compose bridge." >&2
258274 cat /tmp/deepsql-agent-switch.json 2> /dev/null >&2 || true
259275 exit 1
260276 fi
261277
262278 session_json=" $( curl -fsS -b " $cookie_jar " -c " $cookie_jar " \
263279 -H ' Content-Type: application/json' \
264- -H " Origin: http://localhost:${DEEPSQL_FRONTEND_PORT} " \
265280 -X POST " http://localhost:${DEEPSQL_FRONTEND_PORT} /agent-api/api/session/new" \
266281 -d " {\" profile\" :\" ${profile} \" ,\" enabled_toolsets\" :[\" deepsql\" ,\" skills\" ]}" ) "
267282 session_id=" $( printf ' %s' " $session_json " | python3 -c ' import sys,json; print(json.load(sys.stdin).get("session",{}).get("session_id") or "")' 2> /dev/null || true) "
@@ -272,11 +287,16 @@ if [[ "$DEEPSQL_SMOKE_AGENT" == "1" ]]; then
272287 fi
273288
274289 # Backend→agent session (dashboard path) — same as AgentChatClient.ensureSession.
290+ # X-Remote-User is required once HERMES_WEBUI_TRUSTED_AUTH_HEADER is set; the
291+ # compose bridge is allowlisted via DEEPSQL_AGENT_TRUSTED_PROXY_CIDRS.
292+ remote_user=" ${profile# u-} "
275293 backend_switch=" $( compose exec -T backend sh -c \
276294 " curl -fsS -c /tmp/hc.jar -H 'Content-Type: application/json' \
295+ -H 'X-Remote-User: ${remote_user} ' \
277296 -X POST '${AGENT_WEBUI_URL} /api/profile/switch' \
278297 -d '{\" name\" :\" ${profile} \" }' >/dev/null && \
279298 curl -fsS -b /tmp/hc.jar -c /tmp/hc.jar -H 'Content-Type: application/json' \
299+ -H 'X-Remote-User: ${remote_user} ' \
280300 -X POST '${AGENT_WEBUI_URL} /api/session/new' \
281301 -d '{\" profile\" :\" ${profile} \" ,\" enabled_toolsets\" :[\" deepsql\" ,\" skills\" ]}'" ) "
282302 if [[ " $backend_switch " != * " session_id" * ]]; then
0 commit comments