merge(release): reconcile absolute final remote tip 67fba531 (#8875)

This commit is contained in:
diegosouzapw
2026-08-23 22:31:02 -03:00
95 changed files with 2024 additions and 598 deletions

View File

@@ -65,6 +65,12 @@ INITIAL_PASSWORD=CHANGEME
# OMNIROUTE_RELEASE_REF=origin/main
# OMNIROUTE_ALLOW_CANARY_BUILD=1
# Build-phase signal (#10060). Set to 1 by scripts/build/build-next-isolated.mjs and
# inherited by every spawned build worker so the DB layer returns a no-op stub instead
# of loading the native better-sqlite3 addon (which aborts the worker on exit).
# Never set this for the running server. Used by: src/lib/buildPhase.ts, src/lib/db/core.ts
# OMNIROUTE_BUILDING=1
# Encryption key for SQLite database encryption at rest.
# Used by: src/lib/db/encryption.ts — encrypts the entire SQLite database.
# Generate: openssl rand -hex 32 | Leave empty to disable DB encryption.

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -12,7 +12,7 @@ import {
isFatalInstrumentationHookFailure,
formatAndroidInstrumentationFailureHint,
} from "../utils/ensureAndroidCacheDir.mjs";
import { resolveServerHost } from "../utils/serverHost.mjs";
import { resolveServerHost, resolveExposureWarning } from "../utils/serverHost.mjs";
import {
resolveMaxOldSpaceMb,
calibrateHeapFallbackMb,
@@ -162,6 +162,15 @@ export async function runServe(opts = {}) {
`);
}
// GHSA-wmgv-ph3p-rv57: the default posture (all interfaces + no API key) is a
// deliberate local-first choice, but it must be loud at startup — an operator
// on an untrusted network learns the two escape hatches here, not after a
// surprise quota bill.
const exposureWarning = resolveExposureWarning();
if (exposureWarning) {
console.warn(`\x1b[33m ⚠ ${exposureWarning}\x1b[0m\n`);
}
const serverWsJs = join(APP_DIR, "server-ws.mjs");
const serverJs = existsSync(serverWsJs) ? serverWsJs : join(APP_DIR, "server.js");
@@ -414,7 +423,9 @@ async function runWithSupervisor(
if (detectMitmCrash(crashLog)) {
try {
const PROJECT_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
const { updateSettings } = await import(pathToFileURL(join(PROJECT_ROOT, "src/lib/db/settings.ts")).href);
const { updateSettings } = await import(
pathToFileURL(join(PROJECT_ROOT, "src/lib/db/settings.ts")).href
);
updateSettings({ mitmEnabled: false });
} catch {}
return "disable-mitm-and-retry";

View File

@@ -24,3 +24,34 @@ export function resolveServerHost(
}
return "0.0.0.0";
}
const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
/**
* Boot-time exposure warning (GHSA-wmgv-ph3p-rv57): the shipped default binds
* all interfaces while the inference plane requires no credentials, so any
* LAN peer can spend the operator's quota. That local-first posture is a
* deliberate, documented default — but it must be LOUD at startup so an
* operator who never read the docs still learns the two escape hatches.
*
* Returns the warning text when the server will listen on a non-loopback
* interface with no API-key requirement, or null when the exposure is closed.
*
* @param {NodeJS.ProcessEnv} [env]
* @param {string} [host]
* @returns {string | null}
*/
export function resolveExposureWarning(env = process.env, host = resolveServerHost(env)) {
if (LOOPBACK_HOSTS.has(host)) return null;
const requireKey = String(env.REQUIRE_API_KEY || "")
.trim()
.toLowerCase();
if (requireKey === "true" || requireKey === "1" || requireKey === "yes") return null;
return (
`SECURITY: listening on ${host} with NO API-key requirement — the inference ` +
`plane (/v1/*) is reachable by ANY device that can route to this host, and ` +
`requests are billed to your configured providers. This local-first default ` +
`is intentional, but on an untrusted network either set REQUIRE_API_KEY=true ` +
`or bind loopback with OMNIROUTE_SERVER_HOST=127.0.0.1.`
);
}

View File

@@ -1,5 +1,9 @@
{
"_comment": "Allowlist anti-slopsquatting (check-deps.mjs). Toda dep nova exige adicao EXPLICITA aqui apos verificar que e legitima.",
"_justifications": {
"@testing-library/dom": "Peer dep obrigatoria de @testing-library/react v16 (adicionada no PR #11224); Refs #9985.",
"@testing-library/user-event": "Utilitario oficial do ecossistema testing-library para testes de UI (adicionada no PR #11224); Refs #9985."
},
"allowed": [
"@atjsh/llmlingua-2",
"@aws-sdk/client-bedrock-runtime",
@@ -20,8 +24,10 @@
"@stryker-mutator/tap-runner",
"@swc/helpers",
"@tailwindcss/postcss",
"@testing-library/dom",
"@testing-library/jest-dom",
"@testing-library/react",
"@testing-library/user-event",
"@toon-format/toon",
"@types/better-sqlite3",
"@types/bun",

View File

@@ -1207,7 +1207,7 @@
},
"src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx": {
"react-hooks/immutability": {
"count": 3
"count": 2
}
},
"src/app/(dashboard)/dashboard/endpoint/components/A2ADashboard.tsx": {
@@ -1402,11 +1402,6 @@
"count": 1
}
},
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/EditConnectionModal.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/dashboard/providers/[id]/components/modals/ImportCodexAuthModal.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
@@ -3186,7 +3181,7 @@
},
"src/lib/providers/validation/webProvidersA.ts": {
"@typescript-eslint/no-unused-vars": {
"count": 2
"count": 1
}
},
"src/lib/providers/validation/webProvidersB.ts": {
@@ -4663,10 +4658,10 @@
},
"tests/unit/cli-combo-suggest-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 16
"count": 14
},
"@typescript-eslint/no-unused-vars": {
"count": 2
"count": 1
}
},
"tests/unit/cli-completion-dynamic.test.ts": {
@@ -4676,7 +4671,7 @@
},
"tests/unit/cli-compression-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 32
"count": 24
}
},
"tests/unit/cli-context-eng-commands.test.ts": {
@@ -4765,9 +4760,6 @@
"tests/unit/cli-oneproxy-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 22
},
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"tests/unit/cli-open-command.test.ts": {
@@ -4837,9 +4829,6 @@
"tests/unit/cli-resilience-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 16
},
"@typescript-eslint/no-unused-vars": {
"count": 2
}
},
"tests/unit/cli-runtime-extended.test.ts": {
@@ -4872,7 +4861,7 @@
},
"tests/unit/cli-skills-commands.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 22
"count": 16
}
},
"tests/unit/cli-stop-supervisor-respawn-9455.test.ts": {
@@ -6561,7 +6550,7 @@
},
"tests/unit/search-route.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 7
"count": 6
},
"@typescript-eslint/no-unused-vars": {
"count": 1

View File

@@ -29,13 +29,28 @@ The Agent Card's `version` field is sourced from `process.env.npm_package_versio
## Authentication
All `/a2a` requests require an API key via the `Authorization` header:
A2A follows OmniRoute's configured authentication posture. With `REQUIRE_API_KEY=true`, callers
must provide a valid OmniRoute API key. When an explicit `OMNIROUTE_API_KEY` is configured, the
bearer must match it. When neither posture requires a key, the local-first keyless mode remains
available.
Authenticated callers send the key through the `Authorization` header:
```
Authorization: Bearer YOUR_OMNIROUTE_API_KEY
```
If no API key is configured on the server, authentication is bypassed.
Task authorization is independent from endpoint admission:
| Scope | Caller | Visible tasks |
| :---------- | :------------------------------------------------------------- | :-------------------------------------------------- |
| `operator` | Authenticated management/dashboard session on REST task routes | All owned and ownerless tasks |
| `owner` | Accepted API-key/bearer caller | Tasks owned by the same caller plus ownerless tasks |
| `ownerless` | Keyless local-first caller | Ownerless tasks only |
A task's authorization owner is stored privately and is never included in REST or JSON-RPC task
objects. Requests for another owner's task return the same not-found response as an unknown task
ID.
## Enablement
@@ -141,13 +156,13 @@ curl -X POST http://localhost:20128/a2a \
OmniRoute exposes 6 A2A skills wired in `src/lib/a2a/taskExecution.ts::A2A_SKILL_HANDLERS`. Each skill module lives in `src/lib/a2a/skills/`.
| Skill | ID | Description | Tags | Examples |
| :----------------- | :------------------- | :-------------------------------------------------------------------------------------------------------------- | :------------------------- | :------------------------------------- |
| Smart Routing | `smart-routing` | Routes a prompt through the optimal provider/combo using OmniRoute's combo engine + scoring | routing, providers | "Route this prompt via the best model" |
| Quota Management | `quota-management` | Reports per-provider quota state, helps callers decide when to throttle/switch | quota, providers | "Check quota for anthropic" |
| Provider Discovery | `provider-discovery` | Lists installed providers with capabilities, free-tier flags, OAuth status | providers, discovery | "What providers are available?" |
| Cost Analysis | `cost-analysis` | Estimates cost of a request/conversation given the catalog + recent usage | cost, usage | "Estimate cost for this conversation" |
| Health Report | `health-report` | Aggregates circuit breaker, cooldown, lockout state per provider | health, resilience | "Show health status of all providers" |
| Skill | ID | Description | Tags | Examples |
| :----------------- | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------- | :------------------------------------- |
| Smart Routing | `smart-routing` | Routes a prompt through the optimal provider/combo using OmniRoute's combo engine + scoring | routing, providers | "Route this prompt via the best model" |
| Quota Management | `quota-management` | Reports per-provider quota state, helps callers decide when to throttle/switch | quota, providers | "Check quota for anthropic" |
| Provider Discovery | `provider-discovery` | Lists installed providers with capabilities, free-tier flags, OAuth status | providers, discovery | "What providers are available?" |
| Cost Analysis | `cost-analysis` | Estimates cost of a request/conversation given the catalog + recent usage | cost, usage | "Estimate cost for this conversation" |
| Health Report | `health-report` | Aggregates circuit breaker, cooldown, lockout state per provider | health, resilience | "Show health status of all providers" |
| List Capabilities | `list-capabilities` | Returns the full 45-entry Agent Skills catalog (23 API + 21 CLI + 1 config) as a markdown table with raw SKILL.md URLs for context injection | catalog, discovery, skills | "List all OmniRoute capabilities" |
> The Agent Card should be kept aligned with the live 329-provider catalog; provider counts and free/no-auth metadata are sourced from the runtime registry.
@@ -171,14 +186,14 @@ Each row includes the `rawUrl` column so agents can immediately fetch the full S
The JSON-RPC endpoint `/a2a` is the canonical A2A entry point. The REST endpoints below provide auxiliary access for dashboards and external tooling:
| Endpoint | Method | Description | Auth |
| :--------------------------- | :----- | :------------------------------- | :--------------------- |
| `/api/a2a/status` | GET | Server status, registered skills | (public) |
| `/api/a2a/tasks` | GET | List tasks with filters | management |
| `/api/a2a/tasks/[id]` | GET | Get task by ID | management |
| `/api/a2a/tasks/[id]/cancel` | POST | Cancel running task | management |
| `/.well-known/agent.json` | GET | Agent Card (A2A discovery) | (public, cached 3600s) |
| `/api/a2a/tasks` | POST | Inbound delegation to the OmniConductor fleet (Conductor PRD RF5) | Bearer vs `OMNIROUTE_API_KEY` + `a2aEnabled` |
| Endpoint | Method | Description | Auth |
| :--------------------------- | :----- | :---------------------------------------------------------------- | :--------------------------------------------------------------------------------------- |
| `/api/a2a/status` | GET | Server status, registered skills | (public) |
| `/api/a2a/tasks` | GET | List tasks with scoped `total`, filters and pagination | Management session (`operator`), API key (`owner`), or keyless local-first (`ownerless`) |
| `/api/a2a/tasks/[id]` | GET | Get a task visible to the caller's scope | Management session (`operator`), API key (`owner`), or keyless local-first (`ownerless`) |
| `/api/a2a/tasks/[id]/cancel` | POST | Cancel a task visible to the caller's scope | Management session (`operator`), API key (`owner`), or keyless local-first (`ownerless`) |
| `/.well-known/agent.json` | GET | Agent Card (A2A discovery) | (public, cached 3600s) |
| `/api/a2a/tasks` | POST | Inbound delegation to the OmniConductor fleet (Conductor PRD RF5) | Shared A2A bearer posture (`REQUIRE_API_KEY` / `OMNIROUTE_API_KEY`) + `a2aEnabled` |
**Inbound Conductor delegation (`POST /api/a2a/tasks`):** external A2A agents delegate coding work to the OmniConductor fleet through OmniRoute. Body: `{ skill: "conductor" | "conductor-cli-<profile>", messages: [{role, content}], metadata: { conductor: { repo: { url, base_ref? }, mode?, cli?, model? } } }` — only Conductor fleet skills (the ones announced on the Agent Card) are delegable; `metadata.conductor.repo.url` is required (the fleet works on git repos). The route translates to the hub's `POST /v1/tasks` using the server-side `CONDUCTOR_ORCHESTRATOR_TOKEN` (fallback `CONDUCTOR_HUB_TOKEN`) and returns `201 { conductor_task_id, state: "submitted" }`; task states flow back through the SSE→A2A mirror (RF1) and are visible via `GET /api/a2a/tasks?skill=conductor`.
@@ -222,7 +237,11 @@ The JSON-RPC endpoint `/a2a` is the canonical A2A entry point. The REST endpoint
## Task TTL
Tasks expire after `ttlMinutes` (default 5 min) — configured in the `A2ATaskManager` constructor at `src/lib/a2a/taskManager.ts:82`. To customize, fork the `A2ATaskManager` instantiation and pass a different value (e.g., `new A2ATaskManager(15)` for 15-minute TTL). A background interval sweeps expired tasks every 60 seconds.
Tasks expire after `ttlMinutes` (default 5 min) — configured in
`A2ATaskManager::constructor` in `src/lib/a2a/taskManager.ts`. To customize, fork the
`A2ATaskManager` instantiation and pass a different value (for example,
`new A2ATaskManager(15)` for a 15-minute TTL). A background interval sweeps expired tasks every
60 seconds.
---

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1240,6 +1240,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1560,7 +1562,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1619,6 +1621,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1650,6 +1653,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1664,7 +1668,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1693,7 +1697,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1709,6 +1713,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1238,6 +1238,8 @@ _Living section — reconciled 2026-08-23 from all cycle commits (cycle open `ed
- **fix(ollama):** preserve every capability advertised by self-hosted Ollama models and defer chat selection to read time, so embedding and image routes accept eligible models without leaking endpoint-only models into provider wildcards or Auto-Combo; image retries remain restricted to the connections that advertised the selected model ([#11271](https://github.com/diegosouzapw/OmniRoute/pull/11271), corrected release-line port of [#11088](https://github.com/diegosouzapw/OmniRoute/pull/11088) for [#11087](https://github.com/diegosouzapw/OmniRoute/issues/11087) — thanks @yourspraveen)
- **fix(providers):** clamp out-of-vocabulary `reasoning_effort` values to the nearest tier declared by the exact provider/model, so `opencode-go/ox-alpha-free` maps the `medium` default to `high` while undeclared models remain pass-through ([#11274](https://github.com/diegosouzapw/OmniRoute/pull/11274) — thanks @linhdmn and @hartmark); builds on the learned accepted-set clamp from [#11232](https://github.com/diegosouzapw/OmniRoute/pull/11232) by @maxmad64bis
- **fix(security):** replace the GitHub Copilot correlation-ID fallback's `Math.random()` with CSPRNG bytes from `node:crypto` and make the Windows shell-argument test helper undo doubled backslashes and escaped quotes in one left-to-right pass, clearing CodeQL `js/insecure-randomness` and `js/double-escaping` while keeping `crypto.randomUUID()` as the primary path ([#11293](https://github.com/diegosouzapw/OmniRoute/pull/11293) — thanks @hartmark)
- **fix(security):** protect legacy settings export/import, make MITM and root-CA management routes local-only and spawn-capable, reject cloud-metadata search overrides, authenticate and owner-scope A2A tasks, and warn when the CLI exposes an unauthenticated server on a non-loopback interface; implementation, advisory reports and the shared A2A-auth foundation are credited together ([#11261](https://github.com/diegosouzapw/OmniRoute/pull/11261) — thanks @backryun / @ntdat812 / @koushiksaravanan / @highlightime / @mado90 / @rafaelfiguereod-stack)
- **fix(release):** drain the final inherited v3.8.50 base-red cluster by preserving explicit combo skip semantics, restoring missing health and CLI translations, documenting the current build environment, and aligning stale catalog, Qdrant, CLI, mutation, dependency and database guards with the shipped contracts ([#11280](https://github.com/diegosouzapw/OmniRoute/pull/11280)) — thanks @backryun
### 📝 Maintenance
@@ -1558,7 +1560,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@AStupidBear](https://github.com/AStupidBear) | #10180 |
| [@azzaouiomar19-sketch](https://github.com/azzaouiomar19-sketch) | #10394 |
| [@b1nhm1nh](https://github.com/b1nhm1nh) | direct commit / report |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11262, #11263, #11264, #11266, #11267, #11268 |
| [@backryun](https://github.com/backryun) | #8228, #8451, #8627, #8809, #8818, #9084, #9086, #9090, #9091, #9092, #9093, #9114, #9119, #9120, #9122, #9135, #9136, #9137, #9138, #9139, #9141, #9561, #9562, #9563, #9564, #9565, #9566, #9742, #9747, #9748, #9751, #9753, #9755, #9791, #9792, #9793, #9795, #9796, #9797, #9798, #9920, #9972, #9973, #9974, #9975, #9977, #9978, #9979, #9984, #9986, #9987, #9988, #9989, #9990, #9998, #10087, #10088, #10134, #10175, #10178, #10195, #10201, #10226, #10254, #10255, #10256, #10257, #10258, #10324, #10325, #10327, #10328, #10339, #10359, #10367, #10380, #10382, #10390, #10418, #10423, #10433, #10451, #10453, #10464, #10487, #10512, #10520, #10633, #10634, #10637, #10647, #10648, #10649, #10655, #10689, #10691, #10695, #10698, #10699, #10700, #10826, #10964, #11147, #11196, #11208, #11256, #11259, #11260, #11261, #11262, #11263, #11264, #11266, #11267, #11268, #11280 |
| [@Benson-mk](https://github.com/Benson-mk) | #8369 |
| [@benzntech](https://github.com/benzntech) | #9784, #9810, #9812, #9939, #10124, #10126, #10366, #10458 |
| [@Bl0ck154](https://github.com/Bl0ck154) | #9231 |
@@ -1617,6 +1619,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@herjarsa](https://github.com/herjarsa) | #9714, #9816, #9937, #9946, #10128, #10456, #10463 |
| [@hgaib](https://github.com/hgaib) | #10722 |
| [@hichamza](https://github.com/hichamza) | #7764 |
| [@highlightime](https://github.com/highlightime) | #11261 |
| [@horacecar](https://github.com/horacecar) | #7679 |
| [@HouMinXi](https://github.com/HouMinXi) | #8886, #8904, #8905, #8976, #8984, #9079, #9106, #9207, #9242, #9328, #9340, #9342, #9351, #9365, #9380, #9381, #9392, #9449, #9482, #9483, #9509, #9510, #9572, #9631, #9634, #9695, #9929, #10457, #10475, #10525, #10529, #10573, #10663, #10846, #11084, #11139, #11140, #11141 |
| [@hppsc1215](https://github.com/hppsc1215) | #8970 |
@@ -1648,6 +1651,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@KittisakT](https://github.com/KittisakT) | #9423 |
| [@Kizuno18](https://github.com/Kizuno18) | #10803 |
| [@KooshaPari](https://github.com/KooshaPari) | #7329 |
| [@koushiksaravanan](https://github.com/koushiksaravanan) | #11261 |
| [@kriptoburak](https://github.com/kriptoburak) | #10854 |
| [@krishna3554](https://github.com/krishna3554) | #10620, #10855 |
| [@lamchun1110](https://github.com/lamchun1110) | #10372, #10397 |
@@ -1662,7 +1666,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@luoyide](https://github.com/luoyide) | direct commit / report |
| [@maci0](https://github.com/maci0) | #11279 |
| [@mad-gooze](https://github.com/mad-gooze) | #9052 |
| [@mado90](https://github.com/mado90) | #11236 |
| [@mado90](https://github.com/mado90) | #11236, #11261 |
| [@maisdesign](https://github.com/maisdesign) | #8858 |
| [@marchlhw](https://github.com/marchlhw) | #9050 |
| [@marcs7](https://github.com/marcs7) | #11180 |
@@ -1691,7 +1695,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@nguyenha935](https://github.com/nguyenha935) | #8450, #9044, #9215 |
| [@nordz0r](https://github.com/nordz0r) | #10170 |
| [@nosolosoft](https://github.com/nosolosoft) | #8900 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004 |
| [@ntdat812](https://github.com/ntdat812) | #10843, #10853, #10857, #10858, #10860, #10862, #10868, #10935, #10941, #11004, #11261 |
| [@ntdatt812](https://github.com/ntdatt812) | #10715, #11076 |
| [@octo-patch](https://github.com/octo-patch) | #10650 |
| [@oyi77](https://github.com/oyi77) | #8299, #8752, #9158, #9818, #10910, #10942 |
@@ -1707,6 +1711,7 @@ Thanks to everyone whose work landed in v3.8.50:
| [@pucedoteth](https://github.com/pucedoteth) | #10607 |
| [@qianze0628](https://github.com/qianze0628) | #9038 |
| [@rafacpti23](https://github.com/rafacpti23) | #11207, #11213, #11249 |
| [@rafaelfiguereod-stack](https://github.com/rafaelfiguereod-stack) | #11261 |
| [@raflyazf](https://github.com/raflyazf) | direct commit / report |
| [@Rahulsharma0810](https://github.com/Rahulsharma0810) | #8961, #10872 |
| [@RaviTharuma](https://github.com/RaviTharuma) | #10296, #10297, #10299, #10306, #10307, #10344, #10488, #10565, #10566, #10568, #10569, #10584, #10756, #10814, #10816, #10817, #10818, #10819, #10820, #10821, #10822, #10823, #10824, #10825, #10827, #10828, #10847, #10971, #10977, #10979, #10981, #10983, #10988, #11014, #11015, #11016, #11017, #11020, #11024 |

View File

@@ -1,19 +1,19 @@
---
title: "CLI Tools — OmniRoute"
version: 3.8.50
lastUpdated: 2026-08-18
lastUpdated: 2026-08-23
---
# CLI Tools — OmniRoute
Last updated: 2026-08-18
Last updated: 2026-08-23
OmniRoute integrates with three categories of CLI tools spread across three dedicated dashboard pages:
| Page | Route | Concept | Count |
| -------------- | ----------------------- | ------------------------------------------------------------------------- | ------------ |
| **CLI Code's** | `/dashboard/cli-code` | Coding tools you point at OmniRoute (Client → CLI → OmniRoute → Provider) | 26 |
| **CLI Agents** | `/dashboard/cli-agents` | Autonomous agents you point at OmniRoute (same flow, broader scope) | 8 |
| **CLI Agents** | `/dashboard/cli-agents` | Autonomous agents you point at OmniRoute (same flow, broader scope) | 9 |
| **ACP Agents** | `/dashboard/acp-agents` | CLIs that OmniRoute spawns as backend via stdio/ACP (reverse flow) | see registry |
Legacy routes redirect via 308: `/dashboard/cli-tools``/dashboard/cli-code`, `/dashboard/agents``/dashboard/acp-agents`.

View File

@@ -89,6 +89,7 @@ OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These vari
| `OMNIROUTE_RELEASE_REF` | `origin/main` | `scripts/build/buildProvenance.ts` | Ref the pack-artifact provenance gate checks the build SHA against (#10427). |
| `OMNIROUTE_ALLOW_CANARY_BUILD` | _(unset)_ | `scripts/build/buildProvenance.ts` | Set to `1` to allow packing a build whose SHA is not on the release line, recording it as a deliberate canary instead of failing the gate (#10427). |
| `OMNIROUTE_SMOKE_API_KEY` | _(unset)_ | `scripts/ops/deploy-canary.mjs` | API key for the canary-deploy smoke probe, sent as `Authorization: Bearer` on `/v1/chat/completions`. Only used by the deploy script (#10429), never by the server. Not related to the `OMNIROUTE_SMOKE_*` variables of the opt-in CLI smoke harness (`RUN_CLI_SMOKE=1`, `OMNIROUTE_SMOKE_BASE_URL/MODEL/API_KEY_ENV/TARGETS/TIMEOUT_MS` in `tests/integration/upstream-cli-smoke.int.test.ts`) — see [CLI Integrations → Real smoke sweep](../guides/CLI-INTEGRATIONS.md). |
| `OMNIROUTE_BUILDING` | _(unset)_ | `src/lib/buildPhase.ts` | Build-phase signal (#10060): set to `1` by `scripts/build/build-next-isolated.mjs` and inherited by every spawned build worker so the DB layer returns a no-op stub instead of loading the native better-sqlite3 addon (which aborts the worker on exit). Never set for the running server. |
| `OMNIROUTE_DATA_DIR` | _(unset)_ | `open-sse/executors/promptql/threadSticky.ts` | **Fallback alias** for `DATA_DIR`, checked only when `DATA_DIR` is unset. Used to locate the PromptQL executor's on-disk thread-sticky session cache (`<dir>/promptql-thread-sessions.json`); if neither var is set, the cache stays in-memory only (not persisted across restarts). |
| `STORAGE_ENCRYPTION_KEY` | _(empty = disabled)_ | `src/lib/db/encryption.ts` | AES key for full SQLite database encryption at rest. Generate with `openssl rand -hex 32`. |
| `STORAGE_ENCRYPTION_KEY_VERSION` | `v1` | `scripts/build/bootstrap-env.mjs`, `electron/main.js` | Version label for the encryption key. Increment when performing key rotation to support decryption of old backups. |

View File

@@ -1218,7 +1218,12 @@ export async function handleChatCore({
credentials?.providerSpecificData?.preserveEncryptedReasoning === true,
onIncompatibleReasoning: resolveIncompatibleReasoningAction({
reasoningTransportFallback,
isComboStep: Boolean(comboStepId || comboExecutionKey),
// #11178 regressed combo steps whose combo record carries no explicit
// stepId/executionKey (plain model-list combos): their explicit
// `reasoningTransportFallback: "skip"` config was silently degraded to
// "drop". `isCombo` is the combo marker; step ids are optional
// finer-grained metadata that plain combos never set.
isComboStep: Boolean(isCombo) || Boolean(comboStepId || comboExecutionKey),
headers: clientRawRequest?.headers ?? null,
}),
}
@@ -4217,79 +4222,84 @@ export async function handleChatCore({
`[provider] Node ${errorConnectionId} probe ${errorType} (${statusCode}) — connection stays active`
);
} else {
// Kimi's 403 says "billing cycle" for both an exhausted subscription and a
// temporary request window. Read its official usage endpoint before making
// the connection terminal: a non-zero Weekly quota plus an empty Ratelimit
// window must recover automatically at the reported reset time.
let kimiRateLimitResetAt: string | null = null;
if (provider === "kimi-coding") {
try {
const { fetchAndPersistProviderLimits } =
await import("@/lib/usage/providerLimits");
const { usage } = await fetchAndPersistProviderLimits(errorConnectionId, "manual");
kimiRateLimitResetAt = getKimiTemporaryRateLimitResetAt(usage);
} catch {
// Preserve the existing quota handling when Kimi's usage endpoint is unavailable.
// Kimi's 403 says "billing cycle" for both an exhausted subscription and a
// temporary request window. Read its official usage endpoint before making
// the connection terminal: a non-zero Weekly quota plus an empty Ratelimit
// window must recover automatically at the reported reset time.
let kimiRateLimitResetAt: string | null = null;
if (provider === "kimi-coding") {
try {
const { fetchAndPersistProviderLimits } =
await import("@/lib/usage/providerLimits");
const { usage } = await fetchAndPersistProviderLimits(
errorConnectionId,
"manual"
);
kimiRateLimitResetAt = getKimiTemporaryRateLimitResetAt(usage);
} catch {
// Preserve the existing quota handling when Kimi's usage endpoint is unavailable.
}
}
}
// Providers with per-model quotas — lock the model only, not the connection
const quotaCooldownMs = kimiRateLimitResetAt
? Math.max(new Date(kimiRateLimitResetAt).getTime() - Date.now(), 0)
: retryAfterMs || COOLDOWN_MS.rateLimit;
const accountSemaphoreKey = resolveAccountSemaphoreKey({
provider,
model: currentModel,
connectionId: errorConnectionId,
credentials,
});
if (accountSemaphoreKey) {
markAccountSemaphoreBlocked(accountSemaphoreKey, quotaCooldownMs);
}
if (kimiRateLimitResetAt) {
await updateProviderConnection(errorConnectionId, {
testStatus: "unavailable",
rateLimitedUntil: kimiRateLimitResetAt,
backoffLevel: 0,
lastErrorType: PROVIDER_ERROR_TYPES.RATE_LIMITED,
lastError: message,
errorCode: statusCode,
});
console.warn(
`[provider] Node ${errorConnectionId} Kimi request window exhausted (${statusCode}) — retrying after ${kimiRateLimitResetAt}`
);
} else if (isModelScope() && errorConnectionId) {
const lockFn = provider === "antigravity" ? lockExactModel : lockModel;
lockFn(provider, errorConnectionId, model, "quota_exhausted", quotaCooldownMs);
console.warn(
`[provider] Node ${errorConnectionId} ModelScope model quota exhausted (${statusCode}) for ${model} - ${Math.ceil(quotaCooldownMs / 1000)}s (connection stays active)`
);
} else if (
lockModelIfPerModelQuota(
// Providers with per-model quotas — lock the model only, not the connection
const quotaCooldownMs = kimiRateLimitResetAt
? Math.max(new Date(kimiRateLimitResetAt).getTime() - Date.now(), 0)
: retryAfterMs || COOLDOWN_MS.rateLimit;
const accountSemaphoreKey = resolveAccountSemaphoreKey({
provider,
errorConnectionId,
model,
"quota_exhausted",
quotaCooldownMs
)
) {
const quotaScope = getQuotaScopeLabelForProvider(provider, model);
console.warn(
`[provider] Node ${errorConnectionId} ${quotaScope}-only quota exhausted (${statusCode}) for ${model} - ${Math.ceil(quotaCooldownMs / 1000)}s (cooldown_scope=${quotaScope}, ttl_source=${retryAfterMs ? "upstream" : "inferred"}, connection stays active)`
);
} else {
await writeTerminalStatus(
errorConnectionId,
{
testStatus: "credits_exhausted",
model: currentModel,
connectionId: errorConnectionId,
credentials,
});
if (accountSemaphoreKey) {
markAccountSemaphoreBlocked(accountSemaphoreKey, quotaCooldownMs);
}
if (kimiRateLimitResetAt) {
await updateProviderConnection(errorConnectionId, {
testStatus: "unavailable",
rateLimitedUntil: kimiRateLimitResetAt,
backoffLevel: 0,
lastErrorType: PROVIDER_ERROR_TYPES.RATE_LIMITED,
lastError: message,
lastErrorType: errorType,
errorCode: String(statusCode),
},
"production"
);
console.warn(`[provider] Node ${errorConnectionId} exhausted quota (${statusCode})`);
}
errorCode: statusCode,
});
console.warn(
`[provider] Node ${errorConnectionId} Kimi request window exhausted (${statusCode}) — retrying after ${kimiRateLimitResetAt}`
);
} else if (isModelScope() && errorConnectionId) {
const lockFn = provider === "antigravity" ? lockExactModel : lockModel;
lockFn(provider, errorConnectionId, model, "quota_exhausted", quotaCooldownMs);
console.warn(
`[provider] Node ${errorConnectionId} ModelScope model quota exhausted (${statusCode}) for ${model} - ${Math.ceil(quotaCooldownMs / 1000)}s (connection stays active)`
);
} else if (
lockModelIfPerModelQuota(
provider,
errorConnectionId,
model,
"quota_exhausted",
quotaCooldownMs
)
) {
const quotaScope = getQuotaScopeLabelForProvider(provider, model);
console.warn(
`[provider] Node ${errorConnectionId} ${quotaScope}-only quota exhausted (${statusCode}) for ${model} - ${Math.ceil(quotaCooldownMs / 1000)}s (cooldown_scope=${quotaScope}, ttl_source=${retryAfterMs ? "upstream" : "inferred"}, connection stays active)`
);
} else {
await writeTerminalStatus(
errorConnectionId,
{
testStatus: "credits_exhausted",
lastError: message,
lastErrorType: errorType,
errorCode: String(statusCode),
},
"production"
);
console.warn(
`[provider] Node ${errorConnectionId} exhausted quota (${statusCode})`
);
}
} // close probeIsolated3 else
}
} else if (errorType === PROVIDER_ERROR_TYPES.UNAUTHORIZED) {

View File

@@ -31,12 +31,20 @@ import * as xSearch from "./search/xSearch.ts";
import { freeWebSearch } from "../services/freeWebSearch.ts";
import { saveCallLog } from "@/lib/usageDb";
import { safeOutboundFetch } from "@/shared/network/safeOutboundFetch";
import {
parseAndValidateNonMetadataUrl,
parseAndValidatePublicUrl,
} from "@/shared/network/outboundUrlGuard";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { z } from "zod";
import { sanitizeErrorMessage } from "../utils/error.ts";
import { isValidContext7LibraryId } from "../executors/context7-fetch.ts";
import { resolveSearchProxy, executeProviderFetch } from "./search/searchProxy.ts";
import {
executeProviderFetch,
fetchClientControlledSearchUrl,
resolveSearchProxy,
} from "./search/searchProxy.ts";
import { formatSearchProviderFailure } from "./search/providerFailure.ts";
export interface SearchResult {
@@ -296,26 +304,41 @@ function parseDomainFilter(domainFilter?: string[]): {
return { includes, excludes };
}
function getSettingString(record: Record<string, unknown> | undefined, key: string) {
const value = record?.[key];
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
}
function getProviderSettingString(
params: Pick<SearchRequestParams, "providerOptions" | "providerSpecificData">,
key: string
): string | undefined {
const fromOptions = params.providerOptions?.[key];
if (typeof fromOptions === "string" && fromOptions.trim().length > 0) {
return fromOptions.trim();
}
const fromProviderData = params.providerSpecificData?.[key];
if (typeof fromProviderData === "string" && fromProviderData.trim().length > 0) {
return fromProviderData.trim();
}
return undefined;
) {
return (
getSettingString(params.providerOptions, key) ??
getSettingString(params.providerSpecificData, key)
);
}
function resolveSearchBaseUrl(config: SearchProviderConfig, params: SearchRequestParams): string {
const override = getProviderSettingString(params, "baseUrl");
return (override || config.baseUrl).replace(/\/+$/, "");
export function resolveSearchBaseUrl(
config: SearchProviderConfig,
params: SearchRequestParams
): string {
const clientOverride = getSettingString(params.providerOptions, "baseUrl");
if (clientOverride) {
// Request-scoped provider_options is untrusted. Its hostname must be public
// before the request-time DNS pin in searchProxy.ts closes the rebinding gap.
parseAndValidatePublicUrl(clientOverride);
return clientOverride.replace(/\/+$/, "");
}
const storedBaseUrl = getSettingString(params.providerSpecificData, "baseUrl");
if (storedBaseUrl) {
// Persisted operator configuration is where self-hosted SearXNG/Ollama lives,
// so loopback/LAN stays supported. Metadata is never a valid search backend.
parseAndValidateNonMetadataUrl(storedBaseUrl);
return storedBaseUrl.replace(/\/+$/, "");
}
return config.baseUrl.replace(/\/+$/, "");
}
function toSearchPageNumber(offset: number | undefined, maxResults: number): number | undefined {
@@ -1081,8 +1104,16 @@ async function zaiSearchExecute(params: {
signal?: AbortSignal;
}): Promise<{ results: SearchResult[]; totalResults: number | null }> {
const baseUrl = resolveSearchBaseUrl(params.config, params.params);
const clientControlledBaseUrl = Boolean(
getSettingString(params.params.providerOptions, "baseUrl")
);
const guardedMcpFetch = ((input: RequestInfo | URL, init?: RequestInit) => {
const targetUrl =
typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
return fetchClientControlledSearchUrl(targetUrl, init ?? {}, init?.signal ?? undefined);
}) as typeof fetch;
const transport = new StreamableHTTPClientTransport(new URL(baseUrl), {
fetch: safeOutboundFetch,
fetch: clientControlledBaseUrl ? guardedMcpFetch : safeOutboundFetch,
requestInit: {
headers: {
Authorization: `Bearer ${params.token}`,
@@ -1406,13 +1437,22 @@ export async function handleSearch(options: SearchHandlerOptions): Promise<Searc
// 4. Try primary provider (skip catalog-default SearXNG localhost:8888,
// unless a request/connection override resolves it to a real URL).
const primaryEffectiveBaseUrl = resolveSearchBaseUrl(primaryConfig, {
...requestParams,
providerSpecificData:
credentials?.providerSpecificData && typeof credentials.providerSpecificData === "object"
? credentials.providerSpecificData
: undefined,
});
let primaryEffectiveBaseUrl: string;
try {
primaryEffectiveBaseUrl = resolveSearchBaseUrl(primaryConfig, {
...requestParams,
providerSpecificData:
credentials?.providerSpecificData && typeof credentials.providerSpecificData === "object"
? credentials.providerSpecificData
: undefined,
});
} catch (error) {
return {
success: false,
status: 400,
error: sanitizeErrorMessage(error) || "Invalid search provider base URL",
};
}
if (
isUnconfiguredLoopbackSearchProvider({ ...primaryConfig, baseUrl: primaryEffectiveBaseUrl })
) {
@@ -1683,6 +1723,7 @@ async function tryProvider(
connectionId,
proxy,
proxyLevel,
clientControlledBaseUrl: Boolean(getSettingString(params.providerOptions, "baseUrl")),
log,
normalize: normalizeResponse,
});

View File

@@ -8,12 +8,95 @@
* query, API key, or proxy credentials).
*/
import dns from "node:dns";
import { isIP } from "node:net";
import { saveCallLog } from "@/lib/usageDb";
import { isPrivateHost, parseAndValidatePublicUrl } from "@/shared/network/outboundUrlGuard";
import { createPinnedFetch } from "@/shared/network/remoteImageFetch";
import { sanitizeErrorMessage } from "../../utils/error.ts";
import { formatSearchProviderFailure } from "./providerFailure.ts";
import type { SearchProviderConfig } from "../../config/searchRegistry.ts";
import type { SearchResult } from "../search.ts";
export type SearchDnsLookup = (
hostname: string
) => Promise<Array<{ address: string; family: number }>>;
export interface ClientControlledSearchFetchDependencies {
lookup?: SearchDnsLookup;
createPinnedFetch?: (address: string, family: number) => typeof fetch;
}
const defaultSearchLookup: SearchDnsLookup = (hostname) =>
dns.promises.lookup(hostname, { all: true });
async function resolvePublicSearchAddresses(
targetUrl: URL,
lookup: SearchDnsLookup
): Promise<Array<{ address: string; family: number }>> {
const hostname = targetUrl.hostname;
const bare =
hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
const literalFamily = isIP(bare);
if (literalFamily) return [{ address: bare, family: literalFamily }];
let addresses: Array<{ address: string; family: number }>;
try {
addresses = await lookup(bare);
} catch {
throw new Error("Search provider hostname could not be resolved (blocked)");
}
if (addresses.length === 0) {
throw new Error("Search provider hostname could not be resolved (blocked)");
}
if (addresses.some(({ address }) => isPrivateHost(address))) {
throw new Error(
"Search provider hostname resolves to a private address (DNS rebinding blocked)"
);
}
return addresses;
}
/**
* Fetch a request-scoped search base URL without a validation/connect-time DNS gap.
* The URL is public-only, every DNS answer is checked, the connection is pinned to
* the checked answer, and redirects fail closed instead of triggering a second,
* unvalidated fetch. Persisted provider base URLs do not use this path: those are
* operator configuration and intentionally support loopback/LAN backends.
*/
export async function fetchClientControlledSearchUrl(
url: string,
init: RequestInit,
signal?: AbortSignal,
dependencies: ClientControlledSearchFetchDependencies = {}
): Promise<Response> {
const targetUrl = parseAndValidatePublicUrl(url);
const lookup = dependencies.lookup ?? defaultSearchLookup;
const addresses = await resolvePublicSearchAddresses(targetUrl, lookup);
const selected = addresses[0];
const pinnedFetchFactory = dependencies.createPinnedFetch ?? createPinnedFetch;
const response = await pinnedFetchFactory(selected.address, selected.family)(
targetUrl.toString(),
{
...init,
redirect: "manual",
signal: signal ?? init.signal,
}
);
if (response.status >= 300 && response.status < 400) {
try {
await response.body?.cancel();
} catch {
// The redirect is blocked regardless of whether its body can be cancelled.
}
throw new Error(`Search provider redirect blocked (${response.status})`);
}
return response;
}
/** Resolved proxy binding for a single provider attempt. */
export interface ResolvedSearchProxy {
proxy: unknown;
@@ -119,7 +202,11 @@ export interface ProviderFetchResult {
results: SearchResult[];
answer: null;
usage: { queries_used: number; search_cost_usd: number };
metrics: { response_time_ms: number; upstream_latency_ms: number; total_results_available: number | null };
metrics: {
response_time_ms: number;
upstream_latency_ms: number;
total_results_available: number | null;
};
errors: [];
};
}
@@ -144,6 +231,7 @@ export interface ExecuteProviderFetchParams {
connectionId?: string;
proxy: unknown;
proxyLevel: string;
clientControlledBaseUrl?: boolean;
log?: SearchLog;
normalize: (
providerId: string,
@@ -160,9 +248,11 @@ export interface ExecuteProviderFetchParams {
* This is the single chokepoint tryProvider() delegates to after building
* the request and resolving the proxy — keeps search.ts to wiring only.
*/
export async function executeProviderFetch(p: ExecuteProviderFetchParams): Promise<ProviderFetchResult> {
export async function executeProviderFetch(
p: ExecuteProviderFetchParams
): Promise<ProviderFetchResult> {
const { config, url, init, controller, timer, query, searchType, maxResults, startTime } = p;
const { connectionId, proxy, proxyLevel, log, normalize } = p;
const { connectionId, proxy, proxyLevel, clientControlledBaseUrl, log, normalize } = p;
const emitEvent = (status: string) =>
emitSearchProxyEvent(config.id, connectionId, proxy, proxyLevel, url, startTime, status);
const logCall = (fields: Record<string, unknown>) =>
@@ -180,9 +270,12 @@ export async function executeProviderFetch(p: ExecuteProviderFetchParams): Promi
});
try {
const response = await fetchWithSearchProxy(proxy, () =>
fetch(url, { ...init, signal: controller.signal })
);
if (clientControlledBaseUrl && proxy) {
throw new Error("Client-controlled search base URLs cannot use a proxy without DNS pinning");
}
const response = clientControlledBaseUrl
? await fetchClientControlledSearchUrl(url, init, controller.signal)
: await fetchWithSearchProxy(proxy, () => fetch(url, { ...init, signal: controller.signal }));
clearTimeout(timer);
if (!response.ok) {
@@ -190,7 +283,11 @@ export async function executeProviderFetch(p: ExecuteProviderFetchParams): Promi
if (log) {
log.error("SEARCH", `${config.id} error ${response.status}: ${errorText.slice(0, 200)}`);
}
logCall({ status: response.status, duration: Date.now() - startTime, error: errorText.slice(0, 500) });
logCall({
status: response.status,
duration: Date.now() - startTime,
error: errorText.slice(0, 500),
});
await emitEvent("error");
return {
success: false,

View File

@@ -1,11 +1,31 @@
"use client";
import { useEffect, useState } from "react";
import { useState, useSyncExternalStore } from "react";
import Link from "next/link";
import { useTranslations } from "next-intl";
const DISMISS_STORAGE_KEY = "omniroute-first-run-readiness-dismissed";
function subscribeToDismissal(onStoreChange: () => void): () => void {
const handleStorage = (event: StorageEvent) => {
if (event.key === null || event.key === DISMISS_STORAGE_KEY) onStoreChange();
};
window.addEventListener("storage", handleStorage);
return () => window.removeEventListener("storage", handleStorage);
}
function getDismissedSnapshot(): boolean {
try {
return localStorage.getItem(DISMISS_STORAGE_KEY) !== null;
} catch {
return false;
}
}
function getServerDismissedSnapshot(): boolean {
return true;
}
type FirstRunReadinessCardProps = {
setupComplete: boolean;
};
@@ -16,21 +36,15 @@ type FirstRunReadinessCardProps = {
*/
export default function FirstRunReadinessCard({ setupComplete }: FirstRunReadinessCardProps) {
const t = useTranslations("home");
const [visible, setVisible] = useState(false);
const [dismissedForSession, setDismissedForSession] = useState(false);
const dismissedInStorage = useSyncExternalStore(
subscribeToDismissal,
getDismissedSnapshot,
getServerDismissedSnapshot
);
const visible = !setupComplete && !dismissedForSession && !dismissedInStorage;
useEffect(() => {
if (setupComplete) {
setVisible(false);
return;
}
try {
setVisible(!localStorage.getItem(DISMISS_STORAGE_KEY));
} catch {
setVisible(true);
}
}, [setupComplete]);
if (!visible || setupComplete) return null;
if (!visible) return null;
const dismiss = () => {
try {
@@ -38,7 +52,7 @@ export default function FirstRunReadinessCard({ setupComplete }: FirstRunReadine
} catch {
// ignore storage failures; still hide for this session
}
setVisible(false);
setDismissedForSession(true);
};
const steps = [

View File

@@ -290,6 +290,11 @@ export default function EditConnectionModal({
connection.providerSpecificData?.quotaPerUnit != null
? String(connection.providerSpecificData.quotaPerUnit)
: "";
// Modal-open form initialization from the loaded connection (sync with an
// external system on `isOpen`); remounting the 30+ field form per
// connection id is a behavior-risking restructure out of scope here
// (#11251 follow-up, #9985).
// eslint-disable-next-line react-hooks/set-state-in-effect
setFormData({
name: connection.name || "",
priority: connection.priority || 1,

View File

@@ -10,15 +10,13 @@
* Auth: Bearer token via Authorization header
*/
import { timingSafeEqual } from "node:crypto";
import { NextRequest, NextResponse } from "next/server";
import { getTaskManager } from "@/lib/a2a/taskManager";
import { A2A_OWNERLESS_SCOPE, a2aOwnerScope, getTaskManager } from "@/lib/a2a/taskManager";
import { logRoutingDecision } from "@/lib/a2a/routingLogger";
import { createA2AStream, SSE_HEADERS } from "@/lib/a2a/streaming";
import { A2A_SKILL_HANDLERS, executeA2ATaskWithState } from "@/lib/a2a/taskExecution";
import { getSettings } from "@/lib/db/settings";
import { isRequireApiKeyEnabled } from "@/shared/utils/featureFlags";
import { extractApiKey, isValidApiKey } from "@/sse/services/auth";
import { authenticateA2ARequest, resolveA2AOwner } from "@/lib/a2a/authenticate";
// ============ A2A v1.0 ↔ v0.3 compatibility layer ============
// A2A 1.0 renamed the JSON-RPC methods (message/send → SendMessage,
@@ -55,7 +53,7 @@ function buildV1Task(
? result.artifacts
.map((a) =>
a && typeof a === "object" && typeof (a as { content?: unknown }).content === "string"
? ((a as { content: string }).content)
? (a as { content: string }).content
: ""
)
.filter((s) => s.length > 0)
@@ -124,39 +122,13 @@ function toMessageArray(raw: unknown): A2AMessage[] | null {
// ============ Auth ============
/**
* Constant-time comparison of the presented bearer token against the configured
* key. A plain `===` short-circuits on the first differing byte, leaking the
* length of the shared prefix through response timing; `timingSafeEqual` does
* not. It requires equal-length buffers, so mismatched lengths are rejected up
* front (the length itself is not secret).
*/
function tokensMatch(provided: string, expected: string): boolean {
const a = Buffer.from(provided);
const b = Buffer.from(expected);
if (a.length !== b.length) return false;
return timingSafeEqual(a, b);
}
async function authenticate(req: NextRequest): Promise<boolean> {
// /a2a is outside the authz proxy matcher, so the REQUIRE_API_KEY posture the
// pipeline enforces for /v1 never ran here — the route accepted every caller
// whenever OMNIROUTE_API_KEY was unset, which is the shipped default
// (GHSA-v54m-6rm3-p565). Apply the same posture directly: when a client key is
// required, demand a valid OmniRoute key; otherwise honor the legacy explicit
// A2A key; otherwise stay keyless (the same local-first default as /v1).
const apiKey = extractApiKey(req);
if (isRequireApiKeyEnabled()) {
return apiKey ? await isValidApiKey(apiKey) : false;
}
const configuredKey = process.env.OMNIROUTE_API_KEY;
if (configuredKey) {
return apiKey ? tokensMatch(apiKey, configuredKey) : false;
}
// No API key required and none configured — allow (keyless local-first).
return true;
// (GHSA-v54m-6rm3-p565). The shared helper applies the same posture on both
// the JSON-RPC and the REST task surfaces (GHSA-jcm5-6wpp-wjj8).
return authenticateA2ARequest(req);
}
// ============ JSON-RPC Helpers ============
@@ -213,6 +185,10 @@ export async function POST(req: NextRequest) {
if (disabledResponse) return disabledResponse;
const tm = getTaskManager();
// GHSA-jcm5-6wpp-wjj8: scope every task read/mutation below to the caller's
// owner id (hashed API key; undefined under the keyless local-first posture).
const callerOwner = resolveA2AOwner(req);
const callerScope = callerOwner ? a2aOwnerScope(callerOwner) : A2A_OWNERLESS_SCOPE;
// A2A 1.0 method-name compatibility (SendMessage → message/send, etc.)
const isV1Method = method in V1_METHOD_ALIASES;
@@ -236,7 +212,7 @@ export async function POST(req: NextRequest) {
return jsonRpcError(id, -32601, `Unknown skill: ${skill}`);
}
const task = tm.createTask({ skill, messages, metadata: params?.metadata });
const task = tm.createTask({ skill, messages, metadata: params?.metadata }, callerOwner);
try {
tm.updateTask(task.id, "working");
const result = await handler(task);
@@ -302,7 +278,7 @@ export async function POST(req: NextRequest) {
return jsonRpcError(id, -32601, `Unknown skill: ${skill}`);
}
const task = tm.createTask({ skill, messages, metadata: params?.metadata });
const task = tm.createTask({ skill, messages, metadata: params?.metadata }, callerOwner);
tm.updateTask(task.id, "working");
const stream = createA2AStream(
@@ -323,7 +299,7 @@ export async function POST(req: NextRequest) {
const taskId = params?.taskId || params?.id;
if (!taskId) return jsonRpcError(id, -32602, "Invalid params: taskId required");
const task = tm.getTask(taskId);
const task = tm.getTask(taskId, callerScope);
if (!task) return jsonRpcError(id, -32601, `Task not found: ${taskId}`);
return jsonRpcResult(id, { task });
@@ -335,7 +311,7 @@ export async function POST(req: NextRequest) {
if (!taskId) return jsonRpcError(id, -32602, "Invalid params: taskId required");
try {
const task = tm.cancelTask(taskId);
const task = tm.cancelTask(taskId, callerScope);
return jsonRpcResult(id, { task: { id: task.id, state: task.state } });
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);

60
src/app/api/a2a/_auth.ts Normal file
View File

@@ -0,0 +1,60 @@
/**
* Shared authorization for the REST A2A task routes (GHSA-jcm5-6wpp-wjj8).
*
* Dual audience: the dashboard calls these routes with a management session,
* A2A clients with an inference API key. Posture matrix:
*
* - REQUIRE_API_KEY=true: a valid OmniRoute key is mandatory (the same
* posture the /v1 inference plane enforces); a management session also
* passes (dashboard), via alwaysRequireAuth so requireLogin=false cannot
* bypass it.
* - otherwise + requireLogin=true: management session, or a valid key.
* - otherwise + requireLogin=false (local-first default): open with an
* ownerless task scope, by design.
*
* Callers authenticated by key are owner-scoped — another principal's tasks
* answer as if they did not exist. Management/operator view sees all tasks.
*/
import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
import { extractApiKey, isValidApiKey } from "@/sse/services/auth";
import { isRequireApiKeyEnabled } from "@/shared/utils/featureFlags";
import { resolveA2AOwner } from "@/lib/a2a/authenticate";
import {
A2A_OPERATOR_SCOPE,
A2A_OWNERLESS_SCOPE,
a2aOwnerScope,
type A2ATaskScope,
} from "@/lib/a2a/taskManager";
export interface A2ARestAuth {
scope: A2ATaskScope;
}
/**
* NOTE: the failure branch is whatever requireManagementAuth returns — today a
* plain `Response` from createErrorResponse(), NOT a NextResponse. Callers must
* test with `instanceof Response` (NextResponse extends Response), never
* `instanceof NextResponse`, or the 401 silently falls through to the handler.
*/
export async function authorizeA2ATaskRoute(request: Request): Promise<A2ARestAuth | Response> {
const apiKey = extractApiKey(request);
if (apiKey && (await isValidApiKey(apiKey))) {
const owner = resolveA2AOwner(request);
if (owner) return { scope: a2aOwnerScope(owner) };
}
// alwaysRequireAuth distinguishes a real management credential from the
// keyless local-first posture, where requireManagementAuth normally returns
// null before examining credentials.
const managementError = await requireManagementAuth(request, {
invalidApiKeyStatus: 401,
alwaysRequireAuth: true,
});
if (managementError === null) return { scope: A2A_OPERATOR_SCOPE };
if (isRequireApiKeyEnabled()) return managementError;
const postureError = await requireManagementAuth(request, { invalidApiKeyStatus: 401 });
if (postureError === null) return { scope: A2A_OWNERLESS_SCOPE };
return postureError;
}

View File

@@ -1,14 +1,23 @@
import { NextResponse } from "next/server";
import { getTaskManager } from "@/lib/a2a/taskManager";
import { authorizeA2ATaskRoute } from "@/app/api/a2a/_auth";
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";
export async function POST(_request: Request, { params }: { params: Promise<{ id: string }> }) {
export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) {
// GHSA-jcm5-6wpp-wjj8: this route had no auth call at all. The owner check
// happens inside cancelTask: another principal's task throws the same
// "not found" a missing one would (no existence oracle).
const auth = await authorizeA2ATaskRoute(request);
if (auth instanceof Response) return auth;
try {
const { id } = await params;
const tm = getTaskManager();
const task = tm.cancelTask(id);
const task = tm.cancelTask(id, auth.scope);
return NextResponse.json({ task: { id: task.id, state: task.state } });
} catch (error) {
const message = error instanceof Error ? error.message : "Failed to cancel A2A task";
const message = sanitizeErrorMessage(
error instanceof Error ? error.message : "Failed to cancel A2A task"
);
const status = message.includes("not found") ? 404 : 400;
return NextResponse.json({ error: message }, { status });
}

View File

@@ -1,17 +1,30 @@
import { NextResponse } from "next/server";
import { getTaskManager } from "@/lib/a2a/taskManager";
import { authorizeA2ATaskRoute } from "@/app/api/a2a/_auth";
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";
export async function GET(_request: Request, { params }: { params: Promise<{ id: string }> }) {
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
// GHSA-jcm5-6wpp-wjj8: this route had no auth call at all — open regardless
// of configuration. Another principal's task answers 404, same as a missing
// one, so an IDOR probe cannot tell the two apart.
const auth = await authorizeA2ATaskRoute(request);
if (auth instanceof Response) return auth;
try {
const { id } = await params;
const tm = getTaskManager();
const task = tm.getTask(id);
const task = tm.getTask(id, auth.scope);
if (!task) {
return NextResponse.json({ error: `Task not found: ${id}` }, { status: 404 });
}
return NextResponse.json({ task });
} catch (error) {
const message = error instanceof Error ? error.message : "Failed to load A2A task";
return NextResponse.json({ error: message }, { status: 500 });
return NextResponse.json(
{
error: sanitizeErrorMessage(
error instanceof Error ? error.message : "Failed to load A2A task"
),
},
{ status: 500 }
);
}
}

View File

@@ -1,8 +1,10 @@
import { timingSafeEqual } from "node:crypto";
import { NextResponse } from "next/server";
import { z } from "zod";
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error";
import { getTaskManager, type TaskState } from "@/lib/a2a/taskManager";
import { authorizeA2ATaskRoute } from "@/app/api/a2a/_auth";
import { authenticateA2ARequest } from "@/lib/a2a/authenticate";
import { createConductorTask } from "@/lib/conductor/hubProxy";
import { getSettings } from "@/lib/db/settings";
@@ -22,6 +24,11 @@ function parseIntParam(value: string | null, fallback: number): number {
}
export async function GET(request: Request) {
// GHSA-jcm5-6wpp-wjj8: the list route had no auth call at all. Management
// sees every task; a valid API key is owner-scoped, and the keyless posture
// sees only ownerless tasks.
const auth = await authorizeA2ATaskRoute(request);
if (auth instanceof Response) return auth;
try {
const { searchParams } = new URL(request.url);
const stateParam = searchParams.get("state");
@@ -35,8 +42,8 @@ export async function GET(request: Request) {
: undefined;
const tm = getTaskManager();
const total = tm.countTasks({ state, skill });
const tasks = tm.listTasks({ state, skill, limit, offset });
const total = tm.countTasks({ state, skill }, auth.scope);
const tasks = tm.listTasks({ state, skill, limit, offset }, auth.scope);
return NextResponse.json({
tasks,
@@ -45,7 +52,9 @@ export async function GET(request: Request) {
offset,
});
} catch (error) {
const message = error instanceof Error ? error.message : "Failed to list A2A tasks";
const message = sanitizeErrorMessage(
error instanceof Error ? error.message : "Failed to list A2A tasks"
);
return NextResponse.json({ error: message }, { status: 500 });
}
}
@@ -69,42 +78,17 @@ const delegationSchema = z.object({
.optional(),
});
/**
* Constant-time comparison of the presented bearer token against the configured
* key. A plain `===` short-circuits on the first differing byte, leaking the
* length of the shared prefix through response timing; `timingSafeEqual` does
* not. It requires equal-length buffers, so mismatched lengths are rejected up
* front (the length itself is not secret).
*
* Exported as a test seam only — not part of the route contract.
*/
export function tokensMatch(provided: string, expected: string): boolean {
const a = Buffer.from(provided);
const b = Buffer.from(expected);
if (a.length !== b.length) return false;
return timingSafeEqual(a, b);
}
/**
* Mesma semântica de auth do JSON-RPC A2A (src/app/a2a/route.ts): Bearer vs OMNIROUTE_API_KEY; aberto se não configurada.
*
* Exported as a test seam only — not part of the route contract.
*/
export function authenticateA2A(request: Request): boolean {
const configuredKey = process.env.OMNIROUTE_API_KEY;
if (!configuredKey) return true;
const token = (request.headers.get("authorization") || "").replace(/^Bearer\s+/i, "");
return tokensMatch(token, configuredKey);
}
/**
* Traduz uma task A2A externa em `POST /v1/tasks` do hub do OmniConductor.
* Só skills da frota (`conductor` / `conductor-cli-<profile>` — as anunciadas no
* Agent Card) são delegáveis; os estados voltam pelo espelho SSE→A2A (RF1).
*/
export async function POST(request: Request) {
if (!authenticateA2A(request)) {
return NextResponse.json({ error: "Unauthorized: missing or invalid API key" }, { status: 401 });
if (!(await authenticateA2ARequest(request))) {
return NextResponse.json(
{ error: "Unauthorized: missing or invalid API key" },
{ status: 401 }
);
}
const settings = await getSettings();
if (settings.a2aEnabled !== true) {
@@ -122,12 +106,18 @@ export async function POST(request: Request) {
}
const parsed = delegationSchema.safeParse(raw);
if (!parsed.success) {
return NextResponse.json({ error: "Invalid A2A task: provide messages[] (and metadata.conductor)" }, { status: 400 });
return NextResponse.json(
{ error: "Invalid A2A task: provide messages[] (and metadata.conductor)" },
{ status: 400 }
);
}
const { skill, messages, metadata } = parsed.data;
if (skill !== "conductor" && !skill.startsWith("conductor-cli-")) {
return NextResponse.json(
{ error: "Only Conductor fleet skills are delegable here (conductor / conductor-cli-<profile>)" },
{
error:
"Only Conductor fleet skills are delegable here (conductor / conductor-cli-<profile>)",
},
{ status: 400 }
);
}
@@ -138,7 +128,9 @@ export async function POST(request: Request) {
{ status: 400 }
);
}
const prompt = [...messages].reverse().find((m) => m.role === "user")?.content ?? messages[messages.length - 1].content;
const prompt =
[...messages].reverse().find((m) => m.role === "user")?.content ??
messages[messages.length - 1].content;
const created = await createConductorTask({
repoUrl: conductor.repo.url,

View File

@@ -1221,12 +1221,6 @@
"consoleLogsSubtitle": "Console output",
"logsActivitySubtitle": "User activity log",
"healthSubtitle": "System health check",
"healthVerdictReady": "OmniRoute is ready",
"healthVerdictActionRequired": "Action required to restore full operation",
"healthVerdictCoolingDown": "Cooling down after recent changes",
"advancedDiagnosticsTitle": "Advanced diagnostics",
"hide": "Hide",
"show": "Show",
"costsPricingSubtitle": "Per-model pricing rules",
"costsBudgetSubtitle": "Budget limits",
"costsQuotaShareSubtitle": "Share provider quotas across keys",
@@ -2928,6 +2922,7 @@
"interpreter": "Open Interpreter autonomous coding agent CLI",
"omp": "Oh My Pi terminal coding agent",
"letta": "Letta CLI agent with persistent memory and tool use",
"prime-agent": "Prime Agent — self-improving RLM coding harness with OpenAI-compatible provider support",
"warp": "Warp AI terminal with custom provider support",
"agent-deck": "Agent Deck multi-agent orchestrator"
},
@@ -4637,6 +4632,13 @@
"retry": "Retry",
"allOperational": "All systems operational",
"issuesDetected": "System issues detected",
"healthVerdictReady": "OmniRoute is ready",
"healthVerdictActionRequired": "Action required to restore full operation",
"healthVerdictCoolingDown": "Cooling down after recent changes",
"healthSubtitle": "System health check",
"advancedDiagnosticsTitle": "Advanced diagnostics",
"hide": "Hide",
"show": "Show",
"updatedAt": "Updated {time}",
"latency": "Latency",
"latencyP50": "p50",

View File

@@ -970,6 +970,13 @@
"batchTimelineCancelled": "Cancelado",
"batchTokenUsage": "Uso de Token",
"batchMetadata": "Metadados",
"batchHeaderSubtitle": "Execute muitas requisições como um único job",
"batchStep1": "1 · Enviar JSONL",
"batchStep1Desc": "Adicionar requisições",
"batchStep2": "2 · Criar lote",
"batchStep2Desc": "Executar job",
"batchStep3": "3 · Obter resultados",
"batchStep3Desc": "Baixar saída",
"batchFileContents": "Conteúdo do Arquivo",
"batchFileUsedByCount": "Usado por {count, plural, one {# lote} other {# lotes}}",
"batchFilePreview": "Prévia",
@@ -1260,6 +1267,7 @@
"agentBridgeSubtitle": "Interceptar tráfego de agentes IDE",
"trafficInspector": "Inspector de Tráfego",
"trafficInspectorSubtitle": "Monitorar chamadas LLM + debugar tráfego HTTPS",
"trafficInspectorPurpose": "Veja exatamente o que seu aplicativo envia aos provedores de IA e recebe deles. Funciona com qualquer cliente compatível com OpenAI.",
"cliCode": "CLI Code's",
"cliCodeSubtitle": "Ferramentas de código que apontam para o OmniRoute",
"cliAgents": "CLI Agents",
@@ -1861,7 +1869,16 @@
"directDownloadHint": "Ou baixe o formato do instalador respectivo diretamente:",
"releaseNotes": "Notas de Lançamento",
"readMore": "Leia Mais",
"noAuthLabel": "Sem Autenticação"
"noAuthLabel": "Sem Autenticação",
"readinessEyebrow": "Prepare-se para rotear",
"readinessTitle": "Envie sua primeira requisição",
"readinessSubtitle": "Quatro etapas simples. O OmniRoute verifica se está tudo pronto ao longo da configuração.",
"readinessStep1": "Conecte um provedor",
"readinessStep2": "Configure a autenticação do endpoint",
"readinessStep3": "Copie seu endpoint",
"readinessStep4": "Envie uma requisição de teste",
"readinessContinue": "Continuar configuração",
"readinessDismiss": "Dispensar por enquanto"
},
"analytics": {
"title": "Análises",
@@ -2905,6 +2922,7 @@
"interpreter": "CLI do agente de codificação autônomo Open Interpreter",
"omp": "Agente de codificação de terminal Oh My Pi",
"letta": "Agente CLI Letta com memória persistente e uso de ferramentas",
"prime-agent": "Prime Agent — harness de codificação RLM autoevolutivo com suporte a API compatível com OpenAI",
"warp": "Terminal de IA Warp com suporte a provedor personalizado",
"agent-deck": "Orquestrador multi-agente Agent Deck"
},
@@ -3831,6 +3849,9 @@
},
"endpoint": {
"title": "Endpoint da API",
"subtitle": "Use o endpoint compatível com OpenAI na maioria dos SDKs e ferramentas.",
"testEndpoint": "Testar endpoint →",
"advancedProtocols": "Protocolos avançados",
"available": "Endpoints Disponíveis",
"cloudProxy": "Proxy na Nuvem",
"disableConfirm": "Tem certeza que deseja desativar o proxy na nuvem?",
@@ -4611,6 +4632,13 @@
"retry": "Tentar Novamente",
"allOperational": "Todos os sistemas operacionais",
"issuesDetected": "Problemas detectados no sistema",
"healthVerdictReady": "O OmniRoute está pronto",
"healthVerdictActionRequired": "Ação necessária para restaurar a operação plena",
"healthVerdictCoolingDown": "Em resfriamento após mudanças recentes",
"healthSubtitle": "Verificação de saúde do sistema",
"advancedDiagnosticsTitle": "Diagnósticos avançados",
"hide": "Ocultar",
"show": "Mostrar",
"updatedAt": "Atualizado {time}",
"latency": "Latência",
"latencyP50": "p50",
@@ -6682,6 +6710,18 @@
"sidebarVisibility": "Hide sidebar items",
"sidebarVisibilityDesc": "Hide any sidebar navigation entry to reduce visual clutter.",
"sidebarVisibilityHint": "Any sidebar section is hidden automatically when a...",
"presetAll": "Tudo",
"presetAllDesc": "Mostrar tudo",
"presetEssentials": "Essenciais",
"presetEssentialsDesc": "Caminho para iniciantes — as ferramentas avançadas continuam disponíveis na busca",
"presetMinimal": "Mínimo",
"presetMinimalDesc": "Somente páginas principais",
"presetDeveloper": "Desenvolvedor",
"presetDeveloperDesc": "Ferramentas de desenvolvimento e proxy",
"presetAdmin": "Administrador",
"presetAdminDesc": "Monitoramento e auditoria",
"settingsSidebarTitle": "Personalização da barra lateral",
"settingsSidebarDesc": "Escolha quais itens mostrar na barra lateral. No modo Essenciais, as ferramentas avançadas continuam disponíveis na busca.",
"hideHealthLogs": "Ocultar Logs de Health Check",
"hideHealthLogsDesc": "Quando ATIVADO, suprime mensagens [HealthCheck] no console do servidor",
"themeAccent": "Cor do tema",
@@ -12035,6 +12075,7 @@
"acp": {
"title": "ACP Agents",
"phrase": "CLIs que o OmniRoute spawna como backend de execução (fluxo reverso)",
"warning": "A maioria dos usuários pode ignorar isto — use apenas quando uma integração exigir.",
"flow": "Cliente → OmniRoute → spawn CLI (stdio/ACP) → resposta",
"seeOther": "Ver →"
}
@@ -13342,6 +13383,13 @@
},
"resilienceConnections": {
"title": "Resiliência de Conexão",
"reassuranceTitle": "Suas conexões se recuperam automaticamente",
"reassuranceDetail": "Normalmente nenhuma ação é necessária. O OmniRoute dá uma pausa temporária em uma conexão após falhas e depois a tenta novamente com segurança.",
"plainStates": {
"healthy": "Requisições podem ser enviadas",
"coolingDown": "Tentando novamente em breve",
"lockedOut": "Precisa da sua atenção"
},
"table": {
"status": "Status",
"provider": "Provedor",

View File

@@ -1267,6 +1267,7 @@
"agentBridgeSubtitle": "Chặn lưu lượng agent IDE",
"trafficInspector": "Traffic Inspector",
"trafficInspectorSubtitle": "Giám sát lệnh gọi LLM + gỡ lỗi mọi lưu lượng HTTPS",
"trafficInspectorPurpose": "Xem chính xác ứng dụng của bạn gửi gì đến và nhận gì từ các nhà cung cấp AI. Hoạt động với mọi ứng dụng khách tương thích OpenAI.",
"cliCode": "CLI Code",
"cliCodeSubtitle": "Các công cụ lập trình trỏ đến OmniRoute",
"cliAgents": "CLI Agents",
@@ -1300,13 +1301,7 @@
"open": "mở",
"close": "đóng"
},
"noResults": "Không có kết quả",
"healthVerdictReady": "OmniRoute đã sẵn sàng",
"healthVerdictActionRequired": "Cần hành động để khôi phục hoạt động đầy đủ",
"healthVerdictCoolingDown": "Đang nguội sau các thay đổi gần đây",
"advancedDiagnosticsTitle": "Chẩn đoán nâng cao",
"hide": "Ẩn",
"show": "Hiện"
"noResults": "Không có kết quả"
},
"webhooks": {
"title": "Webhook",
@@ -1874,7 +1869,16 @@
"directDownloadHint": "Hoặc tải trực tiếp định dạng trình cài đặt phù hợp:",
"releaseNotes": "Ghi chú phát hành",
"readMore": "Đọc thêm",
"noAuthLabel": "Không xác thực"
"noAuthLabel": "Không xác thực",
"readinessEyebrow": "Sẵn sàng định tuyến",
"readinessTitle": "Gửi yêu cầu đầu tiên",
"readinessSubtitle": "Bốn bước đơn giản. OmniRoute sẽ kiểm tra mức độ sẵn sàng trong quá trình thiết lập.",
"readinessStep1": "Kết nối một nhà cung cấp",
"readinessStep2": "Cấu hình xác thực endpoint",
"readinessStep3": "Sao chép endpoint của bạn",
"readinessStep4": "Gửi yêu cầu kiểm thử",
"readinessContinue": "Tiếp tục thiết lập",
"readinessDismiss": "Để sau"
},
"analytics": {
"title": "Phân tích",
@@ -2918,6 +2922,7 @@
"interpreter": "Tác nhân lập trình tự trị Open Interpreter CLI",
"omp": "Tác nhân lập trình Oh My Pi trên terminal",
"letta": "Tác nhân Letta CLI có bộ nhớ lâu dài và khả năng dùng công cụ",
"prime-agent": "Prime Agent — bộ khung lập trình RLM tự cải tiến hỗ trợ API tương thích OpenAI",
"warp": "Terminal Warp AI hỗ trợ nhà cung cấp tùy chỉnh",
"agent-deck": "Trình điều phối đa tác nhân Agent Deck"
},
@@ -4627,6 +4632,13 @@
"retry": "Thử lại",
"allOperational": "Tất cả hệ thống đang hoạt động bình thường",
"issuesDetected": "Phát hiện sự cố hệ thống",
"healthVerdictReady": "OmniRoute đã sẵn sàng",
"healthVerdictActionRequired": "Cần hành động để khôi phục hoạt động đầy đủ",
"healthVerdictCoolingDown": "Đang nguội sau các thay đổi gần đây",
"healthSubtitle": "Kiểm tra tình trạng hệ thống",
"advancedDiagnosticsTitle": "Chẩn đoán nâng cao",
"hide": "Ẩn",
"show": "Hiện",
"updatedAt": "Đã cập nhật {time}",
"latency": "Độ trễ",
"latencyP50": "p50",
@@ -6698,6 +6710,18 @@
"sidebarVisibility": "Ẩn các mục trên thanh bên",
"sidebarVisibilityDesc": "Ẩn bất kỳ mục điều hướng nào trên thanh bên để giảm bớt sự lộn xộn về mặt trực quan mà không vô hiệu hóa bất kỳ tính năng nào",
"sidebarVisibilityHint": "Bất kỳ phần nào trên thanh bên sẽ tự động bị ẩn khi tất cả các mục bên trong nó đều bị ẩn",
"presetAll": "Tất cả",
"presetAllDesc": "Hiển thị tất cả",
"presetEssentials": "Thiết yếu",
"presetEssentialsDesc": "Lộ trình cho người mới bắt đầu — vẫn có thể tìm kiếm các công cụ nâng cao",
"presetMinimal": "Tối giản",
"presetMinimalDesc": "Chỉ các trang cốt lõi",
"presetDeveloper": "Nhà phát triển",
"presetDeveloperDesc": "Công cụ phát triển và proxy",
"presetAdmin": "Quản trị",
"presetAdminDesc": "Giám sát và kiểm toán",
"settingsSidebarTitle": "Tùy chỉnh thanh bên",
"settingsSidebarDesc": "Chọn các mục hiển thị trên thanh bên. Chế độ Thiết yếu vẫn cho phép tìm kiếm các công cụ nâng cao.",
"hideHealthLogs": "Ẩn nhật ký kiểm tra sức khỏe",
"hideHealthLogsDesc": "Khi BẬT, sẽ chặn các thông báo [HealthCheck] trong bảng điều khiển máy chủ",
"themeAccent": "Màu chủ đề",

View File

@@ -0,0 +1,53 @@
/**
* Shared A2A authentication + caller-owner resolution (GHSA-jcm5-6wpp-wjj8).
*
* The JSON-RPC router (/a2a) grew its own authenticate() for GHSA-v54m, but
* the REST task routes under /api/a2a/tasks/ had no auth call at all. Both
* surfaces now share this single implementation so they cannot drift again:
* same REQUIRE_API_KEY posture as /v1, same keyless local-first default, and
* a stable owner id (hashed API key) used to scope task visibility.
*/
import { createHash, timingSafeEqual } from "crypto";
import type { NextRequest } from "next/server";
import { extractApiKey, isValidApiKey } from "@/sse/services/auth";
import { isRequireApiKeyEnabled } from "@/shared/utils/featureFlags";
function tokensMatch(provided: string, expected: string): boolean {
const a = Buffer.from(provided);
const b = Buffer.from(expected);
if (a.length !== b.length) return false;
return timingSafeEqual(a, b);
}
/**
* Whether the request may use the A2A surface at all. Mirrors the JSON-RPC
* posture: when a client key is required, demand a valid OmniRoute key;
* otherwise honor the legacy explicit A2A key; otherwise stay keyless (the
* same local-first default as /v1).
*/
export async function authenticateA2ARequest(req: NextRequest | Request): Promise<boolean> {
const apiKey = extractApiKey(req as NextRequest);
if (isRequireApiKeyEnabled()) {
return apiKey ? await isValidApiKey(apiKey) : false;
}
const configuredKey = process.env.OMNIROUTE_API_KEY;
if (configuredKey) {
return apiKey ? tokensMatch(apiKey, configuredKey) : false;
}
// No API key required and none configured — allow (keyless local-first).
return true;
}
/**
* Owner id for task scoping (GHSA-jcm5-6wpp-wjj8): a stable hash of the
* caller's API key, or `undefined` when the call carries no key (keyless
* posture — ownerless tasks stay visible to everyone, by design).
*/
export function resolveA2AOwner(req: NextRequest | Request): string | undefined {
const apiKey = extractApiKey(req as NextRequest);
if (!apiKey) return undefined;
return createHash("sha256").update(apiKey).digest("hex").slice(0, 32);
}

View File

@@ -47,6 +47,26 @@ export interface A2ATask {
expiresAt: string;
}
/**
* Authorization scope for task reads and mutations (GHSA-jcm5-6wpp-wjj8).
*
* - operator: authenticated management callers can see every task.
* - owner: API-key callers can see their tasks plus public ownerless tasks.
* - ownerless: the keyless local-first posture can see only ownerless tasks.
*
* The owner hash is intentionally absent from A2ATask so JSON responses cannot
* expose an offline-verifiable derivative of a caller's API key.
*/
export type A2ATaskScope =
{ kind: "operator" } | { kind: "owner"; owner: string } | { kind: "ownerless" };
export const A2A_OPERATOR_SCOPE: A2ATaskScope = Object.freeze({ kind: "operator" });
export const A2A_OWNERLESS_SCOPE: A2ATaskScope = Object.freeze({ kind: "ownerless" });
export function a2aOwnerScope(owner: string): A2ATaskScope {
return { kind: "owner", owner };
}
export interface TaskListFilter {
state?: TaskState;
skill?: string;
@@ -75,6 +95,7 @@ const VALID_TRANSITIONS: Record<TaskState, TaskState[]> = {
export class A2ATaskManager {
private tasks = new Map<string, A2ATask>();
private taskOwners = new Map<string, string>();
private readonly ttlMs: number;
private cleanupInterval: ReturnType<typeof setInterval>;
private activeStreams = 0;
@@ -91,7 +112,7 @@ export class A2ATaskManager {
}
}
createTask(input: TaskInput): A2ATask {
createTask(input: TaskInput, owner?: string): A2ATask {
const now = new Date();
const task: A2ATask = {
id: randomUUID(),
@@ -106,17 +127,31 @@ export class A2ATaskManager {
expiresAt: new Date(now.getTime() + this.ttlMs).toISOString(),
};
this.tasks.set(task.id, task);
if (owner !== undefined) this.taskOwners.set(task.id, owner);
return task;
}
getTask(taskId: string): A2ATask | undefined {
/**
* Ownerless tasks stay visible to every scope. Owned tasks require either
* the matching owner or an explicit operator scope.
*/
private isVisibleTo(taskId: string, scope: A2ATaskScope): boolean {
const taskOwner = this.taskOwners.get(taskId);
if (taskOwner === undefined) return true;
if (scope.kind === "operator") return true;
return scope.kind === "owner" && taskOwner === scope.owner;
}
getTask(taskId: string, scope: A2ATaskScope = A2A_OPERATOR_SCOPE): A2ATask | undefined {
const task = this.tasks.get(taskId);
if (task && new Date(task.expiresAt) < new Date()) {
if (task.state === "submitted" || task.state === "working") {
this.updateTask(taskId, "failed", undefined, "Task expired");
}
}
return this.tasks.get(taskId);
const current = this.tasks.get(taskId);
if (!current || !this.isVisibleTo(taskId, scope)) return undefined;
return current;
}
updateTask(
@@ -142,21 +177,37 @@ export class A2ATaskManager {
return task;
}
cancelTask(taskId: string): A2ATask {
cancelTask(taskId: string, scope: A2ATaskScope = A2A_OPERATOR_SCOPE): A2ATask {
// Owner check BEFORE the mutation (GHSA-jcm5-6wpp-wjj8): a caller must not
// cancel another principal's task by id. Uses the same not-found error as
// a missing task so an IDOR probe cannot distinguish "exists but not
// yours" from "does not exist".
const task = this.tasks.get(taskId);
if (!task || !this.isVisibleTo(taskId, scope)) {
throw new Error(`Task ${taskId} not found`);
}
return this.updateTask(taskId, "cancelled", undefined, "Cancelled by client");
}
countTasks(filter?: Pick<TaskListFilter, "state" | "skill">): number {
let tasks = [...this.tasks.values()];
private filterTasks(
filter: Pick<TaskListFilter, "state" | "skill"> | undefined,
scope: A2ATaskScope
): A2ATask[] {
let tasks = [...this.tasks.values()].filter((task) => this.isVisibleTo(task.id, scope));
if (filter?.state) tasks = tasks.filter((t) => t.state === filter.state);
if (filter?.skill) tasks = tasks.filter((t) => t.skill === filter.skill);
return tasks.length;
return tasks;
}
listTasks(filter?: TaskListFilter): A2ATask[] {
let tasks = [...this.tasks.values()];
if (filter?.state) tasks = tasks.filter((t) => t.state === filter.state);
if (filter?.skill) tasks = tasks.filter((t) => t.skill === filter.skill);
countTasks(
filter?: Pick<TaskListFilter, "state" | "skill">,
scope: A2ATaskScope = A2A_OPERATOR_SCOPE
): number {
return this.filterTasks(filter, scope).length;
}
listTasks(filter?: TaskListFilter, scope: A2ATaskScope = A2A_OPERATOR_SCOPE): A2ATask[] {
const tasks = this.filterTasks(filter, scope);
tasks.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
const offset = Math.max(0, filter?.offset || 0);
const limit =
@@ -220,6 +271,7 @@ export class A2ATaskManager {
now.getTime() - new Date(task.updatedAt).getTime() > this.ttlMs * 2
) {
this.tasks.delete(id);
this.taskOwners.delete(id);
}
}
}

View File

@@ -43,6 +43,8 @@ export const LOCAL_ONLY_API_PREFIXES: ReadonlyArray<string> = [
"/dashboard/providers/services/", // T-07: reverse proxy to embedded service UIs
"/api/copilot/", // unauthenticated LLM driver — CLI-only by default; admins can opt-in to remote access via manage-scope bypass
"/api/tools/agent-bridge/", // AgentBridge: spawns MITM server + DNS edits (Hard Rules #15 + #17)
"/api/settings/mitm", // "Enable MITM" flow: installs a system-wide trusted root CA (security add-trusted-cert / certutil / update-ca-certificates) and writes /etc/hosts DNS overrides via src/mitm/* — host-level TLS interception. Was MANAGEMENT-only, so requireLogin=false left it remotely reachable (GHSA-x7vm-hp44-9p79, Hard Rules #15 + #17). Same tier as /api/tools/agent-bridge/.
"/api/cli-tools/antigravity-mitm", // Antigravity MITM enable flow: same privileged CA-trust + DNS surface as /api/settings/mitm (GHSA-x7vm-hp44-9p79, Hard Rules #15 + #17). Covers the /alias child route by prefix.
"/api/tools/traffic-inspector/", // Traffic Inspector: http-proxy listener + system proxy (Hard Rules #15 + #17)
"/api/issue-agent/", // Issue Agent: recorded/local triage executor surface; keep loopback/LAN until sandbox + audit hardening is complete
"/api/plugins/", // plugins: load/execute via worker_threads + child_process (Hard Rules #15 + #17)
@@ -125,6 +127,12 @@ export const ALWAYS_PROTECTED_API_PATHS: ReadonlyArray<string> = [
// /api/settings/database already does. isAlwaysProtectedPath matches on a path
// boundary, so this covers export, exportAll and import. (GHSA-mghq-58h3-qcqj)
"/api/db-backups",
// Legacy siblings of /api/db-backups left out of the mghq fix: export-json
// dumps every stored credential and import-json irreversibly replaces
// settings/connections, and both handlers only gate on isAuthRequired() —
// which is false under requireLogin=false. (GHSA-v7g9-7f55-5g46)
"/api/settings/export-json",
"/api/settings/import-json",
];
export function isLoopbackHost(hostHeader: string | null): boolean {

View File

@@ -156,7 +156,7 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
];
});
}),
[hiddenItems, radarAdminUrl, safeTranslate]
[activePreset, hiddenItems, radarAdminUrl, safeTranslate]
);
const filtered = useMemo(() => {

View File

@@ -28,6 +28,8 @@ export const SPAWN_CAPABLE_PREFIXES: ReadonlyArray<string> = [
"/api/cli-tools/qwen-settings", // GET probes the Qwen Code binary; the route also mutates local ~/.qwen files
"/api/services/", // T-10: can run npm install + spawn node processes
"/api/tools/agent-bridge/", // start/stop MITM server + DNS edits (Hard Rules #15 + #17)
"/api/settings/mitm", // installs a system trusted root CA + /etc/hosts DNS overrides via src/mitm/* — must never be whitelistable via manage-scope bypass (GHSA-x7vm-hp44-9p79, Hard Rules #15 + #17)
"/api/cli-tools/antigravity-mitm", // same privileged CA-trust + DNS surface as /api/settings/mitm (GHSA-x7vm-hp44-9p79, Hard Rules #15 + #17)
"/api/tools/traffic-inspector/", // http-proxy listener + system proxy (Hard Rules #15 + #17)
"/api/plugins/", // plugins: load/execute via worker_threads + child_process (Hard Rules #15 + #17)
"/api/local/", // T-12: 1-click local service launchers (Redis today) — must never be whitelistable via manage-scope bypass (Hard Rules #15 + #17)

View File

@@ -67,4 +67,5 @@ export const EXPECTED_CODE_COUNT = 21;
// +2 (#6318): "omp" (Oh My Pi) and "letta" (Letta CLI) added as agent entries.
// Note: #6318 originally also shipped duplicate "pi"/"jcode"/"codewhale" entries —
// those tools were already delivered by a separate PR, so only omp+letta landed here.
export const EXPECTED_AGENT_COUNT = 8;
// +1 (#11166): "prime-agent" (PrimeIntellect-ai/prime-agent) added as an agent entry.
export const EXPECTED_AGENT_COUNT = 9;

View File

@@ -306,6 +306,7 @@
"tests/unit/public-client-ids-3493.test.ts",
"tests/unit/publicCreds.test.ts",
"tests/unit/qoder-oauth-config.test.ts",
"tests/unit/quota-exhaustion-cutoff-opencode.test.ts",
"tests/unit/quota-groups-route.test.ts",
"tests/unit/quota-key-models-route.test.ts",
"tests/unit/quota-policy-generalization.test.ts",

View File

@@ -5,24 +5,59 @@ import { getRegistryEntry } from "../../open-sse/config/providerRegistry.ts";
const { getNextFamilyFallback } = await import("../../open-sse/services/modelFamilyFallback.ts");
// Regression for #8134: family fallback candidates absent from the resolved
// provider catalog must be skipped. GitHub now legitimately supports Opus 4.6,
// so its current chain exercises that tier while GHE Copilot remains the
// negative fixture because its catalog omits 4.6.
// Regression for #8134 — GitHub Copilot ("github", alias "gh") T5 family fallback
// returned "claude-opus-4-6" verbatim even though the github registry catalog at
// the time (Opus 4.8 / 4.8-fast / 4.7 / 4.5) had NO 4.6 tier under any dot/hyphen
// notation. getNextFamilyFallback() resolved `supportedIds` from the provider's
// registry but only used it to try notation variants of a candidate, never to
// filter out a candidate that is provably absent from the catalog — so the
// unsupported id fell through and was returned anyway, costing a 3rd wasted
// upstream round-trip before the family was exhausted.
//
// Fix: when the provider registry is resolved, getNextFamilyFallback() now
// skips (continue) any family candidate that has no match in supportedIds
// under ANY notation (hyphen, dot, or a dated-snapshot id with the date
// suffix stripped) instead of returning it unfiltered.
//
// Fixture note: #10952 later added claude-opus-4.6 to the github registry, so
// the provably-absent tier used by the fixture moved to claude-opus-4-6-thinking
// (the ladder's first candidate after 4.6 — still absent from the catalog).
test("#8134: github claude-opus-4.8 follows its current supported fallback chain", () => {
test("#8134: github claude-opus fallback chain never returns an unsupported tier (claude-opus-4-6-thinking)", () => {
const github = getRegistryEntry("github");
assert.ok(github, "expected the github registry entry to resolve");
const githubIds = new Set(github.models.map((m) => m.id));
assert.ok(githubIds.has("claude-opus-4.6"), "expected github to support Opus 4.6");
// Fixture assumption: #10952 added claude-opus-4.6 to the github registry, so
// the original absent-tier role moved to the 4.6-thinking variant, which the
// catalog still does NOT carry under any notation.
assert.ok(
!githubIds.has("claude-opus-4-6-thinking") && !githubIds.has("claude-opus-4.6-thinking"),
"fixture assumption broken: github registry now has a 4.6-thinking tier"
);
// Ladder reality: 4.8 -> 4.7 -> 4.6 -> [4-6-thinking (absent), 4-5-20251101,
// sonnet-5]. The absent 4-6-thinking must be SKIPPED — the third hop resolves
// to the dated 4.5 snapshot's undated catalog entry, never to 4-6-thinking.
const tried = new Set(["github/claude-opus-4.8"]);
const first = getNextFamilyFallback("github/claude-opus-4.8", tried);
assert.equal(first, "github/claude-opus-4.7");
tried.add(first);
const second = getNextFamilyFallback(first, tried);
assert.equal(second, "github/claude-opus-4.6");
const hops: string[] = [];
let current = "github/claude-opus-4.8";
for (let hop = 0; hop < 3; hop++) {
const next = getNextFamilyFallback(current, tried);
assert.ok(next, `hop ${hop + 1}: family must not be silently exhausted`);
const bareId = next!.replace(/^github\//, "");
assert.ok(
githubIds.has(bareId),
`hop ${hop + 1}: "${next}" is not in github's registered model catalog: ${[...githubIds].join(", ")}`
);
assert.notEqual(bareId, "claude-opus-4-6-thinking");
assert.notEqual(bareId, "claude-opus-4.6-thinking");
tried.add(next!);
hops.push(next!);
current = next!;
}
// The skip specifically fired: the 4.6 -> next hop jumped past the absent
// 4-6-thinking tier straight to a catalogued model.
assert.equal(hops[2].replace(/^github\//, ""), "claude-opus-4.5");
});
test("#8134: getNextFamilyFallback never returns a candidate absent from the resolved provider's catalog", () => {

View File

@@ -0,0 +1,349 @@
/**
* GHSA-jcm5-6wpp-wjj8 — A2A task IDOR + unauthenticated REST task routes.
*
* Two gaps closed here:
* 1. The REST routes /api/a2a/tasks/[id] and /api/a2a/tasks/[id]/cancel had
* NO auth call at all — open regardless of configuration. They now share
* the JSON-RPC surface's authentication (REQUIRE_API_KEY posture).
* 2. Tasks lived in an owner-less Map: any caller could read/cancel any
* task by id. Tasks now bind to an owner (hashed API key) at creation and
* reads/cancels/lists are owner-scoped. Ownerless tasks (keyless
* local-first posture) stay visible to everyone — by design.
*
* Run with:
* node --import tsx/esm --test tests/unit/a2a-task-owner-idor.test.ts
*/
import { after, describe, it, mock } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omni-a2a-idor-"));
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.API_KEY_SECRET = process.env.API_KEY_SECRET || "a2a-idor-test-secret";
process.env.OMNIROUTE_DISABLE_REDIS_AUTH_CACHE = "1";
const core = await import("../../src/lib/db/core.ts");
const apiKeysDb = await import("../../src/lib/db/apiKeys.ts");
const settingsDb = await import("../../src/lib/db/settings.ts");
const { A2ATaskManager, A2A_OPERATOR_SCOPE, A2A_OWNERLESS_SCOPE, a2aOwnerScope, getTaskManager } =
await import("../../src/lib/a2a/taskManager.ts");
const { resolveA2AOwner } = await import("../../src/lib/a2a/authenticate.ts");
const jsonRpcRoute = await import("../../src/app/a2a/route.ts");
const restList = await import("../../src/app/api/a2a/tasks/route.ts");
const restGet = await import("../../src/app/api/a2a/tasks/[id]/route.ts");
const { makeManagementSessionRequest } = await import("../helpers/managementSession.ts");
const ORIGINAL_REQUIRE = process.env.REQUIRE_API_KEY;
const ORIGINAL_OMNIROUTE_KEY = process.env.OMNIROUTE_API_KEY;
const ORIGINAL_JWT_SECRET = process.env.JWT_SECRET;
after(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
if (ORIGINAL_REQUIRE === undefined) delete process.env.REQUIRE_API_KEY;
else process.env.REQUIRE_API_KEY = ORIGINAL_REQUIRE;
if (ORIGINAL_OMNIROUTE_KEY === undefined) delete process.env.OMNIROUTE_API_KEY;
else process.env.OMNIROUTE_API_KEY = ORIGINAL_OMNIROUTE_KEY;
if (ORIGINAL_JWT_SECRET === undefined) delete process.env.JWT_SECRET;
else process.env.JWT_SECRET = ORIGINAL_JWT_SECRET;
});
function makeManager() {
const tm = new A2ATaskManager(5);
// Prevent the per-instance cleanup interval from keeping the process alive.
clearInterval((tm as unknown as { cleanupInterval: NodeJS.Timeout }).cleanupInterval);
return tm;
}
describe("A2ATaskManager — owner scoping (GHSA-jcm5)", () => {
it("another principal cannot READ an owned task (same undefined as missing)", () => {
const tm = makeManager();
const task = tm.createTask({ skill: "smart-routing", messages: [] }, "owner-a");
assert.equal(
tm.getTask(task.id, a2aOwnerScope("owner-a"))?.id,
task.id,
"the owner still reads it"
);
assert.equal(
tm.getTask(task.id, a2aOwnerScope("owner-b")),
undefined,
"another owner gets undefined"
);
});
it("another principal cannot CANCEL an owned task (not-found error, no existence oracle)", () => {
const tm = makeManager();
const task = tm.createTask({ skill: "smart-routing", messages: [] }, "owner-a");
assert.throws(() => tm.cancelTask(task.id, a2aOwnerScope("owner-b")), /not found/);
assert.equal(
tm.getTask(task.id, a2aOwnerScope("owner-a"))?.state,
"submitted",
"task untouched"
);
assert.equal(
tm.cancelTask(task.id, a2aOwnerScope("owner-a")).state,
"cancelled",
"the owner can cancel"
);
});
it("uses the same operator/owner/ownerless scope for list, get, cancel and count", () => {
const tm = makeManager();
const foreign = tm.createTask({ skill: "s1", messages: [] }, "owner-a");
const mine = tm.createTask({ skill: "s1", messages: [] }, "owner-b");
const ownerless = tm.createTask({ skill: "s1", messages: [] });
const ownerScope = a2aOwnerScope("owner-b");
const listed = tm.listTasks(undefined, ownerScope);
assert.deepEqual(new Set(listed.map((t) => t.id)), new Set([ownerless.id, mine.id]));
assert.equal(tm.countTasks(undefined, ownerScope), 2);
assert.equal(tm.getTask(foreign.id, ownerScope), undefined);
assert.equal(tm.listTasks(undefined, A2A_OWNERLESS_SCOPE).length, 1);
assert.equal(tm.countTasks(undefined, A2A_OWNERLESS_SCOPE), 1);
assert.equal(tm.getTask(mine.id, A2A_OWNERLESS_SCOPE), undefined);
assert.equal(tm.listTasks(undefined, A2A_OPERATOR_SCOPE).length, 3);
assert.equal(tm.countTasks(undefined, A2A_OPERATOR_SCOPE), 3);
assert.equal(tm.getTask(foreign.id, A2A_OPERATOR_SCOPE)?.id, foreign.id);
assert.equal(
tm.cancelTask(foreign.id, A2A_OPERATOR_SCOPE).state,
"cancelled",
"operator can manage every task"
);
});
it("ownerless tasks stay visible to everyone (keyless local-first posture)", () => {
const tm = makeManager();
const task = tm.createTask({ skill: "smart-routing", messages: [] });
assert.equal(tm.getTask(task.id, a2aOwnerScope("anyone"))?.id, task.id);
assert.equal(tm.getTask(task.id, A2A_OWNERLESS_SCOPE)?.id, task.id);
assert.equal(tm.cancelTask(task.id, a2aOwnerScope("anyone")).state, "cancelled");
});
it("keeps the authorization owner private when tasks are serialized", () => {
const tm = makeManager();
const task = tm.createTask({ skill: "smart-routing", messages: [] }, "secret-owner-hash");
assert.equal(JSON.stringify(task).includes("secret-owner-hash"), false);
assert.equal(Object.hasOwn(task, "owner"), false);
});
});
describe("REST /api/a2a/tasks/[id] — authentication (GHSA-jcm5)", () => {
it("rejects an unkeyed call when REQUIRE_API_KEY=true (was: no auth at all)", async () => {
process.env.REQUIRE_API_KEY = "true";
delete process.env.OMNIROUTE_API_KEY;
const res = await restGet.GET(new Request("http://localhost/api/a2a/tasks/abc") as never, {
params: Promise.resolve({ id: "abc" }),
});
assert.equal(res.status, 401);
});
it("serves a keyed call under REQUIRE_API_KEY=true", async () => {
process.env.REQUIRE_API_KEY = "true";
const key = await apiKeysDb.createApiKey("a2a-rest-client", "machine-rest", []);
const res = await restGet.GET(
new Request("http://localhost/api/a2a/tasks/definitely-missing", {
headers: { authorization: `Bearer ${key.key}` },
}) as never,
{ params: Promise.resolve({ id: "definitely-missing" }) }
);
// Authenticated — the 404 now comes from the task lookup, not the auth gate.
assert.equal(res.status, 404);
});
it("keyed caller gets 404 for another principal's task (route-level IDOR, GHSA-jcm5)", async () => {
process.env.REQUIRE_API_KEY = "true";
const tm = getTaskManager();
// A task owned by a DIFFERENT principal than the caller's key hash.
const foreign = tm.createTask({ skill: "smart-routing", messages: [] }, "some-other-owner");
const key = await apiKeysDb.createApiKey("a2a-rest-idor", "machine-idor", []);
const req = new Request(`http://localhost/api/a2a/tasks/${foreign.id}`, {
headers: { authorization: `Bearer ${key.key}` },
});
const res = await restGet.GET(req as never, { params: Promise.resolve({ id: foreign.id }) });
assert.equal(res.status, 404, "another principal's task is invisible");
// And the same task IS visible to its owner (owner hash derived from the key).
const owned = tm.createTask(
{ skill: "smart-routing", messages: [] },
resolveA2AOwner(req as never)
);
const res2 = await restGet.GET(
new Request(`http://localhost/api/a2a/tasks/${owned.id}`, {
headers: { authorization: `Bearer ${key.key}` },
}) as never,
{ params: Promise.resolve({ id: owned.id }) }
);
assert.equal(res2.status, 200, "the owner reads its own task");
});
});
describe("A2A public surfaces — scope consistency", () => {
it("maps a management session to operator scope", async () => {
process.env.REQUIRE_API_KEY = "false";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ requireLogin: true, password: "" });
const skill = `scope-operator-${Date.now()}`;
const tm = getTaskManager();
const owned = tm.createTask({ skill, messages: [] }, "api-key-owner");
const ownerless = tm.createTask({ skill, messages: [] });
const request = await makeManagementSessionRequest(
`http://localhost/api/a2a/tasks?skill=${encodeURIComponent(skill)}`
);
const response = await restList.GET(request);
assert.equal(response.status, 200);
const body = (await response.json()) as { tasks: Array<{ id: string }>; total: number };
assert.deepEqual(new Set(body.tasks.map((task) => task.id)), new Set([owned.id, ownerless.id]));
assert.equal(body.total, 2);
});
it("keeps a valid API-key caller owner-scoped when requireLogin=false", async () => {
process.env.REQUIRE_API_KEY = "false";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ requireLogin: false });
const key = await apiKeysDb.createApiKey("a2a-rest-default", "machine-default", []);
const request = new Request("http://localhost/api/a2a/tasks", {
headers: { authorization: `Bearer ${key.key}` },
});
const skill = `scope-default-${Date.now()}`;
const tm = getTaskManager();
const mine = tm.createTask({ skill, messages: [] }, resolveA2AOwner(request as never));
const ownerless = tm.createTask({ skill, messages: [] });
tm.createTask({ skill, messages: [] }, "foreign-owner");
const response = await restList.GET(
new Request(`${request.url}?skill=${encodeURIComponent(skill)}`, {
headers: request.headers,
})
);
assert.equal(response.status, 200);
const body = (await response.json()) as {
tasks: Array<{ id: string; owner?: string }>;
total: number;
};
assert.deepEqual(
new Set(body.tasks.map((task) => task.id)),
new Set([mine.id, ownerless.id]),
"an optional-but-valid key must never be promoted to operator"
);
assert.equal(body.total, 2, "total must use the same owner scope as tasks[]");
assert.equal(
body.tasks.some((task) => Object.hasOwn(task, "owner")),
false
);
});
it("keeps the explicit A2A bearer owner-scoped across JSON-RPC and REST", async () => {
process.env.REQUIRE_API_KEY = "false";
process.env.OMNIROUTE_API_KEY = "explicit-a2a-cross-surface-key";
await settingsDb.updateSettings({ requireLogin: false });
const request = new Request("http://localhost/api/a2a/tasks", {
headers: { authorization: `Bearer ${process.env.OMNIROUTE_API_KEY}` },
});
const skill = `scope-explicit-key-${Date.now()}`;
const tm = getTaskManager();
const mine = tm.createTask({ skill, messages: [] }, resolveA2AOwner(request as never));
tm.createTask({ skill, messages: [] }, "foreign-owner");
const response = await restList.GET(
new Request(`${request.url}?skill=${encodeURIComponent(skill)}`, {
headers: request.headers,
})
);
assert.equal(response.status, 200);
const body = (await response.json()) as { tasks: Array<{ id: string }>; total: number };
assert.deepEqual(
body.tasks.map((task) => task.id),
[mine.id]
);
assert.equal(body.total, 1);
});
it("keeps keyless REST callers limited to ownerless tasks", async () => {
process.env.REQUIRE_API_KEY = "false";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ requireLogin: false });
const skill = `scope-keyless-rest-${Date.now()}`;
const tm = getTaskManager();
const ownerless = tm.createTask({ skill, messages: [] });
tm.createTask({ skill, messages: [] }, "foreign-owner");
const response = await restList.GET(
new Request(`http://localhost/api/a2a/tasks?skill=${encodeURIComponent(skill)}`)
);
assert.equal(response.status, 200);
const body = (await response.json()) as { tasks: Array<{ id: string }>; total: number };
assert.deepEqual(
body.tasks.map((task) => task.id),
[ownerless.id]
);
assert.equal(body.total, 1);
});
it("keeps keyless JSON-RPC get limited to ownerless tasks", async () => {
process.env.REQUIRE_API_KEY = "false";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ a2aEnabled: true });
const tm = getTaskManager();
const ownerless = tm.createTask({ skill: "smart-routing", messages: [] });
const foreign = tm.createTask(
{ skill: "smart-routing", messages: [] },
"foreign-json-rpc-owner"
);
const requestTask = (taskId: string) =>
new Request("http://localhost/a2a", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tasks/get",
params: { taskId },
}),
});
const visible = await jsonRpcRoute.POST(requestTask(ownerless.id) as never);
assert.equal(visible.status, 200);
const visibleBody = (await visible.json()) as {
result: { task: { id: string; owner?: string } };
};
assert.equal(visibleBody.result.task.id, ownerless.id);
assert.equal(Object.hasOwn(visibleBody.result.task, "owner"), false);
const hidden = await jsonRpcRoute.POST(requestTask(foreign.id) as never);
assert.equal(hidden.status, 404);
const hiddenBody = (await hidden.json()) as { error: { code: number } };
assert.equal(hiddenBody.error.code, -32601);
});
it("sanitizes GET list failures instead of returning raw error.message", async () => {
process.env.REQUIRE_API_KEY = "false";
await settingsDb.updateSettings({ requireLogin: false });
const tm = getTaskManager();
const countTasks = mock.method(tm, "countTasks", () => {
throw new Error("list failed\n at /srv/private/a2a.ts:1:1");
});
try {
const response = await restList.GET(new Request("http://localhost/api/a2a/tasks"));
assert.equal(response.status, 500);
const body = (await response.json()) as { error: string };
assert.equal(body.error.includes("at /"), false);
assert.equal(body.error.includes("/srv/private"), false);
} finally {
countTasks.mock.restore();
}
});
});

View File

@@ -1,91 +1,91 @@
import test from "node:test";
import { after, afterEach, test } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omni-a2a-tasks-auth-"));
process.env.DATA_DIR = TEST_DATA_DIR;
process.env.API_KEY_SECRET = process.env.API_KEY_SECRET || "a2a-tasks-auth-test-secret";
process.env.OMNIROUTE_DISABLE_REDIS_AUTH_CACHE = "1";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const A2A_AUTH_HELPER = path.resolve(__dirname, "../../src/lib/a2a/authenticate.ts");
const TASKS_ROUTE = path.resolve(__dirname, "../../src/app/api/a2a/tasks/route.ts");
const A2A_ROUTE = path.resolve(__dirname, "../../src/app/a2a/route.ts");
const core = await import("../../src/lib/db/core.ts");
const apiKeysDb = await import("../../src/lib/db/apiKeys.ts");
const settingsDb = await import("../../src/lib/db/settings.ts");
const tasksRoute = await import("../../src/app/api/a2a/tasks/route.ts");
const { authenticateA2ARequest } = await import("../../src/lib/a2a/authenticate.ts");
const source = fs.readFileSync(TASKS_ROUTE, "utf-8");
const ORIGINAL_REQUIRE = process.env.REQUIRE_API_KEY;
const ORIGINAL_OMNIROUTE_KEY = process.env.OMNIROUTE_API_KEY;
const { tokensMatch, authenticateA2A } = await import("../../src/app/api/a2a/tasks/route.ts");
afterEach(() => {
if (ORIGINAL_REQUIRE === undefined) delete process.env.REQUIRE_API_KEY;
else process.env.REQUIRE_API_KEY = ORIGINAL_REQUIRE;
if (ORIGINAL_OMNIROUTE_KEY === undefined) delete process.env.OMNIROUTE_API_KEY;
else process.env.OMNIROUTE_API_KEY = ORIGINAL_OMNIROUTE_KEY;
});
function hasImport(src: string, name: string, from: string): boolean {
const pattern = new RegExp(
`import\\s+\\{[^}]*\\b${name}\\b[^}]*\\}\\s+from\\s+["']${from}["']`
);
return pattern.test(src);
after(() => {
core.resetDbInstance();
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
function request(token?: string): Request {
return new Request("http://localhost/api/a2a/tasks", {
method: "POST",
headers: token ? { authorization: `Bearer ${token}` } : undefined,
});
}
test("tasks route uses the same constant-time contract as src/app/a2a/route.ts", () => {
const a2aSource = fs.readFileSync(A2A_ROUTE, "utf-8");
assert.ok(
hasImport(a2aSource, "timingSafeEqual", "node:crypto"),
"reference route imports timingSafeEqual"
);
assert.ok(
hasImport(source, "timingSafeEqual", "node:crypto"),
"tasks route imports timingSafeEqual"
);
assert.ok(
/\btokensMatch\s*\(\s*token\s*,\s*configuredKey\s*\)/.test(source),
"tasks route authenticates with tokensMatch(token, configuredKey)"
);
assert.ok(
!/return\s+token\s*===\s*configuredKey\s*;/.test(source),
"tasks route no longer uses a plain === bearer compare"
);
test("shared A2A helper keeps the explicit legacy key comparison constant-time", () => {
const source = fs.readFileSync(A2A_AUTH_HELPER, "utf-8");
assert.match(source, /import\s+\{[^}]*\btimingSafeEqual\b[^}]*\}\s+from\s+["']crypto["']/);
assert.match(source, /timingSafeEqual\(a, b\)/);
assert.doesNotMatch(source, /return\s+provided\s*===\s*expected/);
});
test("tokensMatch behaves like the helper in src/app/a2a/route.ts", () => {
assert.equal(tokensMatch("omniroute-a2a-test-key", "omniroute-a2a-test-key"), true);
assert.equal(
tokensMatch("x".repeat("omniroute-a2a-test-key".length), "omniroute-a2a-test-key"),
false,
"same-length different token is rejected"
);
assert.equal(tokensMatch("", "omniroute-a2a-test-key"), false, "empty token is rejected");
assert.equal(
tokensMatch("short", "omniroute-a2a-test-key"),
false,
"different-length token is rejected without throwing"
);
});
test("authenticateA2A preserves the documented semantics", () => {
const API_KEY = "omniroute-a2a-test-key";
function makeRequest(token?: string): Request {
return {
headers: {
get(name: string) {
if (name.toLowerCase() !== "authorization") return null;
return token === undefined ? null : `Bearer ${token}`;
},
},
} as unknown as Request;
}
test("POST /api/a2a/tasks enforces REQUIRE_API_KEY even without OMNIROUTE_API_KEY", async () => {
process.env.REQUIRE_API_KEY = "true";
delete process.env.OMNIROUTE_API_KEY;
assert.equal(
authenticateA2A(makeRequest()),
true,
"when OMNIROUTE_API_KEY is not set the route is open"
);
process.env.OMNIROUTE_API_KEY = API_KEY;
assert.equal(authenticateA2A(makeRequest(API_KEY)), true, "a valid bearer token passes auth");
const response = await tasksRoute.POST(request());
assert.equal(response.status, 401);
});
test("POST /api/a2a/tasks accepts a valid database API key under REQUIRE_API_KEY", async () => {
process.env.REQUIRE_API_KEY = "true";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ a2aEnabled: false });
const key = await apiKeysDb.createApiKey("a2a-post", "machine-post", []);
const response = await tasksRoute.POST(request(key.key));
assert.equal(response.status, 503, "auth passed; the disabled endpoint gate answered next");
});
test("POST /api/a2a/tasks preserves the keyless local-first posture", async () => {
process.env.REQUIRE_API_KEY = "false";
delete process.env.OMNIROUTE_API_KEY;
await settingsDb.updateSettings({ a2aEnabled: false });
assert.equal(await authenticateA2ARequest(request()), true);
const response = await tasksRoute.POST(request());
assert.equal(
authenticateA2A(makeRequest("x".repeat(API_KEY.length))),
false,
"a same-length but different token is rejected"
response.status,
503,
"keyless auth passed; the disabled endpoint gate answered next"
);
assert.equal(authenticateA2A(makeRequest("")), false, "an empty bearer token is rejected");
});
delete process.env.OMNIROUTE_API_KEY;
test("shared A2A helper honors an explicit OMNIROUTE_API_KEY", async () => {
process.env.REQUIRE_API_KEY = "false";
process.env.OMNIROUTE_API_KEY = "omniroute-a2a-test-key";
assert.equal(await authenticateA2ARequest(request("omniroute-a2a-test-key")), true);
assert.equal(await authenticateA2ARequest(request("same-length-wrong-key")), false);
assert.equal(await authenticateA2ARequest(request()), false);
});

View File

@@ -22,6 +22,22 @@ test("isLocalOnlyPath: /api/cli-tools/runtime/ is local-only", () => {
assert.equal(isLocalOnlyPath("/api/cli-tools/runtime/claude"), true);
});
test("isLocalOnlyPath: MITM management routes are local-only (GHSA-x7vm-hp44-9p79)", () => {
// The "Enable MITM" flow installs a system-wide trusted root CA and writes
// /etc/hosts DNS overrides (src/mitm/*) — host-level TLS interception. Both
// routes were MANAGEMENT-classified only, so requireLogin=false left them
// remotely reachable. They belong to the same loopback tier as
// /api/tools/agent-bridge/ (also MITM + DNS).
assert.equal(isLocalOnlyPath("/api/settings/mitm"), true);
assert.equal(isLocalOnlyPath("/api/cli-tools/antigravity-mitm"), true);
assert.equal(isLocalOnlyPath("/api/cli-tools/antigravity-mitm/alias"), true);
});
test("isLocalOnlyBypassableByManageScope: MITM routes are NOT bypassable (GHSA-x7vm-hp44-9p79)", () => {
assert.equal(isLocalOnlyBypassableByManageScope("/api/settings/mitm"), false);
assert.equal(isLocalOnlyBypassableByManageScope("/api/cli-tools/antigravity-mitm"), false);
});
test("isLocalOnlyPath: regular management routes are not local-only", () => {
assert.equal(isLocalOnlyPath("/api/settings"), false);
assert.equal(isLocalOnlyPath("/api/providers"), false);
@@ -89,6 +105,19 @@ test("isAlwaysProtectedPath: /api/db-backups is always protected (GHSA-mghq-58h3
assert.equal(isAlwaysProtectedPath("/api/db-backups/import"), true);
});
test("isAlwaysProtectedPath: legacy settings export/import-json are always protected (GHSA-v7g9-7f55-5g46)", () => {
// The mghq fix covered /api/db-backups but left the legacy sibling routes out:
// export-json dumps every credential and import-json irreversibly replaces
// settings/connections. Both handlers only check isAuthRequired(), which
// returns false under requireLogin=false — so they must sit in Tier 2 like
// /api/settings/database and /api/db-backups.
assert.equal(isAlwaysProtectedPath("/api/settings/export-json"), true);
assert.equal(isAlwaysProtectedPath("/api/settings/import-json"), true);
// The matcher is a plain startsWith (fail-closed: covers more, never less),
// so a hypothetical export-json2 sibling would also be protected — fine.
assert.equal(isAlwaysProtectedPath("/api/settings/proxy"), false);
});
test("isAlwaysProtectedPath: ordinary settings routes are not always protected", () => {
assert.equal(isAlwaysProtectedPath("/api/settings"), false);
assert.equal(isAlwaysProtectedPath("/api/settings/proxy"), false);

View File

@@ -82,11 +82,13 @@ test("SPAWN_CAPABLE_PREFIXES is defined in the server-free constants leaf with t
"/api/headroom/stop",
"/api/vnc-session",
"/api/modality-bridge/video/",
"/api/settings/mitm",
"/api/cli-tools/antigravity-mitm",
]) {
assert.ok(
SPAWN_CAPABLE_PREFIXES.includes(prefix),
`SPAWN_CAPABLE_PREFIXES lost the spawn-capable prefix "${prefix}" during extraction`
);
}
assert.equal(SPAWN_CAPABLE_PREFIXES.length, 12);
assert.equal(SPAWN_CAPABLE_PREFIXES.length, 14);
});

View File

@@ -61,6 +61,11 @@ function hasImporter(mod: string, roots: string[]): boolean {
new RegExp(`(?:import|require)\\s*\\(\\s*['""][^'"]+/db/${escaped}['"]`),
// dynamic template: import(`…/db/<mod>.ts`) — bin/cli/runtime.mjs uses template literals
new RegExp(`import\\s*\\(\`[^'"\`]+/db/${escaped}\\.ts\`\\)`),
// dynamic via file:// URL helper: import(projectFileUrl("…/db/<mod>.ts")) —
// bin/cli/runtime.mjs since #11238 (Windows-safe file:// dynamic imports).
new RegExp(
`import\\s*\\(\\s*projectFileUrl\\(\\s*['""][^'"]+/db/${escaped}\\.ts['"]\\s*\\)\\s*\\)`
),
// relative import within db/: from "./<mod>" or from "./<mod>"
new RegExp(`from\\s+['"]\\.\\.?/${escaped}['"]`),
];

View File

@@ -41,8 +41,8 @@ test("CLI_TOOLS total code entries (including none) equals 26 (21 visible + 5 no
assert.equal(codeAll.length, 26, `Expected 26 total code entries, got ${codeAll.length}`);
});
test("CLI_TOOLS total (code + agent) = 34", () => {
assert.equal(all.length, 34, `Expected 34 total entries, got ${all.length}`);
test("CLI_TOOLS total (code + agent) = 35", () => {
assert.equal(all.length, 35, `Expected 35 total entries, got ${all.length}`);
});
test("All code-none entries have configType mitm OR are legacy excluded entries", () => {
@@ -99,7 +99,7 @@ test("The 21 visible code entries include Qwen Code's rebuilt integration", () =
}
});
test("The 8 agent entries match D15 list exactly (+ omp + letta, #6318)", () => {
test("The 9 agent entries match D15 list exactly (+ omp + letta #6318, + prime-agent #11166)", () => {
const d15Agents = new Set([
"hermes-agent",
"openclaw",
@@ -109,6 +109,7 @@ test("The 8 agent entries match D15 list exactly (+ omp + letta, #6318)", () =>
"agent-deck",
"omp",
"letta",
"prime-agent",
]);
const agentIds = new Set(agentAll.map((t) => t.id));
for (const id of d15Agents) {

View File

@@ -1,5 +1,5 @@
import test from "node:test";
import { makeMcpResp, makeMcpStreamFetch } from "./helpers/mcpStreamMock.ts";
import { makeMcpStreamFetch } from "./helpers/mcpStreamMock.ts";
import assert from "node:assert/strict";
function makeResp(data: unknown, status = 200) {
@@ -16,25 +16,6 @@ function makeResp(data: unknown, status = 200) {
return obj;
}
async function captureStdout(fn: () => Promise<void>): Promise<string> {
const chunks: string[] = [];
const orig = process.stdout.write.bind(process.stdout);
process.stdout.write = (c: string | Uint8Array) => {
if (typeof c === "string") chunks.push(c);
return true;
};
try {
await fn();
} finally {
process.stdout.write = orig;
}
return chunks.join("");
}
function makeCmd(output = "json") {
return { optsWithGlobals: () => ({ output, quiet: output !== "table" }) };
}
test("resilience status busca /api/resilience", async () => {
let capturedUrl = "";
const origFetch = globalThis.fetch;

View File

@@ -1,6 +1,6 @@
import test from "node:test";
import assert from "node:assert/strict";
import { resolveServerHost } from "../../bin/cli/utils/serverHost.mjs";
import { resolveServerHost, resolveExposureWarning } from "../../bin/cli/utils/serverHost.mjs";
test("serve hostname: Linux honors OMNIROUTE_SERVER_HOST when HOSTNAME is set", () => {
assert.equal(
@@ -55,3 +55,26 @@ test("serve hostname: Windows preserves an explicit legacy HOSTNAME", () => {
test("serve hostname: Windows ignores an auto-set HOSTNAME matching the machine", () => {
assert.equal(resolveServerHost({ HOSTNAME: "windows-pc" }, "win32", "windows-pc"), "0.0.0.0");
});
test("exposure warning: fires when bound to all interfaces with no API-key requirement (GHSA-wmgv-ph3p-rv57)", () => {
const warning = resolveExposureWarning({}, "0.0.0.0");
assert.ok(warning, "a warning must be returned for the shipped default posture");
assert.match(warning, /REQUIRE_API_KEY/);
assert.match(warning, /OMNIROUTE_SERVER_HOST/);
});
test("exposure warning: silent when REQUIRE_API_KEY is enabled", () => {
assert.equal(resolveExposureWarning({ REQUIRE_API_KEY: "true" }, "0.0.0.0"), null);
assert.equal(resolveExposureWarning({ REQUIRE_API_KEY: "1" }, "0.0.0.0"), null);
});
test("exposure warning: silent on loopback binds", () => {
assert.equal(resolveExposureWarning({}, "127.0.0.1"), null);
assert.equal(resolveExposureWarning({}, "localhost"), null);
assert.equal(resolveExposureWarning({}, "::1"), null);
});
test("exposure warning: fires for a LAN bind too (any non-loopback interface)", () => {
assert.ok(resolveExposureWarning({}, "192.168.0.17"));
assert.ok(resolveExposureWarning({}, "::"));
});

View File

@@ -74,6 +74,9 @@ describe("omniroute setup opencode", () => {
// Commander turns `--base-url` into `baseUrl` — the runner must accept it.
baseUrl: "http://10.0.0.5:20128",
nonInteractive: true,
// These tests exercise the plugin install/merge path, not the container
// guard (#10057) — keep them hermetic on container devboxes/CI.
allowContainerWrite: true,
});
assert.equal(r.exitCode, 0);
@@ -99,6 +102,7 @@ describe("omniroute setup opencode", () => {
configDir: CONFIG_DIR,
baseUrl: "http://10.0.0.9:20128",
nonInteractive: true,
allowContainerWrite: true,
});
assert.equal(r.exitCode, 0);
@@ -127,7 +131,11 @@ describe("omniroute setup opencode", () => {
})
);
const r = await runSetupOpenCodeCommand({ configDir: CONFIG_DIR, nonInteractive: true });
const r = await runSetupOpenCodeCommand({
configDir: CONFIG_DIR,
nonInteractive: true,
allowContainerWrite: true,
});
assert.equal(r.exitCode, 0);
const cfg = readConfig();
@@ -140,7 +148,11 @@ describe("omniroute setup opencode", () => {
it("fails with a clear error (exit 1) when the bundled plugin dist is missing", async () => {
fs.rmSync(path.join(FAKE_PLUGIN_DIR, "dist"), { recursive: true, force: true });
try {
const r = await runSetupOpenCodeCommand({ configDir: CONFIG_DIR, nonInteractive: true });
const r = await runSetupOpenCodeCommand({
configDir: CONFIG_DIR,
nonInteractive: true,
allowContainerWrite: true,
});
assert.equal(r.exitCode, 1);
} finally {
makeFakePluginDist();

View File

@@ -1,5 +1,5 @@
import test from "node:test";
import { makeMcpResp, makeMcpStreamFetch } from "./helpers/mcpStreamMock.ts";
import { makeMcpStreamFetch } from "./helpers/mcpStreamMock.ts";
import assert from "node:assert/strict";
import {
SkillEnableSchema,

View File

@@ -15,6 +15,7 @@ const originalFetch = globalThis.fetch;
const originalJwtSecret = process.env.JWT_SECRET;
const originalApiKeySecret = process.env.API_KEY_SECRET;
const originalXdg = process.env.XDG_CONFIG_HOME;
const originalAllowContainerWrite = process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE;
const testRoots = new Set<string>();
async function createAuthCookie(): Promise<string> {
@@ -45,6 +46,9 @@ async function postApply(): Promise<Response> {
}
test.beforeEach(async () => {
// This suite exercises apply/merge, not the container guard (#10057). Restore the
// override before every case because afterEach deliberately restores process.env.
process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE = "1";
const root = await fs.mkdtemp(path.join(os.tmpdir(), "omniroute-apply-jsonc-"));
testRoots.add(root);
process.env.XDG_CONFIG_HOME = root;
@@ -72,6 +76,9 @@ test.afterEach(async () => {
else process.env.API_KEY_SECRET = originalApiKeySecret;
if (originalXdg === undefined) delete process.env.XDG_CONFIG_HOME;
else process.env.XDG_CONFIG_HOME = originalXdg;
if (originalAllowContainerWrite === undefined)
delete process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE;
else process.env.OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE = originalAllowContainerWrite;
for (const root of testRoots) await fs.rm(root, { recursive: true, force: true });
testRoots.clear();
});

View File

@@ -11,6 +11,7 @@ test("CLI_TOOLS registry contains all expected tools including rebuilt Qwen Code
// (CodeWhale is the actively-maintained successor to DeepSeek TUI).
// omp + letta added by #6318 (agent-category CLI integrations).
// grok-build added — xAI Grok Build TUI coding agent (ported from upstream decolua/9router#2571).
// prime-agent added by #11166 (PrimeIntellect-ai/prime-agent, agent category).
const expected = [
"claude",
"codex",
@@ -46,6 +47,7 @@ test("CLI_TOOLS registry contains all expected tools including rebuilt Qwen Code
"grok-build",
"qwen",
"zcode",
"prime-agent",
];
for (const id of expected) {
assert.ok(id in CLI_TOOLS, `Missing tool: ${id}`);

View File

@@ -106,7 +106,9 @@ test("CLI fingerprint preserves Codex executor User-Agent and maps legacy Copilo
{ model: "gpt-4o", messages: [] }
);
assert.equal(copilot.headers["User-Agent"], "GitHubCopilotChat/0.54.0");
// #10952 bumped GITHUB_COPILOT_CLI_VERSION 0.54.0 -> 1.0.81-6; the fingerprint
// pin tracks the advertised upstream CLI version.
assert.equal(copilot.headers["User-Agent"], "GitHubCopilotChat/1.0.81-6");
});
test("CLI fingerprint keeps legacy Copilot settings functional without exposing duplicate UI toggles", () => {

View File

@@ -42,6 +42,9 @@ test("setup-qwen writes current V4 settings and only its dedicated env key", asy
configPath: settingsPath,
envPath,
yes: true,
// These tests exercise the merge/write logic, not the container guard
// (#10057) — keep them hermetic on container devboxes/CI.
allowContainerWrite: true,
});
assert.equal(code, 0);
@@ -76,6 +79,8 @@ test("setup-qwen does not overwrite an invalid settings file", async () => {
model: "model-id",
configPath: settingsPath,
yes: true,
// See above — hermetic regardless of container detection (#10057).
allowContainerWrite: true,
});
assert.equal(code, 1);
assert.equal(await fs.readFile(settingsPath, "utf8"), "{ invalid JSON");

View File

@@ -497,7 +497,13 @@ test(
}
);
test("build phase uses an in-memory database without creating sqlite files", serial, async () => {
test("build phase returns the no-op stub without creating sqlite files", serial, async () => {
// Contract changed by #10060 (via #10952): the build phase no longer opens a
// real in-memory SQLite with migrations — loading the native better-sqlite3
// addon aborts the Next.js build worker on exit (node::
// RemoveEnvironmentCleanupHook). getDbInstance() now returns a no-op stub
// (pinned by tests/unit/build/10060-build-sqlite-stub.test.ts); queries are
// harmless no-ops and no file is touched.
const dataDir = makeTempDir("omniroute-db-build-");
try {
@@ -510,13 +516,15 @@ test("build phase uses an in-memory database without creating sqlite files", ser
const core = await importFresh("src/lib/db/core.ts");
const db = core.getDbInstance();
assert.ok(
assert.notEqual(db.driver, "better-sqlite3");
assert.equal(
db
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?")
.get("provider_connections")
.get("provider_connections"),
undefined,
"the build stub must answer queries with no-ops, never a real table scan"
);
assert.equal(fs.existsSync(path.join(dataDir, "storage.sqlite")), false);
assert.equal(db.pragma("journal_mode", { simple: true }), "memory");
core.resetDbInstance();
}
@@ -526,35 +534,39 @@ test("build phase uses an in-memory database without creating sqlite files", ser
}
});
test("invalid DATA_DIR (a file where a dir is expected) surfaces as a startup failure", serial, async () => {
const sandboxDir = makeTempDir("omniroute-db-bad-path-");
const fileAsDir = path.join(sandboxDir, "not-a-directory");
fs.writeFileSync(fileAsDir, "blocked");
test(
"invalid DATA_DIR (a file where a dir is expected) surfaces as a startup failure",
serial,
async () => {
const sandboxDir = makeTempDir("omniroute-db-bad-path-");
const fileAsDir = path.join(sandboxDir, "not-a-directory");
fs.writeFileSync(fileAsDir, "blocked");
try {
// Since #4767, db/core.ts resolves a writable data dir at module load via
// resolveWritableDataDir() → mkdirSync(recursive). Pointing DATA_DIR at a
// regular file is a non-permission misconfiguration (EEXIST/ENOTDIR), which
// resolveWritableDataDir rethrows by design (only EACCES/EPERM fall back), so
// the failure now surfaces at import time, not lazily from getDbInstance().
let caught: unknown;
await withEnv({ DATA_DIR: fileAsDir }, () => importFresh("src/lib/db/core.ts")).then(
() => {
throw new Error("expected importing db/core with an invalid DATA_DIR to reject");
},
(err) => {
caught = err;
}
);
assert.ok(caught instanceof Error, "an invalid DATA_DIR must surface as a thrown Error");
assert.match(
String((caught as Error).message),
/unable to open database file|ENOTDIR|EEXIST|not a directory|file already exists/i
);
} finally {
removePath(sandboxDir);
try {
// Since #4767, db/core.ts resolves a writable data dir at module load via
// resolveWritableDataDir() → mkdirSync(recursive). Pointing DATA_DIR at a
// regular file is a non-permission misconfiguration (EEXIST/ENOTDIR), which
// resolveWritableDataDir rethrows by design (only EACCES/EPERM fall back), so
// the failure now surfaces at import time, not lazily from getDbInstance().
let caught: unknown;
await withEnv({ DATA_DIR: fileAsDir }, () => importFresh("src/lib/db/core.ts")).then(
() => {
throw new Error("expected importing db/core with an invalid DATA_DIR to reject");
},
(err) => {
caught = err;
}
);
assert.ok(caught instanceof Error, "an invalid DATA_DIR must surface as a thrown Error");
assert.match(
String((caught as Error).message),
/unable to open database file|ENOTDIR|EEXIST|not a directory|file already exists/i
);
} finally {
removePath(sandboxDir);
}
}
});
);
test(
"legacy empty schema databases are renamed before a fresh sqlite database is created",

View File

@@ -98,7 +98,11 @@ test("single-target Codex combo advertises a larger model context override", asy
assert.equal(response.status, 200);
assert.equal(direct?.context_length, contextWindow);
assert.equal(combo?.context_length, contextWindow);
assert.equal(combo?.max_input_tokens, 272000);
// #11179 raised the static codex catalog cap to maxInputTokens=872000 (the real
// usable window; the old 272000 was just the first pricing tier). The input cap
// can never exceed the total window, so with the 500K override it clamps to it:
// min(872000, 500000) = 500000.
assert.equal(combo?.max_input_tokens, 500000);
} finally {
contextOverrides.removeModelContextOverride("codex", modelId);
}

View File

@@ -181,10 +181,11 @@ test("provider models route merges live Codex models with the local catalog then
// merge conservatively — the smaller of live vs. pinned wins, never the
// larger, so a stale/inflated live number can never make OmniRoute promise
// more context than the account can actually serve (#7012). Here the pinned
// GPT-5.6 Codex contract (272000/128000, see GPT_5_6_CODEX_CAPABILITIES)
// GPT-5.6 Codex contract (872000/128000, see GPT_5_6_CODEX_CAPABILITIES — raised
// from the old 272K pricing tier to the real usable window by #11179)
// is smaller than the live payload's 999999/999999, so the pinned value wins.
assert.equal(liveModel?.name, "GPT 5.6 Sol Live");
assert.equal(liveModel?.inputTokenLimit, 272000);
assert.equal(liveModel?.inputTokenLimit, 872000);
assert.equal(liveModel?.outputTokenLimit, 128000);
assert.equal(liveModel?.apiFormat, "responses");
assert.deepEqual(liveModel?.supportedEndpoints, ["responses"]);

View File

@@ -0,0 +1,168 @@
/**
* SSRF guard coverage for /v1/search's shared base-url resolution (GHSA-j7j4-g9qc-q69c).
*
* `provider_options.baseUrl` is client-controlled and flows through
* `resolveSearchBaseUrl()` into every search builder's server-side fetch target
* (searxng, ollama, …). Persisted `providerSpecificData.baseUrl`, by contrast,
* is operator configuration and must keep supporting self-hosted LAN instances.
*
* The request override therefore uses `public-only`, with DNS pinning at the
* fetch seam. Persisted configuration uses `block-metadata`: private hosts keep
* working while cloud-metadata endpoints remain unconditionally forbidden.
*
* Run with:
* node --import tsx/esm --test tests/unit/search-baseurl-ssrf-guard.test.ts
*/
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { resolveSearchBaseUrl } from "../../open-sse/handlers/search.ts";
import type { SearchProviderConfig } from "../../open-sse/config/searchRegistry.ts";
import { fetchClientControlledSearchUrl } from "../../open-sse/handlers/search/searchProxy.ts";
const config: SearchProviderConfig = {
id: "searxng-search",
name: "SearXNG",
baseUrl: "http://127.0.0.1:8888",
method: "GET",
authType: "none",
costPerQuery: 0,
} as SearchProviderConfig;
const base = {
query: "test",
searchType: "web",
maxResults: 5,
};
const METADATA_URLS = [
"http://169.254.169.254/latest/meta-data/iam/security-credentials/",
"http://169.254.169.254/latest/meta-data/?x=/search", // reporter's suffix-bypass shape
"http://metadata.google.internal/computeMetadata/v1/",
];
describe("resolveSearchBaseUrl — SSRF guard on client-controlled baseUrl (GHSA-j7j4)", () => {
for (const malicious of METADATA_URLS) {
it(`rejects providerOptions.baseUrl pointing at cloud metadata (${malicious})`, () => {
assert.throws(() => {
resolveSearchBaseUrl(config, { ...base, providerOptions: { baseUrl: malicious } });
});
});
it(`rejects providerSpecificData.baseUrl pointing at cloud metadata (${malicious})`, () => {
assert.throws(() => {
resolveSearchBaseUrl(config, { ...base, providerSpecificData: { baseUrl: malicious } });
});
});
}
it("rejects client overrides targeting loopback or LAN addresses", () => {
assert.throws(() =>
resolveSearchBaseUrl(config, {
...base,
providerOptions: { baseUrl: "http://127.0.0.1:9999" },
})
);
assert.throws(() =>
resolveSearchBaseUrl(config, {
...base,
providerOptions: { baseUrl: "http://10.0.0.5:8080" },
})
);
});
it("still allows loopback and LAN addresses from persisted provider configuration", () => {
assert.equal(
resolveSearchBaseUrl(config, {
...base,
providerSpecificData: { baseUrl: "http://127.0.0.1:9999" },
}),
"http://127.0.0.1:9999"
);
assert.equal(
resolveSearchBaseUrl(config, {
...base,
providerSpecificData: { baseUrl: "http://10.0.0.5:8080" },
}),
"http://10.0.0.5:8080"
);
});
it("leaves the catalog baseUrl untouched when no override is supplied", () => {
assert.equal(resolveSearchBaseUrl(config, base), "http://127.0.0.1:8888");
});
});
describe("fetchClientControlledSearchUrl — request-time SSRF guard", () => {
it("rejects a public hostname whose DNS answer is private before connecting", async () => {
let fetchCreated = false;
await assert.rejects(
() =>
fetchClientControlledSearchUrl("https://search.example.test/query", {}, undefined, {
lookup: async () => [{ address: "169.254.169.254", family: 4 }],
createPinnedFetch: () => {
fetchCreated = true;
return async () => new Response("unexpected");
},
}),
/private|metadata|DNS rebinding/i
);
assert.equal(fetchCreated, false);
});
it("pins the connection to the public DNS answer that passed validation", async () => {
let pinnedAddress = "";
let pinnedFamily = 0;
const response = await fetchClientControlledSearchUrl(
"https://search.example.test/query",
{ method: "POST", body: "{}" },
undefined,
{
lookup: async () => [{ address: "203.0.113.42", family: 4 }],
createPinnedFetch: (address, family) => {
pinnedAddress = address;
pinnedFamily = family;
return async (_input, init) => {
assert.equal(init?.redirect, "manual");
return new Response("{}", {
status: 200,
headers: { "content-type": "application/json" },
});
};
},
}
);
assert.equal(response.status, 200);
assert.equal(pinnedAddress, "203.0.113.42");
assert.equal(pinnedFamily, 4);
});
it("blocks redirects instead of letting fetch follow a public URL into metadata", async () => {
let calls = 0;
await assert.rejects(
() =>
fetchClientControlledSearchUrl("https://search.example.test/query", {}, undefined, {
lookup: async () => [{ address: "203.0.113.42", family: 4 }],
createPinnedFetch: () => async (_input, init) => {
calls += 1;
assert.equal(init?.redirect, "manual");
return new Response(null, {
status: 302,
headers: {
location: "http://169.254.169.254/latest/meta-data/iam/security-credentials/",
},
});
},
}),
/redirect blocked/i
);
assert.equal(calls, 1, "the redirect target must never be requested");
});
});

View File

@@ -115,7 +115,7 @@ test("v1 search POST uses stored Linkup credentials and returns normalized resul
);
const body = (await response.json()) as any;
assert.equal(response.status, 200);
assert.equal(response.status, 200, JSON.stringify(body));
assert.equal(capturedUrl, "https://api.linkup.so/v1/search");
assert.equal(
(capturedInit?.headers as Record<string, string>).Authorization,
@@ -267,25 +267,13 @@ test("v1 search POST uses stored You.com credentials and returns unified news re
}
});
test("v1 search POST accepts authless SearXNG with provider_options baseUrl", async () => {
test("v1 search POST rejects a client-controlled private SearXNG baseUrl", async () => {
const originalFetch = globalThis.fetch;
let capturedUrl = "";
let fetchCalled = false;
globalThis.fetch = async (url) => {
capturedUrl = String(url);
return new Response(
JSON.stringify({
results: [
{
title: "SearXNG result",
url: "https://searx.example/result",
content: "Self-hosted response",
engines: ["duckduckgo"],
},
],
}),
{ status: 200, headers: { "content-type": "application/json" } }
);
globalThis.fetch = async () => {
fetchCalled = true;
return new Response("unexpected");
};
try {
@@ -303,16 +291,14 @@ test("v1 search POST accepts authless SearXNG with provider_options baseUrl", as
}),
})
);
const body = (await response.json()) as any;
const body = (await response.json()) as { error?: { message?: string } | string };
assert.equal(response.status, 200);
assert.equal(
capturedUrl,
"http://127.0.0.1:9090/custom-search/search?q=self+hosted+meta+search&format=json&categories=news"
assert.equal(response.status, 400);
assert.equal(fetchCalled, false);
assert.match(
String(typeof body.error === "string" ? body.error : body.error?.message),
/blocked/i
);
assert.equal(body.provider, "searxng-search");
assert.equal(body.results[0].title, "SearXNG result");
assert.equal(body.results[0].citation.provider, "searxng-search");
} finally {
globalThis.fetch = originalFetch;
}
@@ -420,25 +406,24 @@ test("v1 search POST preserves stored SearXNG baseUrl for authless providers", a
}
});
test("v1 search POST returns 400 when auto-select finds no configured provider (searxng-search is now fallbackOnly)", async () => {
test("v1 search POST falls back to duckduckgo-free when no provider is configured (#11097)", async () => {
// Contract changed by PR #11097 ("fix(search): fall back to duckduckgo-free when
// no search provider is configured"): zero-credential /v1/search no longer returns
// 400 — it promotes the fallback-only duckduckgo-free provider so out-of-the-box
// search works. This test pins the NEW contract.
const originalFetch = globalThis.fetch;
let capturedUrl = "";
// DuckDuckGo lite HTML shape: result link + snippet cell (see
// open-sse/services/freeWebSearch.ts parseDuckDuckGoLite).
const liteHtml = `<html><body>
<a href="https://example.com/auto-result" class='result-link'>Auto-selected DuckDuckGo result</a>
<td class='result-snippet'>Fallback free search snippet</td>
</body></html>`;
globalThis.fetch = async (url) => {
capturedUrl = String(url);
return new Response(
JSON.stringify({
results: [
{
title: "Auto-selected SearXNG result",
url: "https://searx.example/auto",
content: "Auto-selected self-hosted response",
engines: ["duckduckgo"],
},
],
}),
{ status: 200, headers: { "content-type": "application/json" } }
);
return new Response(liteHtml, { status: 200, headers: { "content-type": "text/html" } });
};
try {
@@ -454,14 +439,15 @@ test("v1 search POST returns 400 when auto-select finds no configured provider (
);
const body = (await response.json()) as any;
assert.equal(response.status, 400);
assert.equal(capturedUrl, "", "fallback-only SearXNG must not receive an upstream request");
assert.ok(body.error?.message || body.error);
assert.match(
String(body.error?.message ?? body.error),
/provider|configured/i,
"the response must explain that no provider was selected"
assert.equal(response.status, 200);
assert.equal(
capturedUrl,
"https://lite.duckduckgo.com/lite/",
"the fallback must call the DuckDuckGo lite endpoint"
);
assert.equal(body.provider, "duckduckgo-free");
assert.equal(body.results[0].title, "Auto-selected DuckDuckGo result");
assert.equal(body.results[0].url, "https://example.com/auto-result");
} finally {
globalThis.fetch = originalFetch;
}

View File

@@ -0,0 +1,107 @@
// @vitest-environment jsdom
import React, { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import FirstRunReadinessCard from "@/app/(dashboard)/dashboard/FirstRunReadinessCard";
import CommandPalette from "@/shared/components/CommandPalette";
vi.mock("next-intl", () => ({
useTranslations: () => {
const translate = (key: string) => key;
translate.has = () => true;
return translate;
},
}));
vi.mock("next/link", () => ({
default: ({ children, href, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement>) => (
<a href={href} {...props}>
{children}
</a>
),
}));
vi.mock("next/navigation", () => ({
useRouter: () => ({ push: vi.fn() }),
}));
const DISMISS_STORAGE_KEY = "omniroute-first-run-readiness-dismissed";
if (typeof Element.prototype.scrollIntoView === "undefined") {
Object.defineProperty(Element.prototype, "scrollIntoView", {
configurable: true,
value: () => {},
});
}
function jsonResponse(body: unknown): Response {
return { json: async () => body } as Response;
}
describe("first-run readiness and command palette hook state", () => {
let container: HTMLDivElement;
let root: Root;
beforeEach(() => {
(
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
).IS_REACT_ACT_ENVIRONMENT = true;
localStorage.clear();
vi.stubGlobal(
"fetch",
vi.fn(async () => jsonResponse({}))
);
container = document.createElement("div");
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
localStorage.clear();
vi.unstubAllGlobals();
});
it("synchronizes first-run dismissal written by another browser context", async () => {
await act(async () => {
root.render(<FirstRunReadinessCard setupComplete={false} />);
});
expect(container.querySelector('[role="region"]')).not.toBeNull();
localStorage.setItem(DISMISS_STORAGE_KEY, "true");
await act(async () => {
window.dispatchEvent(
new StorageEvent("storage", {
key: DISMISS_STORAGE_KEY,
newValue: "true",
storageArea: localStorage,
})
);
});
expect(container.querySelector('[role="region"]')).toBeNull();
});
it("keeps hidden essentials tools searchable after settings load", async () => {
vi.stubGlobal(
"fetch",
vi.fn(async () =>
jsonResponse({
hiddenSidebarItems: ["playground"],
sidebarActivePreset: "essentials",
})
)
);
await act(async () => {
root.render(<CommandPalette isOpen onClose={vi.fn()} />);
});
const labels = Array.from(container.querySelectorAll('[role="option"] p')).map(
(label) => label.textContent
);
expect(labels).toContain("playground");
});
});

View File

@@ -72,10 +72,12 @@ test("usage service covers GitHub free-plan parsing, auth denial and unsupported
assert.equal(freeUsage.quotas.completions.used, 0);
assert.equal(freeUsage.quotas.completions.remainingPercentage, 100);
assert.equal(calls[0].headers.Authorization, "token gho-free");
assert.equal(calls[0].headers["User-Agent"], "GitHubCopilotChat/0.54.0");
assert.equal(calls[0].headers["Editor-Version"], "vscode/1.126.0");
assert.equal(calls[0].headers["Editor-Plugin-Version"], "copilot-chat/0.54.0");
assert.equal(calls[0].headers["X-GitHub-Api-Version"], "2026-06-01");
// #10952 re-based the Copilot wire identity on the live-captured CLI 1.0.81-6
// (copilot-developer-cli integration id; API version 2026-08-01).
assert.equal(calls[0].headers["User-Agent"], "GitHubCopilotChat/1.0.81-6");
assert.equal(calls[0].headers["Editor-Version"], "copilot/1.0.81-6");
assert.equal(calls[0].headers["Editor-Plugin-Version"], "copilot-chat/1.0.81-6");
assert.equal(calls[0].headers["X-GitHub-Api-Version"], "2026-08-01");
globalThis.fetch = async () => new Response("forbidden", { status: 403 });
const forbidden: any = await usageService.getUsageForProvider({

View File

@@ -128,9 +128,11 @@ test("vscode raw models route exposes native GPT-5.6 IDs and effort tiers", asyn
assert.equal(typeof defaultModel.created, "number");
assert.equal(defaultModel.owned_by, "codex");
assert.equal(defaultModel.name, "Codex GPT 5.6 Sol");
assert.equal(defaultModel.context_length, 272000);
// #11179: codex static catalog advertises the usable 872K window (max_context_window),
// not the old 272K pricing tier.
assert.equal(defaultModel.context_length, 872000);
assert.equal(defaultModel.max_output_tokens, 128000);
assert.equal(defaultModel.max_input_tokens, 272000);
assert.equal(defaultModel.max_input_tokens, 872000);
assert.deepEqual(defaultModel.capabilities, {
vision: true,
tool_calling: true,

View File

@@ -255,7 +255,9 @@ test("vscode combos route resolves combo names through Ollama api/show", async (
assert.equal(body.model, "show-combo");
assert.equal(body.modelfile, "FROM show-combo");
assert.equal(body.details.family, "show-combo");
assert.equal(body.model_info.context_length, 272000);
// #11179: codex static catalog advertises the usable 872K window (max_context_window),
// not the old 272K pricing tier.
assert.equal(body.model_info.context_length, 872000);
assert.deepEqual(body.supportsReasoningEffort, ["none", "low", "medium", "high", "xhigh"]);
assert.equal(body.model_info.capabilities.reasoning, true);
});
@@ -290,7 +292,8 @@ test("vscode tokenized combos root route exposes importable combo metadata", asy
assert.equal(response.status, 200);
assert.ok(combo, "expected balanced-load in combo root response");
assert.equal(combo.url.includes("/responses#models.ai.azure.com"), true);
assert.equal(combo.maxInputTokens, 272000);
// #11179: codex static catalog maxInputTokens is now the usable 872K window.
assert.equal(combo.maxInputTokens, 872000);
assert.equal(combo.toolCalling, true);
assert.deepEqual(combo.supportsReasoningEffort, ["none", "low", "medium", "high", "xhigh"]);
});
@@ -1073,7 +1076,9 @@ test("vscode tokenized api/show route exposes explicit reasoning effort metadata
assert.equal(body.configurationSchema?.properties?.reasoningEffort?.default, "low");
assert.equal(body.model_info["general.basename"], "Codex GPT 5.6 Sol (Default)");
assert.equal(body.model_info["general.architecture"], "codex");
assert.equal(body.model_info["codex.context_length"], 272000);
// #11179: codex static catalog advertises the usable 872K window (max_context_window),
// not the old 272K pricing tier.
assert.equal(body.model_info["codex.context_length"], 872000);
assert.deepEqual(body.model_info.supports_reasoning_effort, [
"low",
"medium",