Skip to content

feat!: remove gateway/GATEWAY_ and pre-rename legacy aliases#314

Open
njbrake wants to merge 3 commits into
mainfrom
feat/remove-legacy-aliases
Open

feat!: remove gateway/GATEWAY_ and pre-rename legacy aliases#314
njbrake wants to merge 3 commits into
mainfrom
feat/remove-legacy-aliases

Conversation

@njbrake

@njbrake njbrake commented Jul 17, 2026

Copy link
Copy Markdown
Member

Description

Follow-up to #142 (the "Otari Gateway" to "Otari" rename), which kept the old names working for backward compatibility. The deprecation window has passed, so this retires them. Per the issue's open question, this also folds in the older pre-rename aliases.

Removed:

  • the gateway console-script alias (pyproject.toml); the CLI is otari
  • the GATEWAY_ environment prefix: the native pydantic env_prefix (now OTARI_, which also lets complex fields be set via env), the otari_env() fallback / LEGACY_ENV_PREFIX (core/env.py), the GATEWAY_MODE alias, and the alembic GATEWAY_DATABASE_URL fallback
  • the pre-rename AnyLLM-Key / X-AnyLLM-Key request-header aliases
  • the pre-rename OTARI_PLATFORM_TOKEN / ANY_LLM_PLATFORM_TOKEN platform-token env aliases; only OTARI_AI_TOKEN remains

Kept intentionally (out of scope per the issue):

  • the gateway Python import package (the otari PyPI name belongs to the client SDK)
  • internal identifiers, Prometheus metric names, the logger name
  • the /gateway/... platform wire-protocol paths and the X-Gateway-Token header (contract surface, not product naming)

Tests that asserted the legacy names worked are inverted to assert they are now ignored (legacy env prefix ignored, legacy headers return 401, legacy token env leaves the gateway standalone).

Note: the issue's suggested sequence had a "ship a release carrying deprecation warnings" step before removal. No runtime deprecation warnings were found in the code, so this goes straight to removal. Flagging in case a warnings release is wanted first.

PR Type

  • New Feature
  • Bug Fix
  • Refactor
  • Documentation
  • Infrastructure / CI

This is a breaking change (removes recognized CLI/env/header names); see the BREAKING CHANGE: footer on the commit.

Relevant issues

Fixes #157

Checklist

  • I understand the code I am submitting.
  • I have added or updated tests that cover my change (tests/unit, tests/integration).
  • I ran the Definition of Done checks locally (make lint, make typecheck, make test).
  • Documentation was updated where necessary.
  • If the API contract changed, I regenerated the OpenAPI spec (uv run python scripts/generate_openapi.py).

Note on make test: unit tests pass (665 passed, 1 skipped). The Postgres/Testcontainers integration tests could not run in the dev sandbox (no Docker); the SQLite-based integration tests (config loading, hybrid mode, dispatch, batches) pass. CI runs the full Postgres suite.

AI Usage

  • No AI was used.
  • AI was used for drafting/refactoring.
  • This is fully AI-generated.

AI Model/Tool used: Claude Code (Opus 4.8)

Any additional AI details you'd like to share: Drafted via back-and-forth with @njbrake; the scope decision (folding in the pre-rename aliases) and the direction are his.

NOTE:
When responding to reviewer questions, please respond yourself rather than copy/pasting reviewer comments into an AI and pasting back its answer. We want to discuss with you, not your AI :)

  • I am an AI Agent filling out this form (check box if true)

Summary by CodeRabbit

  • Configuration

    • Standardized configuration to use the OTARI_ environment variable prefix only.
    • Removed legacy GATEWAY_ environment-variable fallbacks, including related sandbox/web-search URL settings and database URL resolution.
    • Adjusted dev startup defaults to use OTARI_HOST/OTARI_PORT.
  • Authentication

    • Kept the supported auth headers as Otari-Key and Authorization: Bearer ....
    • Removed support for legacy AnyLLM-Key / X-AnyLLM-Key request-header aliases.
    • Tightened validation so hybrid/standalone mode selection is driven by OTARI_AI_TOKEN.
  • CLI / Entrypoints

    • Removed the legacy gateway console-script alias; only otari remains.
  • Documentation & security guidance

    • Updated docs and the SSRF/request-forwarding security checklist to reference OTARI_SANDBOX_URL / OTARI_WEB_SEARCH_URL.
    • Removed documentation guidance that mentioned legacy GATEWAY_ precedence/fallbacks and legacy header names.
  • Tests

    • Updated and expanded integration/unit tests to ensure legacy environment variables and headers are ignored (or rejected) and that only OTARI_-based behavior is accepted.

