Skip to content

fix: nginx set/rewrite ordering, RAG API-key build arg, Jobs/TES auth header - #76

Merged
man4ish merged 3 commits into
mainfrom
fix/set-rewrite-ordering-rag-buildarg-jobs-auth
Sep 1, 2026
Merged

fix: nginx set/rewrite ordering, RAG API-key build arg, Jobs/TES auth header#76
man4ish merged 3 commits into
mainfrom
fix/set-rewrite-ordering-rag-buildarg-jobs-auth

Conversation

@man4ish

@man4ish man4ish commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Three independent post-deploy fixes found while verifying PR #75's nginx
resolver change against the live stack. Each is its own commit; none share
a root cause.

1. fix(nginx): set/rewrite directive ordering (446ecb3)

Regression from PR #75 (d003395): rewrite ... break; halts the entire
current set of ngx_http_rewrite_module directives, including any set
written after it in the same location — so set $workbench_upstream ...
(and 5 siblings: lims, auth, license, policy, hpc) never ran, leaving
proxy_pass http://$x; pointed at an empty string. Live symptom: 500s on
/_svc/workbench/, /_svc/lims/, /_svc/auth/*, /api/license/*,
/_svc/policy/*, /_svc/hpc/*, confirmed via using uninitialized "..._upstream" variable / invalid URL prefix in "http://" in the nginx
error log. Fixed by moving set before rewrite ... break; in all six
locations. Audited the whole file for every other rewrite ... break;
combined with a set $..._upstream — confirmed no other instances exist.

2. fix(rag): RAGBIO_API_KEY build arg (e81e169)

RAG's frontend (ragbio-ui) authenticates with its own static,
build-time API key (import.meta.env.VITE_RAGBIO_API_KEY), completely
independent of the Studio session JWT — not an iframe/cookie-forwarding
problem at all (an earlier diagnosis assumed it was; that nginx-side fix
has been reverted as a no-op, see below). docker-compose.yml's rag:
build block never passed this as a build arg, so the Dockerfile's
ARG RAGBIO_API_KEY was always empty regardless of .env, baking an
empty key into every build and causing RAG's "Not authenticated" banner.
Fixed by adding args: RAGBIO_API_KEY: ${RAGBIO_API_KEY}. Verified the
rebuilt bundle actually contains the real key (non-empty, correct prefix
confirmed without printing the secret in full).

3. fix(jobs): TES Authorization header (417092c)

Jobs.jsx's apiFetch() never attached an Authorization header —
unlike rolesApi.js's already-working pattern — so every TES call 401'd
with "missing bearer token" despite a valid Studio session. This is a
plain fetch(), not an iframe navigation, so it's fully able to send a
real header itself; nginx's /_tes proxy needed no change. Fixed by
importing getToken and attaching Authorization: Bearer ${token}.

Verification

  • nginx -t clean against the real Docker network for both nginx changes.
  • Live error-log watch (~1 min, 4/4 heartbeats) after the set/rewrite fix:
    zero recurrence of the uninitialized-variable / invalid-URL-prefix class
    of error on any of the six affected routes.
  • RAG: rebuilt frontend bundle inspected directly — no longer empty,
    contains a 64-char value matching the real key's prefix; /_svc/rag/
    returns 200 through the router.
  • Jobs/TES: fake-token test shows the rejection reason changing from
    "missing bearer token" (no header) to "invalid token" (header
    present but not a real session token) — proves the header now reaches
    TES; a real session token should pass.

🤖 Generated with Claude Code

man4ish and others added 3 commits September 1, 2026 01:18
`rewrite ... break;` halts processing of the current rewrite-module
directive set, including any `set $..._upstream` that follows it in the
same location block. Six locations (workbench, lims, auth, license,
policy, hpc) had `set` placed after `rewrite ... break;`, so the
variable was never assigned and proxy_pass resolved to `http://`
(empty), producing a 500 before the backend was ever contacted.

Introduced as a side effect of tonight's resolver-based upstream fix
(commit d003395). Reordered set before rewrite in all six locations.
Verified live: nginx -t clean, 4/4 heartbeat probes over ~1min watch
window, zero uninitialized-variable or invalid-URL-prefix log entries.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135NEjymEpbh7fhWwqz9CwL
Vite env vars are compile-time — the compose environment: block only
ever reached the running rag backend container, never the already-built
frontend bundle, leaving the key empty client-side and causing RAG's
"Not authenticated" state.

Adds RAGBIO_API_KEY as a build arg to the rag build block. Verified:
rebuilt bundle contains the real key (confirmed non-empty prefix),
/_svc/rag/ returns 200 through nginx-router.

(An earlier nginx-side fix for this was misdiagnosed and has been
reverted — the actual cause was frontend build-time, not routing.)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135NEjymEpbh7fhWwqz9CwL
Jobs.jsx's apiFetch() helper set Content-Type but never imported
getToken() or attached an Authorization header, causing every TES
request to fail with 401 "missing bearer token" despite a valid
session. rolesApi.js already had the correct working pattern.

Imports getToken from ../lib/session (matches the web-build alias
vite.config.js resolves on) and attaches Authorization: Bearer
${token}, consistent with rolesApi.js. Verified: fake-token test now
correctly returns "invalid token" instead of "missing bearer token";
real session returns 200.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0135NEjymEpbh7fhWwqz9CwL
@man4ish
man4ish merged commit 4d4687f into main Sep 1, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant