Skip to content

Route bare /orgs to auth-service (Phase 1 PR2 org/team/API-key endpoints) - #17

Merged
man4ish merged 2 commits into
mainfrom
feature/nginx-orgs-route-claim
Aug 1, 2026
Merged

Route bare /orgs to auth-service (Phase 1 PR2 org/team/API-key endpoints)#17
man4ish merged 2 commits into
mainfrom
feature/nginx-orgs-route-claim

Conversation

@man4ish

@man4ish man4ish commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

omnibioai-auth's Phase 1 PR2 (OmniBioAI/omnibioai-auth#4, merged) added three new route files, all reachable at bare paths this router didn't yet claim:

  • routes_orgs.py — prefix /orgs
  • routes_teams.py — nested under /orgs/{org_id}/teams
  • routes_apikeys.py — nested under /orgs/{org_id}/api-keys

One location ^~ /orgs block covers all three, since they all nest under the same prefix.

Why this matters

This file's own header comment documents the exact failure mode of not doing this: an unclaimed bare path falls through to the catch-all location / (web-ui) and returns a 200 with index.html instead of a real response or a 404 — indistinguishable from a frontend bug ("blank page", "JSON parse error"). That's already happened four times for /license, /roles, and /users/. This PR claims the path proactively instead of waiting for the same thing to happen to /orgs.

Change

  • Added /orgs to the header comment's path inventory
  • Added a location ^~ /orgs { ... } block, structurally identical to the existing /roles//users/ blocks (same limit_req zone, same proxy_pass http://auth)

Testing

  • Brace-balance sanity check on the full file (111/111) — no structural syntax break
  • New block mirrors three already-proven blocks in the same file exactly; no novel directives introduced
  • Not yet runtime-tested against a live container — a full nginx -t requires reconstructing this file's compose-provided context (upstreams, includes), which wasn't done here
  • Not yet deployed. Per this file's own top-of-file warning, the running nginx-router container has this file bind-mounted by inode — picking up this change requires docker compose up -d --no-deps --force-recreate nginx-router, not a plain reload (a reload re-reads the same stale inode and reports success while serving old content)

Related

🤖 Generated with Claude Code

man4ish and others added 2 commits August 1, 2026 01:26
…router

Follow-up to the dev-hub require_auth fix (omnibioai-dev-hub commit
073c615): that fix alone wasn't sufficient because nginx-router is the
platform's actual public entry point (reached via cloudflared) and its
/rag/ location proxied straight to dev-hub:8082, bypassing dev-hub's own
internal nginx entirely -- so the internal-header bridge built for that
container never applied to real production traffic. Discovered via an
exhaustive re-search for /rag/query and /rag/stream callers.

Considered and rejected: having this router unconditionally inject a
trusted header on every /rag/ request, mirroring dev-hub's own internal
bridge. That would have authenticated all traffic equally -- legitimate
frontend and anonymous internet caller alike -- since this router is the
single point everyone passes through. It would have just moved the same
open-oracle problem here instead of closing it.

Instead, reused Control Center's already-working auth_request pattern:
/rag/ now gates on /internal/auth/verify, which validates the caller's
real session (their Authorization header, or the omnibioai_access_token
cookie via the existing $control_authorization map) against api-gateway,
then forwards that same verified JWT to dev-hub -- which require_auth
also accepts, since it's signed with the same shared secret. A real
logged-in user's session satisfies both gates with no dev-hub-ui code
changes needed.

Verified live against the actual running stack (all 27 services up):
anonymous request -> 401, spoofed X-Devhub-Internal header -> still 401
(not trusted at this layer, confirming no bypass), real access_token from
a genuine /auth/login -> passes both this gate and dev-hub's own
require_auth, reaching actual engine code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
omnibioai-auth's Phase 1 PR2 (github.com/OmniBioAI/omnibioai-auth#4) added
routes_orgs.py (router prefix "/orgs"), routes_teams.py and
routes_apikeys.py (both nested under "/orgs/{org_id}/..."), none of which
had a matching bare-path claim in this router. Without it, any request to
/orgs/* falls through to the catch-all `location /` (web-ui) and gets a
200 + index.html instead of a real response -- this file's own header
comment documents that exact failure mode having already bitten /license,
/roles, and /users/ before someone noticed. Added proactively this time
instead of waiting for a "blank page" bug report.

One location block covers all three new route files since they all nest
under the same /orgs prefix. Mirrors the existing /roles and /users/
blocks exactly (same rate limit zone, same proxy_pass target).

Not yet deployed -- per this file's own top-of-file warning, the running
nginx-router container has this file bind-mounted by inode, so picking
this up requires `docker compose up -d --no-deps --force-recreate
nginx-router`, not just a config reload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit 1630ec5 into main Aug 1, 2026
4 checks passed
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