Technical notes

  • Legacy aliases removed include GATEWAY_ env prefix fallbacks, GATEWAY_MODE / GATEWAY_DATABASE_URL, AnyLLM-Key / X-AnyLLM-Key, and legacy platform-token environment aliases (while keeping OTARI_AI_TOKEN as the controlling token source).
  • Routing/backend selection tests were updated to use OTARI_SANDBOX_URL / OTARI_WEB_SEARCH_URL.

The Otari rename (#142) kept the old names working for backward
compatibility. The deprecation window has passed, so this retires them.

Removed:
- the `gateway` console-script alias (pyproject.toml); the CLI is `otari`
- the `GATEWAY_` environment prefix: the native pydantic env_prefix (now
  `OTARI_`, which also covers complex fields), the `otari_env()` fallback
  in core/env.py, the `GATEWAY_MODE` alias, and the alembic
  `GATEWAY_DATABASE_URL` fallback
- the pre-rename `AnyLLM-Key` / `X-AnyLLM-Key` request-header aliases
- the pre-rename `OTARI_PLATFORM_TOKEN` / `ANY_LLM_PLATFORM_TOKEN` platform
  token env aliases; only `OTARI_AI_TOKEN` remains

Kept intentionally: the `gateway` import package, internal identifiers,
metric and logger names, and the `/gateway/...` platform wire-protocol
paths and `X-Gateway-Token` header (contract surface, not product naming).

Tests that asserted the legacy names worked now assert they are ignored.

BREAKING CHANGE: the `gateway` CLI command, the `GATEWAY_` env prefix, the
`AnyLLM-Key` / `X-AnyLLM-Key` headers, and the `OTARI_PLATFORM_TOKEN` /
`ANY_LLM_PLATFORM_TOKEN` token env vars are no longer recognized. Use
`otari`, `OTARI_` env vars, the `Otari-Key` header, and `OTARI_AI_TOKEN`.

Fixes #157

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@njbrake
njbrake temporarily deployed to integration-tests July 17, 2026 19:26 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2d58a7a5-b492-410e-b04c-7ef50aa7da11

📥 Commits

Reviewing files that changed from the base of the PR and between 14a031e and 5ea5653.

📒 Files selected for processing (3)
  • .github/instructions/security-review.instructions.md
  • src/gateway/core/config.py
  • tests/unit/test_url_safety.py
💤 Files with no reviewable changes (1)
  • tests/unit/test_url_safety.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/instructions/security-review.instructions.md
  • src/gateway/core/config.py

Walkthrough

The change removes legacy GATEWAY_, platform-token, AnyLLM authentication, and gateway CLI aliases. Configuration, authentication, runtime references, backend tests, and documentation now use canonical OTARI_ names.

Changes

Legacy alias removal

Layer / File(s) Summary
Canonical OTARI configuration and token resolution
src/gateway/core/..., tests/integration/test_config_env_loading.py, tests/integration/test_batches_endpoint.py, tests/integration/test_hybrid_mode_*
Configuration reads OTARI_ variables, treats empty values as unset, uses OTARI_AI_TOKEN for mode selection, and ignores legacy aliases.
Canonical authentication headers
src/gateway/api/deps.py, src/gateway/main.py, tests/unit/test_extract_bearer_token.py, docs/api-reference.md
Bearer extraction and CORS handling retain canonical headers while removing AnyLLM aliases.
Runtime entry points and operator references
pyproject.toml, Makefile, alembic/env.py, AGENTS.md, .github/..., docs/..., scripts/web-search-*/app.py
Runtime commands, database configuration, guidance, and adapter instructions use current Otari names; the gateway script alias is removed.
Canonical backend environment coverage
tests/integration/test_*route_dispatch.py, tests/integration/test_hybrid_mode_chat.py, tests/unit/test_*
Sandbox, web-search, SSRF, URL-safety, and settlement tests use OTARI_ environment variables while retaining existing assertions and route coverage.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • mozilla-ai/otari#142: Introduced the OTARI-preferred and GATEWAY-fallback environment handling that this change removes.
  • mozilla-ai/otari#163: Shares the mode-selection and platform-token configuration path.
  • mozilla-ai/otari#280: Shares the configuration loading and YAML-to-environment precedence paths.

Suggested reviewers: tbille

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title matches the change, but feat!: is not one of the required Conventional Commit prefixes. Use a valid prefix such as feat: and keep the title imperative, e.g. feat: remove legacy gateway aliases.
Docstring Coverage ⚠️ Warning Docstring coverage is 34.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description follows the template and includes the required sections, issue reference, checklist, and AI usage details.
Linked Issues check ✅ Passed The PR removes the requested legacy CLI and GATEWAY_ aliases and keeps the explicitly preserved package and protocol surfaces.
Out of Scope Changes check ✅ Passed The docs, tests, and alias-removal edits all support the stated cleanup rather than introducing unrelated work.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/remove-legacy-aliases
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/remove-legacy-aliases

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from tbille July 17, 2026 19:28
…fallbacks

Making OTARI_ the native pydantic env_prefix meant a blank OTARI_MASTER_KEY
(common from container templating) read as "" instead of unset. On the shared
auth path _is_valid_master_key only guards `is not None`, so an empty bearer
token would then match an empty master key. Set env_ignore_empty=True so the
native prefix skips empty values, matching the empty-skip in
_apply_otari_env_overrides, and add a regression test.

Also drop the leftover GATEWAY_HOST / GATEWAY_PORT shell fallbacks from the
`make dev` target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@njbrake
njbrake temporarily deployed to integration-tests July 17, 2026 19:32 — with GitHub Actions Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unit/test_web_search_backend.py (1)

557-566: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exercise the canonical environment variable in this test.

The docstring says this case is reached via OTARI_WEB_SEARCH_MAX_RESULTS, but the test only passes bad_value directly to WebSearchBackend. Add an environment-resolution assertion, or remove this claim and cover the OTARI_ mapping separately.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_web_search_backend.py` around lines 557 - 566, Update
test_max_results_clamps_subone_to_one to exercise the canonical
OTARI_WEB_SEARCH_MAX_RESULTS environment-variable resolution described in its
docstring, asserting that a non-positive environment value is clamped to 1;
alternatively, remove that environment-variable claim from the docstring and add
separate coverage for the OTARI_ mapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/instructions/security-review.instructions.md:
- Line 141: In the security review instruction text, replace the em dash
separating the operator-controlled URL statement from the per-request override
warning with a colon, preserving the wording and meaning of the documentation.

In `@AGENTS.md`:
- Line 37: Add blank lines before and after the headings in the AGENTS.md
sections “Request lifecycle (chat completions)” and the headings at the
referenced locations, including those near lines 44, 55, and 60, so they satisfy
Markdownlint MD022 without changing the documentation content.

In `@src/gateway/core/config.py`:
- Around line 633-644: Update the validation messages in the configured_mode
checks within the configuration loading method to refer to the configured mode
rather than explicitly naming OTARI_MODE. Preserve the existing guidance about
required tokens and standalone-mode conflicts while ensuring the wording is
accurate for values originating from either environment variables or
gateway.yml.

In `@tests/unit/test_url_safety.py`:
- Line 92: Remove the duplicate monkeypatch.delenv call in the affected URL
safety test, keeping only the preceding statement that clears
OTARI_WEB_SEARCH_ALLOW_PRIVATE_HOSTS.
- Line 82: Remove the redundant monkeypatch.delenv call before
monkeypatch.setenv in the affected test, leaving setenv to overwrite
OTARI_MCP_ALLOW_PRIVATE_HOSTS directly.

---

Outside diff comments:
In `@tests/unit/test_web_search_backend.py`:
- Around line 557-566: Update test_max_results_clamps_subone_to_one to exercise
the canonical OTARI_WEB_SEARCH_MAX_RESULTS environment-variable resolution
described in its docstring, asserting that a non-positive environment value is
clamped to 1; alternatively, remove that environment-variable claim from the
docstring and add separate coverage for the OTARI_ mapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2523536a-aa6f-4dcc-9049-320d45d72e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 0c3542b and 14a031e.

📒 Files selected for processing (26)
  • .github/instructions/security-review.instructions.md
  • .github/skills/backend-standards/SKILL.md
  • AGENTS.md
  • Makefile
  • alembic/env.py
  • docs/api-reference.md
  • docs/configuration.md
  • pyproject.toml
  • scripts/web-search-brave-adapter/app.py
  • scripts/web-search-tavily-adapter/app.py
  • src/gateway/api/deps.py
  • src/gateway/core/config.py
  • src/gateway/core/env.py
  • src/gateway/main.py
  • tests/integration/test_batches_endpoint.py
  • tests/integration/test_config_env_loading.py
  • tests/integration/test_hybrid_mode_chat.py
  • tests/integration/test_hybrid_mode_messages.py
  • tests/integration/test_hybrid_mode_responses.py
  • tests/integration/test_messages_route_dispatch.py
  • tests/integration/test_responses_route_dispatch.py
  • tests/unit/test_extract_bearer_token.py
  • tests/unit/test_otari_env_helper.py
  • tests/unit/test_pipeline_settlement.py
  • tests/unit/test_url_safety.py
  • tests/unit/test_web_search_backend.py
💤 Files with no reviewable changes (2)
  • pyproject.toml
  • docs/api-reference.md

Comment thread .github/instructions/security-review.instructions.md Outdated
Comment thread AGENTS.md
- **Hybrid**: per-request provider credentials are resolved from the platform service (otari.ai); local DB/user/budget management is skipped and usage is reported upstream. `register_routers()` (`src/gateway/api/main.py`) only mounts `chat`, `messages`, `responses`, and `health`; management routers (keys/users/budgets/pricing/usage/etc.) are standalone-only.
- Hybrid mode spans two trust contexts that this codebase treats identically: a gateway someone self-hosts against otari.ai using a workspace's own (BYO) provider keys, and the gateway mozilla.ai operates as part of otari.ai, which additionally serves mozilla.ai-managed models. The managed-vs-BYO boundary (platform-owned upstream credentials are returned only to mozilla.ai's gateway, never to a self-hosted one) is enforced on the platform side (otari-ai), not here. User-facing explanation lives in `docs/modes.md`; the wire contract in `docs/hybrid-mode-protocol.md`.

### Request lifecycle (chat completions)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdown heading spacing warnings.

markdownlint-cli2 reports MD022 at Lines [37], [44], [55], and [60]. Add the required blank lines around these headings so the documentation lint passes.

Also applies to: 44-44, 55-55, 60-60

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 37-37: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` at line 37, Add blank lines before and after the headings in the
AGENTS.md sections “Request lifecycle (chat completions)” and the headings at
the referenced locations, including those near lines 44, 55, and 60, so they
satisfy Markdownlint MD022 without changing the documentation content.

Source: Linters/SAST tools

Comment thread src/gateway/core/config.py Outdated
Comment thread tests/unit/test_url_safety.py Outdated
Comment thread tests/unit/test_url_safety.py Outdated
@njbrake
njbrake requested a review from khaledosman July 17, 2026 23:43
…ruft

- Make the mode-validation error messages source-agnostic (mode can be set
  via OTARI_MODE or the config `mode` field), rather than always naming
  OTARI_MODE.
- Drop a redundant delenv-then-setenv and a duplicate delenv in
  test_url_safety.py left over from the mechanical GATEWAY_ -> OTARI_ rename.
- Replace an em dash with a colon in the security-review instructions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Remove gateway/GATEWAY_ legacy aliases after the Otari rename deprecation window

1 participant