Skip to content

feat(dashboard): orient users before API key management - #11195

Merged
diegosouzapw merged 32 commits into
diegosouzapw:release/v3.8.50from
ignamiranda:feat/beginner-ux-api-keys-header
Aug 23, 2026
Merged

feat(dashboard): orient users before API key management#11195
diegosouzapw merged 32 commits into
diegosouzapw:release/v3.8.50from
ignamiranda:feat/beginner-ux-api-keys-header

Conversation

@ignamiranda

@ignamiranda ignamiranda commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a purpose-first heading to the API key management page using existing localized copy
  • show the request path from an app through an API key to OmniRoute
  • keep the existing key-management controls and behavior unchanged

Why

The page currently opens directly on filters and the registered-keys list. The new orientation layer explains what API keys do before users manage them.

Part of #11167.

Validation

  • node --import tsx/esm --test tests/unit/api-manager-page-static.test.ts
  • npm run lint — 0 errors; 6 pre-existing warnings
  • npm run typecheck:core

Scope

Two files: the existing page client and its static regression test. No API, database, routing, or key-management behavior changes.

⚠️ base-red inherited: #9985

diegosouzapw and others added 8 commits August 22, 2026 22:39
…-usage json (diegosouzapw#11192)

* feat(api): structured ?format=json for the self-service usage endpoint

GET /api/usage/om-usage already let any key read its own usage — personal
daily/weekly USD limits and the provider quota snapshot — but only as
text/plain, which a UI cannot parse safely. OmniCopilot issue diegosouzapw#8 asks exactly
for this surface.

Adds ?format=json, returning the ApiKeyUsageLimitStatus + UsageSnapshot the
text is rendered from. Text and JSON share the same collectors
(collectUsageSnapshots, getApiKeyUsageLimitStatus), so the two can never
disagree about a number. The response is a discriminated union: a key without
allowUsageCommand (403) or an invalid key (401) returns
{ allowed:false, error:{message} }, distinct from allowed:true with empty
sections — the state a panel must render as "nothing learned yet", not a
refusal. Text form unchanged; without ?format the contract is untouched.

The endpoint was previously missing from API_REFERENCE.md; it now has a
section documenting both forms, the allowUsageCommand gate, and the
self-service auth model (caller's own key, not requireManagementAuth).

Regression guards in tests/unit/usage-command-json-format.test.ts (4 tests:
json shape, text default preserved, structured 403, sanitized 401 with no
stack trace). Existing internal-usage-command suite still 12/12.

* chore(changelog): correct the fragment to the real PR number (diegosouzapw#11190)

* feat(api): return every connection's snapshot under providers[] in om-usage json

Closes diegosouzapw#11191. buildUsageCommandJson picked a single snapshot via selectUsageSnapshot, so a panel could only ever show one provider. The collector already had them all — the single-pick is a presentation choice for a terminal. The JSON form now also returns the full UsageSnapshot[] alongside the selected provider, so a UI can render Codex / Claude / OpenCode side by side. The text form is untouched.

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
… links through the shortener (diegosouzapw#11196)

- New CheaperInferenceSponsorBanner on the dashboard home, same size/shape as
  KimiSponsorBanner, no version gate (durable partnership). Uses the
  cheaperinference ProviderIcon and the brand green (#31f889) with the dark
  ink CTA (contrast, per colors.ts token).
- CTA points at https://link.omniroute.online/cheaper — the branded short
  link — so clicks land in our Kutt metrics.
- VscodeCopilotBanner CTA now points at https://link.omniroute.online/vsx
  instead of the raw Marketplace URL, for the same reason.
- i18n strings in en + pt (en is the namespace-level fallback for the other
  41 locales).
- Tests: new cheaperInferenceSponsorBanner.test.tsx (render, CTA href, dismiss
  persistence); vscodeCopilotBanner.test.tsx updated to the new CTA URL.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
… response quality validation (diegosouzapw#11036)

SSE comment lines (OpenRouter keep-alives) and leading whitespace no longer fail the combo quality gate's JSON fallback. First contribution — clean minimal fix with test. Thank you @asorourx, welcome aboard!
…#11041)

Compaction-V2 output now counts as real model output (no synthetic response.failed after response.completed), the Codex SSE filter handles CRLF framing, and terminal detection runs before scan-state bounding. 88/88 stream/readiness suites on the board. Thank you @jackjinke!
Validated on the combined batch board + this branch alone: chat-body-admission + authz/pipeline 65/65, file-size gate green with a dated frozen entry (chatBodyAdmission 1005→1009 — the +4 lease/drain wiring lines, owner-authorized rebaseline). trackRequest was never called, so SIGTERM waitForDrain saw zero in-flight and killed live SSE; leases now hold the drain counter for the stream's lifetime, and the 503 carries Retry-After. Closes diegosouzapw#11015. Thank you @RaviTharuma!
… retrieve tool (diegosouzapw#11084)

Validated on the combined batch board + this branch: ccr-non-mcp-full-prompt-loss + ccr-retrieval-ramp 20/20, file-size gate green with the ccr/index listing (1024, dated annotation — owner-authorized). The callerSupportsCcrRetrieve gate now skips the whole engine for callers whose tools[] cannot reach omniroute_ccr_retrieve — no more 15KB prompt arriving upstream as 112 tokens. Production-measured root cause, textbook TDD. Thank you @HouMinXi!
Merged after conflict resolution in modelMetadataRegistry.ts: the tip's effortTiers chain (declared efforts → declared tiers → undefined-if-thinking-declared → codex extension) now carries this PR's GLM guard as the final-fallback override — GLM-family models without a provider-declared contract get the authoritative empty tier list instead of generic OpenAI tiers. GLM/ZCode suites 40/40 on the resolved branch. Closes diegosouzapw#10962. Thank you @xz-dev!
@ignamiranda

Copy link
Copy Markdown
Contributor Author

Addressed review findings in 2295d0948: localized all request-flow labels, added an accessible group label, made the flow responsive, and strengthened the regression test to assert translation usage. Verification: focused test (11/11), npm run lint, npm run typecheck:core.

jackjinke and others added 18 commits August 22, 2026 22:58
…iegosouzapw#10949, diegosouzapw#10959) (diegosouzapw#10961)

Validated on the combined batch board + this branch: 231/231 across chatcore-translation-paths, reasoning-cache, strip-reasoning-blobs, and both Responses translator suites. Pre-merge: propagated the diegosouzapw#11110/diegosouzapw#11129 summary:[] defaults into five assertions here (each commented with its PR) — without it this branch red against the tip, and as a bonus the merge drains the 4 reasoning reds that were live on the tip from those merges. Plaintext now wins over a coexisting opaque companion; opaque-only drops cleanly for plaintext targets; combos keep explicit Skip. Fixes diegosouzapw#10949 and diegosouzapw#10959. Thank you @jackjinke!
…egosouzapw#10644) (diegosouzapw#10987)

Merged after count reconciliation: the branch's regenerated docs claimed 57 free forever / 157 migrations from its older base; gate-verified values on the current tip are 56 free forever (Logfare carries a Free badge via gateways.ts freeNote but has no freeModelCatalog per-model entries, so the live-code counter stays at 56) and 159 migrations — the README/SVGs now match the check:docs-counts output exactly. provider-consistency OK at 267 registry / 349 canonical. logfare-registry 4/4, icon + KNOWN_PNGS + discovery-set membership all verified present. Closes diegosouzapw#10644. Thank you @jonlwheat2-gif!
…egosouzapw#10964)

Merged after conflict triage: the six base-red repair files (vi.json, opencode.ts JSDoc, context-manager test, the three webhook dispatcher tests, the uncloseai orphan-test rename) were already drained on the tip by today's diegosouzapw#11130/diegosouzapw#11157/diegosouzapw#11160/diegosouzapw#11113 — those hunks resolved to the tip shape. What lands is the production-fix set: GLM transport-aware Anthropic headers, Claude Code-compatible model-listing rejection, combo live-test single-probe, zero-cost Auto-Combo interval normalization, recovery-clearing union handling, LLMLingua real-path compare, macOS netstat PID discovery, AI Horde R2 strict public-host validation. Sweep of every touched test file: 243/243 green; typecheck + file-size clean. (guide-settings-route's 4 reds reproduce on the pure tip — pre-existing drift from diegosouzapw#11079, not from here.) Thank you @backryun!
…ocess-spawning endpoints (diegosouzapw#11189)

Validated on the combined batch board (gates + typecheck clean) and this branch: security-route-guard-tiers green. Regression coverage for the Hard Rule diegosouzapw#15/diegosouzapw#17 contract — Tier 1 process-spawning prefixes (/api/services/, /api/mcp/, /api/cli-tools/runtime/) must stay LOCAL_ONLY before any auth check. Conflict with the tip was only stale provider-count docs. Thank you @rqzbeh!
…ed labels (diegosouzapw#11188)

Validated on the combined batch board + this branch: dashboard-ux-operability green. Unmapped custom quota keys now render as title-cased labels instead of raw snake_case. Conflict with the tip was only stale provider-count docs. Thank you @rqzbeh!
…login (diegosouzapw#11143) (diegosouzapw#11175)

Validated on the combined batch board + this branch: login-11143 green. Full document navigation after login guarantees the auth_token cookie is committed before any RSC prefetch fires — no more 307 back to /login. Conflict with the tip was only stale provider-count docs. Fixes diegosouzapw#11143. Thank you @rqzbeh!
…fication (diegosouzapw#10443) (diegosouzapw#11177)

Validated on the combined batch board + this branch: antigravity-dynamic-session-id + proxy-fetch-dns-retry green; file-size gate green with the proxyFetch 1244 frozen entry (dated annotation for the +5 retry-classification lines, owner-authorized). Static per-account sessionId unpinning ends the concurrent-turn 429s and EmptyStreamError drops on the Hermes→Antigravity path; EAI_AGAIN/ENOTFOUND/ETIMEDOUT now classified retryable. Conflict with the tip was only stale provider-count docs. Resolves the remaining diegosouzapw#10443 root causes. Thank you @rqzbeh!
…ormance optimizations (A, B, C, D) (diegosouzapw#11182)

Validated on the combined batch board + this branch: perf-a-b-c-d + account-fallback-service 93/93, gates + typecheck clean. Owner approved the full bundle including item A (async proxy-log batching, 1s/100-item flush with an unref'd timer — reviewed the implementation: flush helper exists for shutdown wiring, buffered logs are the accepted tradeoff). B (lazy modals), C (O(1) alias maps), D (pre-compiled regex — this is also the entire content of diegosouzapw#11187, being closed as subsumed) ride along. Conflict with the tip was only stale provider-count docs. Thank you @rqzbeh!
…diegosouzapw#9763) (diegosouzapw#11086)

Validated on the combined batch board over tip c92bd40: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

Operator-configured positive minTime floor now survives the plenty-of-headroom relaxation (resolveMinTime instead of a hard 0). Fixes diegosouzapw#9763. Thank you @pacocartones!
…er (diegosouzapw#10071) (diegosouzapw#11185)

Validated on the combined batch board over tip c92bd40: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

Five g4f-* entries re-flagged hasFree:false with the live-probed 402 evidence (proof-of-work wall, member key still works); the two dissenting providers deliberately untouched, matching the chutes/aimlapi/yi precedent. Fixes diegosouzapw#10071. Thank you @pacocartones and @chirag127 for the capture!
…gle works (diegosouzapw#11193)

Validated on the combined batch board over tip c92bd40: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

lkgpEnabled finally reaches the RoutingContext literal — the Settings→Routing LKGP toggle was persisted but unreachable (context.lkgpEnabled always undefined). Scope discipline noted and appreciated: the applyStrategyOrdering dependency change stays out. Fixes diegosouzapw#11181. Thank you @pacocartones!
…* pool (diegosouzapw#11198)

Validated on the combined batch board over tip c92bd40: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

Keyless custom-compatible connections stay in auto/* pools — the credential filter now recognizes a registry-free keyless endpoint instead of dropping the connection before pool construction. Fixes diegosouzapw#11180. Thank you @pacocartones!
…gosouzapw#11199)

Validated on the combined batch board over tip c92bd40: static gates clean (changelog, file-size 158 frozen, complexity 2626<=2774, cognitive 1183<=1223, dead-code 409<=416), typecheck:core clean, 70 focused tests green (PR suites 49/49 + auth/combo neighbors 21/21).

opencode-go joins FLAT_RATE_SUBSCRIPTION_PROVIDER_IDS — cost analytics stop pricing a flat 0 subscription at metered aggregator rates (3.35 reported vs 0 actual). Same pattern as diegosouzapw#10774. Fixes diegosouzapw#11149. Thank you @pacocartones!
…iegosouzapw#11089) (diegosouzapw#11186)

Validated on the combined batch board + this branch: synced-inventory + auth neighbor suites 16/16; file-size gate green with the auth.ts 3337 frozen entry (dated annotation for the +77 inventory-filter lines at the credential-selection chokepoint, owner-authorized). Chat routing now pins to the connection whose synced inventory actually advertises the model — no more spurious model-not-found on multi-host self-hosted setups. Scoping call (not building on the still-open diegosouzapw#11088) was the right one. Fixes diegosouzapw#11089. Thank you @pacocartones and @yourspraveen for the precise report!
…egosouzapw#11040 (diegosouzapw#11147)

The diegosouzapw#11040 merge changed decidePreSpawn() to opt-in adoption
(GHSA-wg9p-6m2g-4v27: a 2xx on the probed port cannot prove the listener
is this service), but the two integration tests in ServiceSupervisor.test.ts
still asserted adopt-by-default, leaving the release tip red:

- diegosouzapw#6205: probeBeforeSpawn adopts a healthy existing instance (no spawn)
- adopted service resolves and records the real pid of the process holding the port

Both now set OMNIROUTE_ADOPT_EXISTING_SERVICE=1 (restored in finally) so the
adoption path they exercise stays covered under the new contract. Adds a new
default-deny case asserting that without the flag a healthy listener is NOT
adopted and the error names the opt-in escape hatch.

Verified against base tip 6cd4d38: file is 8/8 green,
ninerouter-embed-port-6205.test.ts still 9/9, eslint + prettier clean.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…osouzapw#11208)

The sponsor banner landed in en/pt without the vi copy, breaking the strict
Vietnamese parity gate (3 failing tests in i18n-vi-completeness: key parity,
ICU placeholder parity, ICU parse regression) — red on every release-branch CI
run since.

Adds the 5 missing vi translations (title, description, cta, partnerLinkNote,
dismissAriaLabel). The basereds-sse-vi worktree that owned this debt has been
idle for 4 days, so this drains it here.

Verified: i18n-vi-completeness 5/5, i18n:check-ui-coverage PASS (vi now
100.0%), i18n:check-value-drift PASS, prettier clean.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…iegosouzapw#11139)

Validated on the combined batch board over tip 17897cc: gates clean (changelog, file-size 159 frozen, complexity 2628<=2774, cognitive 1184<=1223, dead-code 409<=416, provider-consistency 267/350/0), typecheck:core clean, 83/83 PR suites + neighbors green (mcp-route-scope-carveout 15 tests with bug-injection proof, management-auth-hardening per-route call-shape pinning). The route layer now honors the diegosouzapw#9159 mcp:connect carve-out exactly like the policy layer — audit/audit-stats deliberately stay manage-only, oma_ tokens still require admin. Thank you @HouMinXi!
…leness (diegosouzapw#11141)

Validated on the combined batch board + this branch: oauth-400-recovery + quota-connection-recovery 22/22; file-size gate green with the test/route.ts 1215 frozen entry (dated annotation for the +190 rebuilt-probe lines, owner-authorized). Unknown expiry + refresh token now means proactive refresh before probing, a hard 400 gets exactly one refresh+retry with fresh-token assertion, and the recovery tick clears stale error labels — the four dead-for-weeks antigravity connections from the production report would have self-healed. TDD with bug-injection proof on each leg. Thank you @HouMinXi!
diegosouzapw#11140)

Validated on the combined batch board + this branch: context7-provider 33/33 + search-registry 45/45 (propagated to 17 providers), docs-counts green (350 everywhere: PROVIDER_REFERENCE regenerated, SVGs, README, AGENTS.md, package.json, llm.txt + 42 mirrors synced), provider-consistency OK. Hardening reviewed: canonical isValidContext7LibraryId shared by normalizer+executor, byte-capped error bodies, validated baseUrl with public fallback, anonymous-tier quota sentinel, excluded from auto-select walks. Thank you @HouMinXi — 15 forge-review cycles show!
ignamiranda and others added 3 commits August 23, 2026 06:35
…zapw#11204)

Validated on the combined batch board: gates clean (changelog, file-size 159 frozen, complexity 2620<=2774, cognitive 1180<=1223, dead-code 409<=416), typecheck:core clean, i18n suites 16/16 after the vi translation pass. Two-string reframe that stops Embedded Services reading as required infrastructure. Thank you @ignamiranda!
@diegosouzapw
diegosouzapw merged commit c1e9fbf into diegosouzapw:release/v3.8.50 Aug 23, 2026
4 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.