Commit Graph

2182 Commits

Author SHA1 Message Date
KooshaPari
fa2f9e21a8 fix(image): keep bare gpt-5.5 codex mapping in image resolver (#5902)
* fix: preserve codex bare image model over combo shadowing

* docs(changelog): credit #5902 codex bare image alias fix

* docs(changelog): restore #5902 bullet after merge auto-resolve

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-07-02 06:14:45 -03:00
Diego Rodrigues de Sa e Souza
55e638c312 fix(dashboard): pre-fill Modal Validation Model Id with the server probe model (#5446) (#5892) 2026-07-02 02:54:32 -03:00
Diego Rodrigues de Sa e Souza
53fb1bef4a fix(dashboard): gate Token Expired badge on terminal testStatus, not raw token expiry (#5836) (#5883) 2026-07-02 02:47:04 -03:00
Diego Rodrigues de Sa e Souza
9dceb6289b fix(db): honor autoBackupEnabled setting for pre-write backups (#5871) (#5888) 2026-07-02 02:46:36 -03:00
Diego Rodrigues de Sa e Souza
2b9abebef8 fix(middleware): run operator hook code in hardened vm sandbox instead of new Function (#5872) (#5885) 2026-07-02 02:45:32 -03:00
Diego Rodrigues de Sa e Souza
16aeb08765 fix(dashboard): Modal — two-field auth (Token ID + Token Secret) (#5446) (#5881)
* fix(dashboard): add Modal Token ID + Token Secret fields (#5446)

Modal authenticates with a Token ID (ak-…) + Token Secret (as-…) pair sent as
`Authorization: Bearer <TOKEN_ID>:<TOKEN_SECRET>`. The add-connection form only
exposed a single API-key field, so users could not enter both credentials.

Add a dedicated two-field form for the `modal` provider: the existing field is
relabeled "Token ID" and a new "Token Secret" field is rendered below it. Both
are combined into the single encrypted `apiKey` value via a new pure helper
`combineModalCredential(id, secret)` → `id:secret`, so the generic bearer
executor path emits `Bearer <id:secret>` with no registry/executor/DB changes.
An empty secret returns the id verbatim, preserving the ability to paste a
pre-combined `id:secret` into the single field. The field hint points to
https://modal.com/settings → API Tokens.

Registry (baseUrl/executor), DB schema, and the request-time header path are
untouched — Modal remains bring-your-own-deploy.

Tests: tests/unit/modal-credential-combine.test.ts (5, TDD).

* docs(changelog): add v3.8.43 bullet for Modal two-field auth (#5446)
2026-07-02 02:40:30 -03:00
Diego Rodrigues de Sa e Souza
425324ad5c feat: add NEXT_PUBLIC_LIVE_WS_PUBLIC_URL for custom domain WebSocket support (#5878)
* docs: add ai_features scope to GitLab Duo OAuth env setup instructions

* docs: add LIVE_WS_ALLOWED_HOSTS env var to example config for LAN/Tailscale setups

* feat: add web socket public URL for reverse proxy/Cloudflare Tunnel WebSocket setups

* fix(dashboard): resolve live WS public URL at runtime via handshake with scheme validation

- Read NEXT_PUBLIC_LIVE_WS_PUBLIC_URL lazily in /api/v1/ws (function, not
  module-level const) so runtime env changes are honored in prebuilt images.
- Only echo/consume publicUrl when it is a ws:// or wss:// URL (server and
  client guards); anything else is rejected to null.
- useLiveDashboard now fetches /api/v1/ws?handshake=1 before connecting and
  prefers: explicit wsUrl > build-time env > handshake publicUrl > default.
- Align GitLab Duo scopes line in .env.example with GITLAB_DUO_CONFIG.scope.
- Extend tests: lazy env read + scheme validation cases.
- CHANGELOG entry for 3.8.43.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: Septianata Rizky Pratama <ian.rizkypratama@gmail.com>
2026-07-02 01:16:51 -03:00
Diego Rodrigues de Sa e Souza
5be3d81544 fix(github): keep Copilot access-token sessions active (#5875)
* fix(github): keep Copilot access-token sessions active

GitHub Copilot device-flow accounts may have a GitHub access token and short-lived Copilot token without a refresh token. The proactive health check was treating that as terminal no_refresh_token and marking the connection expired minutes after login. Keep those sessions active, clear stale no_refresh_token state, and refresh the Copilot sub-token when needed.\n\nTests:\n- npx eslint src/lib/tokenHealthCheck.ts tests/unit/token-health-no-refresh-token-expired-5326.test.ts\n- DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/token-health-no-refresh-token-expired-5326.test.ts tests/unit/token-health-check.test.ts tests/unit/token-health-check-circuit-breaker.test.ts tests/unit/token-refresh-service.test.ts tests/unit/token-refresh-route-service.test.ts tests/unit/executor-github.test.ts\n- npm run typecheck:core\n- npm run build

(cherry picked from commit 68095d4796)

* docs(changelog): credit Copilot token-health fix extraction from #5863

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: Wital <wital@example.com>
2026-07-02 00:38:03 -03:00
Diego Rodrigues de Sa e Souza
a205cb7f5e feat(usage): report usage command quotas as percentages + honor observed provider quota resets (#5874)
* feat: report usage command quotas as percentages

Convert @@om-usage and the HTTP usage endpoint to report personal API key quotas as remaining percentages while keeping USD amounts out of the command output. Scale provider quota remaining percentages by the configured quota cutoff so the protected reserve reads as 0% left. Restore provider USD cost drilldown in the quota dashboard.\n\nAlso sync the 3.8.43 i18n changelog mirrors so the docs-sync pre-commit gate remains green.\n\nTests: DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/internal-usage-command.test.ts; DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/api-key-usage-limits.test.ts; DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/provider-window-costs.test.ts; DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/api-manager-usage-command.test.ts tests/unit/apikeys-usage-command.test.ts; npx eslint <changed files>; npm run typecheck:core; npm run build; npm run check:migration-numbering; npm run check:docs-sync; docker build --target runner-base

(cherry picked from commit f66abd2028)

* fix: honor observed provider quota resets

Detect same-resetAt quota resets when provider usage drops back to the reset floor, and prefer that observed snapshot over stale recorded weekly events for provider USD windows and API-key USD quotas.\n\nTests: npx eslint changed files\nTests: npm run typecheck:core\nTests: DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx/esm --test tests/unit/lib/quota-reset-events.test.ts tests/unit/provider-window-costs.test.ts tests/unit/api-key-usage-limits.test.ts\nTests: npm run build\nTests: docker build --target runner-base --build-arg OMNIROUTE_BUILD_MEMORY_MB=4096 -t omniroute:quota-reset-window-20260702002300 .

(cherry picked from commit 39c12a6f17)

* docs(changelog): credit usage quota percentages extraction from #5863

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: Wital <wital@example.com>
2026-07-02 00:36:57 -03:00
Randi
595349a59a fix(chat): preserve JSON default when stream is omitted (#5866)
* fix(chat): preserve JSON default when stream is omitted

* chore(chat): type route record guard

* fix(api): gate early SSE keepalive on explicit stream intent, keep body untouched

Remove the stream:false body normalization so the legacy streaming
default (resolveStreamFlag) and the per-key streamDefaultMode json
opt-in keep deciding the response framing; the keepalive wrapper is
only applied when stream:true is explicit or Accept forces SSE.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-07-02 00:32:38 -03:00
Diego Rodrigues de Sa e Souza
02e73c5440 refactor(oauth): remove dead legacy OAuth service classes (#5838)
The src/lib/oauth/services/ service-class hierarchy is superseded — the live OAuth
flow runs through src/lib/oauth/providers.ts + providers/. The old per-provider
'class *Service extends OAuthService' implementations and their barrel had zero
production or test references. Removed oauth/openai/github/claude/codex/antigravity/
qwen/qoder + the index barrel (-1559 LOC). Kept kiro.ts, cursor.ts, codexImport.ts
(routes import them directly by path, never via the deleted barrel).

Proven safe by typecheck:core staying green (a live reference would fail the build)
+ a filesystem guard test pinning the removal. Salvage of closed PR #5039.
gaps v3.8.42 - T10 (5.7).
2026-07-02 00:25:19 -03:00
Nguyen Minh
f6100d67c7 [codex] Protect long-running agent goal streams (#5772)
Integrated into release/v3.8.43
2026-07-01 22:07:13 -03:00
WITALO ROCHA
cfb2db8261 fix: restore om-usage HTTP endpoint (#5859)
Integrated into release/v3.8.43
2026-07-01 22:03:17 -03:00
Nguyen Minh
9358eeada9 [codex] Tune adaptive stream readiness timeouts (#5767)
Integrated into release/v3.8.43
2026-07-01 22:02:51 -03:00
Nguyen Minh
19703cd6ec Harden provider node URL validation (#5760)
Integrated into release/v3.8.43
2026-07-01 22:02:36 -03:00
PizzaV
36167d7bb7 refactor(executors): deduplicate shared utilities and add comprehensive tests (#5720)
Integrated into release/v3.8.43
2026-07-01 22:02:22 -03:00
Markus Hartung
9bd0211da7 extracted CorrelationId observability changes from #5275 (#5834)
Integrated into release/v3.8.43
2026-07-01 22:02:08 -03:00
Chewji
e5e47eb61c fix(antigravity): 429 hang on credit exhaustion and precise reset time lockout (Cleaned) (#5846)
Integrated into release/v3.8.43
2026-07-01 22:01:26 -03:00
janeza2
057dc3abf3 fix(qwen-web): unblock validator + chat completion (retired endpoint + missing SPA version header) (#5855)
Integrated into release/v3.8.43
2026-07-01 22:01:11 -03:00
janeza2
b708aa7e75 fix(kimi-web): migrate to www.kimi.com Connect-RPC API (kimi.moonshot.cn retired) (#5858)
Integrated into release/v3.8.43
2026-07-01 22:00:57 -03:00
Randi
103a0ee2a2 fix: unify dashboard csrf origin fallback (#5856)
Integrated into release/v3.8.43
2026-07-01 22:00:43 -03:00
Yuan Li
7d7626151b fix(db): preserve healthCheckInterval=0 across create/update (#5822)
Integrated into release/v3.8.43
2026-07-01 22:00:18 -03:00
Diego Rodrigues de Sa e Souza
08dbf6f58a fix(mitm): clean up privileged hosts entries on exit when possible (#5808)
Integrated into release/v3.8.43
2026-07-01 21:58:01 -03:00
Diego Rodrigues de Sa e Souza
b55a330dc5 fix(oauth): disambiguate OAuth connections on username to prevent cross-IdP overwrites (#5803)
Integrated into release/v3.8.43
2026-07-01 21:55:30 -03:00
Diego Rodrigues de Sa e Souza
3323b5b617 fix(dashboard): guard null modelAliases values in model picker (#5792)
Integrated into release/v3.8.43
2026-07-01 21:53:56 -03:00
Diego Rodrigues de Sa e Souza
12ac520014 fix(cli): rename process title to omniroute (#5791)
Integrated into release/v3.8.43
2026-07-01 21:49:48 -03:00
Diego Rodrigues de Sa e Souza
512844710c fix(dashboard): add error boundaries for Combos and MITM Proxy pages (#5788)
Integrated into release/v3.8.43
2026-07-01 21:49:34 -03:00
Diego Rodrigues de Sa e Souza
948d2d7f21 fix(security): explicit http(s) scheme allowlist in linkifyText href
CodeQL flagged the <a href> in LinkifiedText (#5486) with js/xss (high)
and js/client-side-unvalidated-url-redirection (medium) because href
traces back to user-provided text. URL_RE already requires an http(s)://
prefix, so a javascript:/data: scheme can never reach href — but that
guarantee was only implied by the regex. Validate the scheme explicitly
via new URL().protocol before exposing href (non-http(s) degrades to
plain text): defense-in-depth that also makes the sink provably safe to
static analysis. Regression test added.
2026-07-01 13:10:49 -03:00
Diego Rodrigues de Sa e Souza
66c5b718cd fix(db): re-export modelContextOverrides from localDb (check:db-rules #5609) 2026-07-01 10:22:15 -03:00
Diego Rodrigues de Sa e Souza
7d07be9b20 fix(oauth): clamp grok-cli expired-token expiresIn to a positive value (#5775 follow-up) (#5820)
An already-expired grok-cli token (real expires_at/exp in the past) produced a
negative expiresIn, which is truthy in the import-token route and maps to a PAST
expiresAt — AutoCombo then reads that as 'already expired' and excludes the
connection instead of refreshing it. Clamp with Math.max(1, expiresIn) so an
expired token is treated as due-for-refresh. Extends #5775 (thanks @Chewji9875).

Regression: 2 new cases in tests/unit/grok-cli-oauth.test.ts (expired JWT exp +
expired JSON expires_at), both failing-then-passing.
2026-07-01 09:06:07 -03:00
Diego Rodrigues de Sa e Souza
10f00ef274 fix(system): route in-app auto-update npm calls through the win32 shell helper (#5542) (#5797)
The in-app auto-update flow called execFileAsync("npm", ...) directly for the
version lookup (versionCheck.getLatestVersionFromNpmCli), dependency install,
global install, and native rebuild. On Windows npm is npm.cmd and Node >=24
refuses to execFile a .cmd without a shell (nodejs/node#52554), so those calls
threw 'spawn npm ENOENT'. Route them through buildNpmExecOptions (the same
win32-shell helper the embedded-services installer uses, fix #5379). The global
install spec is validated with SERVICE_VERSION_PATTERN before it is shell-joined
(Hard Rule #13). Not the pnpm/npx swap the issue proposed — that is the wrong
direction for an 'npm install -g' flow already solved elsewhere in-repo.

Regression guard: tests/unit/autoupdate-npm-win32-5542.test.ts.
2026-07-01 04:37:28 -03:00
Diego Rodrigues de Sa e Souza
b9d717f3c9 fix(dashboard): neutral badge for unsupported validation + clickable OAuth error links (#5442, #5486) (#5795)
- #5442 LMArena (and any provider with no live validator) returns
  { unsupported: true } from /api/providers/validate and Save succeeds, but the
  Add-API-Key modal only had success/failed states so it rendered a red 'Invalid'
  badge. Add an 'unsupported' result → neutral info 'N/A' badge via the pure leaf
  validationBadgeProps(); both validate handlers now map data.unsupported to it.
- #5486 GitLab Duo's OAuth setup error embeds a registration URL
  (gitlab.com/-/profile/applications) but the OAuth error step rendered it as dead
  red text. New LinkifiedText component (+ pure ReDoS-safe linkify util) makes any
  http(s) URL in an OAuth error clickable; the GitLab Duo backend message already
  carries the full setup steps.

Regression guards: tests/unit/validation-badge-unsupported-5442.test.ts,
tests/unit/oauth-error-linkify-5486.test.ts. Frozen god-files kept within cap
(AddApiKeyModal 868/868, OAuthModal 968/969).
2026-07-01 04:34:22 -03:00
Diego Rodrigues de Sa e Souza
1c4c7caf06 fix(providers): correct stale/broken provider metadata (#5487, #5461, #5534, #5470) (#5790)
- #5487 Qoder: replace the untranslated i18n stubs (personalAccessTokenLabel,
  qoderPatHint, qoderPatPlaceholder) with real copy; extend the STUB_KEYS guard.
- #5461 Scaleway: website pointed at scaleway.com/en/ai/generative-apis (HTTP 404);
  repoint at the live docs URL /en/docs/ai-data/generative-apis/.
- #5534 Microsoft 365 Copilot: rewrite the vague authHint with concrete DevTools
  WebSocket steps (the token lives on the Chathub WS URL, not an Authorization header).
- #5470 Together AI: retired the $25 signup credit and is now fully prepaid (min $5);
  hasFree false + a prepaid notice instead of the stale free-tier freeNote (verified live).

Regression guards: tests/unit/provider-metadata-5461-5470-5534.test.ts + Qoder keys
added to tests/unit/provider-add-ux-i18n-import-warning.test.ts.
2026-07-01 04:26:23 -03:00
jleonar2
e2d2c2759b fix(api): self-hydrate model aliases from DB on GET after restart (#5777)
* Fix grammatical errors in readme (#5738)

* fix(api): self-hydrate model aliases from DB on GET when in-memory state is empty

In the standalone production build, webpack creates two separate copies of
modelDeprecation.ts — one hydrated by the startup path (used for request
routing) and one used by the /api/settings/model-aliases API route.  The
API route's copy starts with an empty _customAliases after each server
restart, causing the Settings → Routing UI to show 'No exact-match aliases
configured' even though the aliases are persisted in the DB.

The GET handler now detects an empty _customAliases state and reads the
modelAliases key from the settings blob in the DB, calling
setCustomAliases() to hydrate this module instance.  This is a best-effort
fallback — when _customAliases is already populated (e.g. by the startup
path in dev mode), no DB read occurs.

Regression test: tests/unit/model-aliases-settings-route-selfheal.test.ts
- Verifies hydration from DB when in-memory state is empty
- Verifies no hydration when in-memory state is already populated
- Verifies graceful handling when no modelAliases exist in DB

---------

Co-authored-by: Chirag Singhal <76880977+chirag127@users.noreply.github.com>
Co-authored-by: marcelpeterson <marcelpeterson@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-07-01 04:11:50 -03:00
Diego Rodrigues de Sa e Souza
ee5ee8b785 fix(providers): import intentional local-catalog-only providers instead of 502 (#5460, #5465) (#5787)
The model-sync route returned a hard 502 ('Remote model discovery failed;
local catalog fallback not synced') for every provider whose local catalog is
its ONLY discovery source (Reka #5460, t3.chat #5465, embedding/rerank like
voyage-ai/jina-ai, Qwen-OAuth, and web-cookie providers).

The /models route now flags catalogs that are the provider's intended source
(no remote /models endpoint) with intentional:true; model-sync imports those
instead of 502-ing, while a genuinely degraded remote fallback still surfaces.
New dependency-free leaf degradedLocalCatalog.ts.

Also fixes t3.chat's confusing add-credential hint: it no longer renders the
circular 'Required cookie: convex-session-id + Cookie header...' copy and wires
the step-by-step DevTools hint (t3ChatWebCookieHint) already translated in every
locale.

Regression guards: tests/unit/sync-models-degraded-local-catalog-5460-5465.test.ts,
tests/unit/t3chat-web-cookie-hint-5465.test.ts, + intentional-flag assertions in
tests/unit/provider-models-route.test.ts.
2026-07-01 04:09:50 -03:00
Chewji
5f92dad1d3 fix(grok-cli): parse expires_at from auth.json and exp from JWT to fix auto-refresh (#5775)
* fix(grok-cli): parse expires_at from auth.json and exp from JWT to fix auto-refresh

* docs(changelog): note grok-cli token auto-refresh fix (#5775)

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-07-01 04:07:41 -03:00
Randi
b50205fc5f Move CLI profile sync toggles to CLI Code (#5778)
* move CLI profile sync toggles to CLI Code

* test CLI profile auto-sync toggles

* Document CLI profile auto-sync flags

* docs(changelog): note CLI profile auto-sync card moved to CLI Code (#5778)

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
2026-07-01 04:06:07 -03:00
Alex
a219ab5ee3 Persist batch item checkpoints during recovery (#5753)
* fix(sse): checkpoint batch item recovery

* fix(db): renumber batch checkpoints migration 110→112 (collision with #5667)

110 was taken by 110_model_context_overrides.sql (#5667), which landed on the
release branch after this PR branched. migrationRunner throws a hard version-
collision error on startup when two files share a numeric prefix. 112 is the
next free slot (110/111 taken on the release tip).

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-07-01 01:24:22 -03:00
Diego Rodrigues de Sa e Souza
521772c082 fix(memory): enabling Qdrant activates it as the engine + inline guidance (#5597) (#5741)
* fix(memory): enabling Qdrant now activates it as the engine + inline guidance (#5597)

Enabling Qdrant in the Engine tab was inert: retrieval only routes to Qdrant when
memoryVectorStore === "qdrant" (the default "auto" never selects it), and the card
only wrote qdrantEnabled — nothing set the engine selector, and there is no UI for
it. So users configured Qdrant, saw "enabled", but it was never actually used.

- PUT /api/settings/qdrant now sets memoryVectorStore alongside the toggle:
  enable -> "qdrant", disable -> "auto". Editing other fields leaves it untouched.
- Add inline guidance to QdrantConfigCard: a Tier-1-vs-Tier-2 banner + per-field
  help (host, collection, embedding model). Note there is no "vector dimension" or
  "distance metric" field: dimension is auto-detected from the embedder, distance
  is always Cosine.
- Document the real behavior in MEMORY.md: engine gate, no back-fill of existing
  memories, dimension auto-detect, Cosine-only, API-key-only auth.

Tests: tests/integration/qdrant-routes.test.ts — enable->qdrant, disable->auto, and
field-edit-without-enabled leaves the engine untouched (TDD: red -> green).

Closes #5597

* fix(memory): invalidate memory-settings cache on Qdrant toggle (#5597)

The PUT handler wrote memoryVectorStore to the DB but retrieval reads through
getMemorySettings(), a module-level cache. Without busting it, the engine switch
did not take effect until a process restart (the DB said qdrant, retrieval kept
routing to sqlite-vec). Now calls invalidateMemorySettingsCache() after the write,
mirroring src/app/api/settings/memory/route.ts.

Regression test warms the cache, toggles via the route, and asserts
getMemorySettings().vectorStore flips to qdrant (fails without the invalidate call).
2026-07-01 01:15:46 -03:00
Diego Rodrigues de Sa e Souza
5d74f1d02a refactor(api): extract pure discovery leaves from provider-models route (#5758)
Split src/app/api/providers/[id]/models/route.ts (2511 -> 1818 LOC) by moving
the cohesive, DB-free discovery building blocks into four leaves under
discovery/:

- helpers.ts              record/string coercion, Azure + base-url helpers,
                          bearer/named-openai header builders
- normalizers.ts          Antigravity / DataRobot / OpenAI-like / SAP models
                          response normalizers
- providerModelsConfig.ts PROVIDER_MODELS_CONFIG + ProviderModelsConfigEntry
- providerSets.ts         NAMED_OPENAI_STYLE_PROVIDERS + isNamedOpenAIStyleProvider

The host keeps all request orchestration and imports the leaves back. The moved
symbols were module-private, so the route's public export set (GET) is unchanged
and no external importer needs updating. Bodies are byte-identical: the code-line
multiset of host + leaves equals the original route verbatim.

Tests:
- repoint the qwen-web source-guard in catalog-updates-v3829-kimi-qwen to the new
  config leaf (assertions unchanged)
- add provider-models-discovery-split as the split regression guard (leaf public
  surface + host wiring + the #5570 cablyai->aimlapi entry swap)
2026-07-01 01:14:35 -03:00
Diego Rodrigues de Sa e Souza
2260b31efd fix: surface relay proxy-test errors instead of silent failure (#5716) (#5765) 2026-07-01 01:11:58 -03:00
Diego Rodrigues de Sa e Souza
aa0ac7da87 docs(security): document full LOCAL_ONLY route set + GHSA-fhh6-4qxv-rpqj + audit path (#5599) (#5748)
Expand ROUTE_GUARD_TIERS.md Tier 1 (LOCAL_ONLY):
- link the GHSA advisory and explain the attack class (RCE via a subprocess spawn
  reachable from non-loopback traffic)
- replace the 3-example prefix table with the full LOCAL_ONLY set, mirroring
  LOCAL_ONLY_API_PREFIXES / LOCAL_ONLY_API_PATTERNS in routeGuard.ts (the
  authoritative source; check-route-guard-membership enforces the code side)
- add an "Operator guidance & auditing" section for users behind
  nginx/Cloudflare/Tailscale: don't forge X-Forwarded-For loopback, keep the
  manage-scope bypass minimal, and how to audit non-loopback access

Docs-only; SECURITY.md already links here.

Closes #5599
2026-07-01 01:09:20 -03:00
Diego Rodrigues de Sa e Souza
1fdea7a882 fix: onboarding wizard saves providers with unsupported validation (#5692) (#5764) 2026-07-01 01:06:39 -03:00
Diego Rodrigues de Sa e Souza
46e33e164d fix: point Quick Start step 1 to API Keys page, not Endpoint (#5695) (#5763) 2026-07-01 01:03:11 -03:00
Diego Rodrigues de Sa e Souza
ccbfca84dd fix: repoint DashScope/Alibaba setup links to consoles (#5665) (#5762) 2026-07-01 01:00:11 -03:00
Randi
9a03840adf fix(chat): harden non-streaming SSE aggregation (#5746) 2026-07-01 00:55:58 -03:00
Diego Rodrigues de Sa e Souza
b7fc200e52 fix(sse): anti-thundering-herd guard tolerates numeric-epoch cooldowns (#5747)
markAccountUnavailable's dedupe guard used a raw `new Date()` on
rateLimitedUntil, which can hold a numeric-epoch string (e.g. the
Antigravity full-quota path via setConnectionRateLimitUntil). That
produced Invalid Date/NaN, so the guard never detected an already
cooling connection — a second concurrent failure on the same
connection overwrote a long quota-exhaustion cooldown with a much
shorter fresh backoff cooldown, making the account selectable again
far sooner than intended.

Reuses the existing cooldownUntilMs normalizer (#3954) instead of a
raw Date parse.
2026-07-01 00:55:48 -03:00
Diego Rodrigues de Sa e Souza
fbcfafd201 feat(providers): opt-in CLI profile auto-sync toggles + Claude Code auto-sync (#5755)
Providers-dashboard 'CLI profile auto-sync' card (Codex + Claude Code toggles), feature-flag backed (default off), + Claude Code auto-sync mirroring the Codex path. Follow-up to #5737.
2026-07-01 00:13:20 -03:00
skyzea1
f3b5dc3533 feat(codex): opt-in auto-sync of Codex profiles after model discovery (#5737)
Auto-sync ~/.codex/*.config.toml profiles after a provider model sync, reusing the setup-codex generator. Opt-in, default OFF (OMNIROUTE_AUTO_SYNC_CODEX_PROFILES=true; also honors CLI_ALLOW_CONFIG_WRITES). Never touches the active Codex config. Gating test added.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-06-30 23:51:41 -03:00
WITALO ROCHA
dafeb42baf feat(api): add opt-in API-key provider quota-policy bypass scope (#5731)
Adds an opt-in per-API-key scope (policy:bypass-provider-quota) that lets a key skip provider/account-side quota cutoffs during routing. Operator USD budgets/usage limits still enforced unconditionally (fail-closed, before the bypass). Default-off; UI toggle + badge in API Manager. Integrated into release/v3.8.43.
2026-06-30 23:45:29 -03:00