Skip to content

fix(auth): replace router.push with window.location navigation after login (#11143) - #11175

Merged
diegosouzapw merged 31 commits into
cheaper-inference:release/v3.8.50from
rqzbeh:fix/login-redirect-cookie-race-11143
Aug 23, 2026
Merged

diegosouzapw merged 31 commits into
cheaper-inference:release/v3.8.50from
rqzbeh:fix/login-redirect-cookie-race-11143

Conversation

@rqzbeh

@rqzbeh rqzbeh commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves #11143 where login succeeds but subsequent Next.js App Router RSC prefetching requests (/dashboard?_rsc=...) return HTTP 307 and redirect back to /login:

  1. Root Cause:
    Client-side navigation after login previously used router.push('/dashboard') (soft navigation). RSC prefetching initiated sub-requests before the browser attached the auth_token cookie set by /api/auth/login, causing the route guard to reject unauthenticated RSC requests.

  2. Fix:
    Updated src/app/login/page.tsx to use full document navigation (window.location.href = '/dashboard') after successful login and authenticated checks. This guarantees the browser commits the auth_token cookie before making requests to /dashboard.

Verification

  • node --import tsx/esm --test tests/unit/login-11143.test.ts (PASS)
  • npm run typecheck:core (0 errors)
  • npm run check:docs-all (PASS)

@rqzbeh
rqzbeh requested a review from diegosouzapw as a code owner August 22, 2026 22:50
rqzbeh and others added 27 commits August 22, 2026 20:07
…heaper-inference#11035) (cheaper-inference#11157)

Cherry-picked the JSDoc commit onto the current tip (authorship preserved), stripping the stale generated-count noise files. Focused: opencode-v2-config-11070 2/2. Comments now match the 128k fallback shipped in cheaper-inference#11035/cheaper-inference#11054. Thank you @rqzbeh!
…-web (cheaper-inference#11000) (cheaper-inference#11161)

Cherry-picked onto the current tip (authorship preserved), noise files stripped. Pre-merge addition: regenerated the golden snapshot with UPDATE_GOLDEN=1 because the branch's snapshot predated two legitimate tip changes — the dify bare-root from cheaper-inference#11065 and the hackclub removal from cheaper-inference#11123. The regen'd delta contains exactly those two (audited). This also drains a live base-red: provider-translate-path-golden was failing on the pure tip. 3/3 green. Thank you @rqzbeh!
…dal Enter handler (cheaper-inference#10995) (cheaper-inference#11156)

Cherry-picked onto the current tip (authorship preserved), generated-count noise stripped. Pre-merge: file-size baseline rebaselined 1080→1082 with dated annotation (the +2 lines are the Enter-handler isCheckDisabled mirror — owner-requested cheaper-inference#11056 polish; rest is Prettier reflow). Gate green; vitest add-api-key-modal-enter-key 2/2 (jsdom render test). Thank you @rqzbeh!
… oauth start (cheaper-inference#11164) (cheaper-inference#11173)

Cherry-picked onto the current tip (authorship preserved), noise stripped. Focused: oauth-device-flow-11164 green + 9474-claude-code-oauth-mismap neighbor suite green. Device-code endpoint is tried first, camelCase/snake_case fallbacks normalized, no more blank code / 'Visit: undefined'. Fixes cheaper-inference#11164. Thank you @rqzbeh!
… providers (cheaper-inference#11100) (cheaper-inference#11155)

Cherry-picked onto the current tip (authorship preserved), generated-count noise stripped. Two pre-merge adjustments: (1) dropped the unrelated localDb.ts re-export hunk (nothing in this PR uses those symbols); (2) automated security review flagged the blocked-provider list resolving once at server creation — the handler now rebuilds the schema per invocation via the resolver (advertised tools/list schema stays a creation-time snapshot, which is inherent to MCP). Vitest: new runtime-blocked-schema suite 3/3, full MCP __tests__ 118/118; contract suites (mcp-web-search-provider-enum-contract, search-blocked-providers-11100) 6/6; typecheck clean. This closes the residual gap noted when cheaper-inference#11120 was closed. Thank you @rqzbeh!
…antiation (cheaper-inference#11039) (cheaper-inference#11163)

Cherry-picked onto the current tip (authorship preserved), noise stripped. Validated on BOTH runtimes: bun test tests/unit/db-adapters/ 44/44 under the pinned Bun 1.3.14 (native bun:sqlite path), and node --test on the same suite 52 pass / 0 fail / 1 skip (Bun-only adapter skips under Node, as designed). Dockerfile.bun entrypoint now matches the standalone runner shape. Follow-up to cheaper-inference#11039. Thank you @rqzbeh!
…workflow (cheaper-inference#11039) (cheaper-inference#11168)

Cherry-picked onto the current tip (authorship preserved, Dockerfile.bun conflict with the just-merged cheaper-inference#11163 resolved additively — runner-web stage after the new entrypoint). Three pre-merge fixes on the branch: (1) generated-count noise stripped; (2) runner-web stage now returns to the non-root bun user after the apt install (mirrors the Node Dockerfile runner-web re-asserting USER node — the stage previously ended as root); (3) the 6 new build/manifest steps SHA-pinned so the zizmor ratchet stays at 191<=192 findings instead of regressing to 197 (actionlint clean). Workflow YAML parses; runner-base/runner-web targets cross-checked against the Dockerfile stages. Thank you @rqzbeh!
…nference#11122) (cheaper-inference#11154)

Validated on a worktree over the current tip: the red it fixes reproduced exactly as described (media-page-client-browser-bundle red since cheaper-inference#11122 — providerRegistry became reachable from the dashboard client bundle via node:net). Post-fix: bundle test 2/2 green, new ip-parity suite + is-local-provider 7/7, all 7 outboundUrlGuard consumer suites 76/76 (the moved normalizeHost/isPrivateHost keep their re-exports; routing behavior untouched). Thank you @yourspraveen — clean surgical extraction with a pure-JS ipVersion mirroring Node's own regexes.
… test (cheaper-inference#11160)

Validated against code before merge: 159 migration files on disk, 56 free-forever (Hack Club removal), 40 pools — counts verified, not trusted. check:docs-counts exit 0 (HARD failures drained; the 2 remaining soft executors-count notes are pre-existing on the tip) and check:test-discovery OK (orphan moved into the collected tree). These reds came from cheaper-inference#11103/cheaper-inference#11123 merging without the count regen — thanks for sweeping them @yourspraveen!
…-inference#11071) (cheaper-inference#11165)

Validated on a worktree over the current tip: account-fallback-service 91/91 plus the five sibling lockout suites 24/24. The measurement in the body (40 of 111 passthroughModels providers uncovered on this branch) is the clincher — one lookup via getProviderById().passthroughModels beside the existing checks, closing the cheaper-inference#11071 remainder for shared-registry gateways (port of cheaper-inference#11075 which had only landed on main). Thank you @yourspraveen!
… confirmed) (cheaper-inference#11114)

Validated on the combined batch board over tip 92ef3c7: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green.

Companion to cheaper-inference#11113 (consumer side): tokenrouter joins BUILTIN_PROVIDERS_SYSTEM_MUST_BE_FIRST — memory-system-first-6135 suite green. Live-confirmed 400 class documented in the body. Thank you @ggdayup!
…inference#11162)

Validated on the combined batch board over tip 92ef3c7: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green.

Combo without models is now refused at the schema boundary (API 400), the CLI flags it, and openapi.yaml matches the real contract (phantom props removed). combo-* suites + cli-combo-create-models green on the board. Closes cheaper-inference#10954. Thank you @maxmad64bis!
…e) (cheaper-inference#11158)

Validated on the combined batch board over tip 92ef3c7: static gates clean (changelog, file-size, complexity 2624<=2774, cognitive 1182<=1223, dead-code 411<=416), typecheck:core clean, focused tests green.

Empty-envelope 400 (no error field, empty content, finish_reason null) now rotates/retries instead of propagating as success; 200/streaming path never buffered; real-error 400s untouched. account-rotation + new rotation suite 34/34 on the board. Thank you @maxmad64bis!
…stem message (cheaper-inference#11113)

Validated on the combined batch board: purify-system-first suite 4/4, typecheck clean. Pre-merge: file-size baseline gained a frozen entry for contextManager.ts at 1001 (+1, this PR's merge-into-leading-system branch) with a dated annotation — the gate caps unlisted files at 1000. Producer side of the live-confirmed TokenRouter 400 class: no internal path emits a mid-array system message anymore. Thank you @ggdayup — the call-log evidence made this airtight!
…ly output (cheaper-inference#11151)

Merged after conflict resolution against the tip's cheaper-inference#11109 (per-call tool_call tracking): scanOpenAiSseText keeps the per-call finish_reason special-case AND gains reasoningText + literal finishReason; canContinue uses the in-flight predicate with the new reasoning-only-clean-stop escape. One integration fix on the branch: the PR's hallucinatedEmptyStop referenced emittedToolCall, which cheaper-inference#11109 had renamed — the branch now tracks emittedSawToolCall at the emitted level (any tool_call delta, complete or not), preserving the PR's don't-recover-after-tool-calls intent. Chain suites green: stream-continuation-wiring + stream-continuation + stream-recovery-toolcall 29/29. Thank you @maxmad64bis!
…f concatenating it raw (cheaper-inference#11152)

Merged after sibling cheaper-inference#11151 landed: streamRecovery.ts auto-merged byte-identical to the validated combined board; the test-file conflict (both PRs added suites at the same anchor) resolved keeping all 11 tests — cheaper-inference#11151's four clean-stop cases plus this PR's three threshold cases, with the PR's updated partial-tail fixture for the pre-existing overlap test. Full chain green: 32/32 (wiring + continuation + toolcall regression). The documented 8-char overlap threshold ends the silent mid-word gluing. Thank you @maxmad64bis!
cheaper-inference#11190)

* 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 cheaper-inference#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 (cheaper-inference#11190)

---------

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
…-usage json (cheaper-inference#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 cheaper-inference#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 (cheaper-inference#11190)

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

Closes cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#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!
…rence#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!
…11020)

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 cheaper-inference#11015. Thank you @RaviTharuma!
… retrieve tool (cheaper-inference#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!
…0963)

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 cheaper-inference#10962. Thank you @xz-dev!
…heaper-inference#10949, cheaper-inference#10959) (cheaper-inference#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 cheaper-inference#11110/cheaper-inference#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 cheaper-inference#10949 and cheaper-inference#10959. Thank you @jackjinke!
…eaper-inference#10644) (cheaper-inference#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 cheaper-inference#10644. Thank you @jonlwheat2-gif!
…eaper-inference#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 cheaper-inference#11130/cheaper-inference#11157/cheaper-inference#11160/cheaper-inference#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 cheaper-inference#11079, not from here.) Thank you @backryun!
rqzbeh and others added 3 commits August 23, 2026 01:00
…ocess-spawning endpoints (cheaper-inference#11189)

Validated on the combined batch board (gates + typecheck clean) and this branch: security-route-guard-tiers green. Regression coverage for the Hard Rule cheaper-inference#15/cheaper-inference#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 (cheaper-inference#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!
@diegosouzapw
diegosouzapw merged commit 47147e0 into cheaper-inference:release/v3.8.50 Aug 23, 2026
4 of 7 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…login (cheaper-inference#11143) (cheaper-inference#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 cheaper-inference#11143. Thank you @rqzbeh!
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.

[BUG] auth_token cookie not persisting after successful login — redirected back to /login from /dashboard