Skip to content

fix(auth): stop new sessions inheriting auto-selected auth profile overrides#62710

Closed
zeynalnia wants to merge 23 commits into
openclaw:mainfrom
zeynalnia:fix/auth-profile-override-sticky-new-sessions
Closed

fix(auth): stop new sessions inheriting auto-selected auth profile overrides#62710
zeynalnia wants to merge 23 commits into
openclaw:mainfrom
zeynalnia:fix/auth-profile-override-sticky-new-sessions

Conversation

@zeynalnia

@zeynalnia zeynalnia commented Apr 7, 2026

Copy link
Copy Markdown

Summary

  • Problem: New sessions inherit authProfileOverride from rate-limited or cooldown backup profiles instead of using the default/best available profile. The auto-failover override persists across gateway restarts, /new, /reset, and manual session clearing.
  • Why it matters: Users get stuck on a degraded auth profile with no way to recover short of deleting session state, and the lastGood/cooldownUntil fields are effectively ignored.
  • What changed: Auto-selected (source === "auto") auth profile overrides are now discarded at session boundaries (gateway reset, /new, /reset). Only user-explicitly-set overrides (source === "user") carry over. Defense-in-depth in resolveSessionAuthProfileOverride ensures new sessions always call pickFirstAvailable() for auto overrides.
  • What did NOT change (scope boundary): User-set auth profile overrides (/auth command) still carry over across session resets as before. The round-robin and cooldown logic is unchanged for continuing (non-new) sessions.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: Three code paths unconditionally carry over authProfileOverride from old to new sessions regardless of whether the override was auto-selected (failover) or user-set. The authProfileOverrideSource discriminator existed in the data model but was not consulted at session boundaries.
  • Missing detection / guardrail: No distinction between "auto" and "user" source when propagating auth profile overrides across session resets.
  • Contributing context (if known): The auto-failover system correctly sets authProfileOverrideSource: "auto" but the session reset and init paths treated all overrides identically.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/auth-profiles/session-override.test.ts
  • Scenario the test should lock in: New session with authProfileOverrideSource: "auto" picks first available profile (not round-robin from stale position); new session with authProfileOverrideSource: "user" round-robins as before; cooldown profiles are skipped.
  • Why this is the smallest reliable guardrail: The resolver function is the last line of defense — testing it covers the defense-in-depth layer regardless of upstream session propagation behavior.
  • Existing test that already covers this (if any): None — only provider-alias and early-return tests existed.
  • If no new test is added, why not: 5 new tests added.

User-visible / Behavior Changes

  • New sessions (via /new, /reset, gateway restart, or session expiry) now start with the best available auth profile instead of inheriting a stale auto-failover profile that may be in cooldown or rate-limited.
  • User-explicitly-set auth profile overrides (via /auth or similar) still persist across session resets.

Diagram (if applicable)

Before:
[rate limit] -> [auto-failover to backup1] -> [/new] -> [backup1 still active, even if in cooldown]

After:
[rate limit] -> [auto-failover to backup1] -> [/new] -> [pickFirstAvailable() -> default profile]

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Linux 6.17.0-1010-azure (x64) per issue report
  • Runtime/container: Node v22.22.1
  • Model/provider: anthropic/claude-opus-4-6
  • Integration/channel (if any): Telegram DM
  • Relevant config (redacted): 3 Anthropic auth profiles (default + 2 backups)

Steps

  1. Configure multiple auth profiles for the same provider
  2. Use system until one profile hits a transient rate limit, triggering auto-failover
  3. Start a new session (/new, /reset, or new message after expiry)

Expected

  • New session uses the best available non-cooldown profile (typically the default)

Actual

  • New session inherits the rate-limited backup profile from the previous session

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

5 new unit tests in src/agents/auth-profiles/session-override.test.ts all pass, covering auto vs user override propagation, cooldown skipping, legacy inference, and all-cooldown fallback.

Human Verification (required)

  • Verified scenarios: All 5 new tests pass; all 7 tests in session-override.test.ts pass; full auth-profiles test suite (109/110 pass, 1 pre-existing unrelated failure in state-observation.test.ts)
  • Edge cases checked: Legacy session entries without authProfileOverrideSource, all-profiles-in-cooldown fallback, provider alias normalization
  • What you did not verify: End-to-end gateway restart with real multi-profile setup; the gateway session-reset-service path is tested indirectly via the defense-in-depth layer

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: Existing sessions with authProfileOverrideSource: "auto" will lose their override on the next session reset, changing profile selection behavior.
    • Mitigation: This is the intended fix. Auto overrides were never meant to be permanent; they should be re-evaluated per session.

🤖 Generated with Claude Code

AI Disclosure

  • This PR was AI-assisted (built with Claude Code / Claude Opus 4.6)
  • Fully tested: 5 new unit tests added, all 7 tests in session-override.test.ts pass, full auth-profiles/ suite passes (109/110, 1 pre-existing unrelated failure)
  • I understand what the code does
  • Bot review conversations will be resolved as addressed

CI Note

The check and check-additional CI failures are pre-existing on main — type errors in extensions/slack/src/approval-handler.runtime.test.ts and extensions/telegram/src/approval-handler.runtime.test.ts (TS18046: 'payload' is of type 'unknown'). These are unrelated to this PR's changes.

@zeynalnia
zeynalnia requested a review from a team as a code owner April 7, 2026 21:08
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime agents Agent runtime and tooling size: M labels Apr 7, 2026
@greptile-apps

greptile-apps Bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where authProfileOverride values set by auto-failover (source "auto") were incorrectly propagated to new sessions via three code paths: resolveSessionAuthProfileOverride, initSessionState, and performGatewaySessionReset. The fix consistently checks authProfileOverrideSource === "user" before carrying any override into a new session, and adds a defense-in-depth guard in the resolver that calls pickFirstAvailable() for auto overrides instead of pickNextAvailable(). Five new targeted unit tests cover the key scenarios and all pass.

Confidence Score: 5/5

Safe to merge — targeted fix with no regressions; all findings are style-level or lower.

All three code paths that propagated auto overrides into new sessions are correctly patched with identical source === "user" guards. The defense-in-depth layer in resolveSessionAuthProfileOverride is updated consistently, including the write-back that now correctly preserves "user" source rather than always overwriting to "auto". Five new unit tests lock in the intended behavior for auto vs user overrides, cooldown skipping, legacy inference, and all-cooldown fallback. No P0 or P1 issues found.

No files require special attention.

Vulnerabilities

No security concerns identified. The change narrows what session state is propagated (dropping auto auth overrides), which can only reduce — not expand — the attack surface for auth bypass or profile confusion.

Reviews (3): Last reviewed commit: "Merge branch 'upstream-main' into fix/au..." | Re-trigger Greptile

@zeynalnia
zeynalnia force-pushed the fix/auth-profile-override-sticky-new-sessions branch 2 times, most recently from 2a4d681 to 30d83ea Compare April 7, 2026 21:56
@zeynalnia zeynalnia closed this Apr 7, 2026
@zeynalnia zeynalnia reopened this Apr 7, 2026
@zeynalnia
zeynalnia force-pushed the fix/auth-profile-override-sticky-new-sessions branch 2 times, most recently from cbdbd15 to d0ebc5a Compare April 7, 2026 23:45
…errides (openclaw#62412)

New sessions were inheriting `authProfileOverride` from rate-limited or
cooldown backup profiles instead of picking the best available profile.
The auto-failover override leaked through three paths: gateway session
reset, /new and /reset command handling, and the session override
resolver's round-robin logic.

Only carry over auth profile overrides when the source is "user"
(explicitly set). Auto-selected overrides are now discarded at session
boundaries so the new session resolves the best available non-cooldown
profile fresh via pickFirstAvailable().

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@zeynalnia
zeynalnia force-pushed the fix/auth-profile-override-sticky-new-sessions branch from d0ebc5a to d69ba4c Compare April 7, 2026 23:47
@zeynalnia
zeynalnia marked this pull request as draft April 7, 2026 23:54
@zeynalnia
zeynalnia marked this pull request as ready for review April 7, 2026 23:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a341f08add

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/auth-profiles/session-override.ts Outdated
Comment thread src/auto-reply/reply/session.ts Outdated
Comment thread src/gateway/session-reset-service.ts Outdated
zeynalnia and others added 4 commits April 7, 2026 20:03
…legacy entries

- User-set overrides now persist across /new without rotation (return
  early instead of round-robining), eliminating the source corruption
  where the persist block relabeled user overrides as "auto".
- Use !== "auto" instead of === "user" in session.ts and
  session-reset-service.ts to preserve legacy entries that have an
  override but no authProfileOverrideSource field.
- Revert source preservation in persist block back to always "auto"
  since user overrides now return before reaching it.
- Add tests for legacy entry preservation and consecutive /new survival.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a475e5b7a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/gateway/session-reset-service.ts Outdated
zeynalnia and others added 2 commits April 8, 2026 00:04
Legacy session entries from auto-failover have
authProfileOverrideCompactionCount set but no authProfileOverrideSource
field. The !== "auto" guard missed these, letting stale failover
overrides leak through gateway reset and /new as if they were user
choices. Now both paths also check for the compactionCount heuristic
to correctly identify and drop legacy auto overrides.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bcc52cfcf1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/auto-reply/reply/session.ts Outdated
Comment thread src/gateway/session-reset-service.ts Outdated
zeynalnia and others added 4 commits April 8, 2026 00:12
The compactionCount heuristic for detecting legacy auto overrides was
too aggressive — it also dropped explicit user overrides (source:
"user") that happened to have a stale authProfileOverrideCompactionCount.

Now the carry-over logic checks source first: explicit "user" always
carries over, explicit "auto" always drops, and only undefined-source
entries fall through to the compactionCount heuristic.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 1, 2026
@clawsweeper

clawsweeper Bot commented May 2, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I did a careful shell check against current main, and the useful part of this older PR is already implemented there.

Close this older PR: the central reset-boundary fix is already on current main and shipped, with shared reset preservation code and regression coverage. The remaining branch diff is stale against the current reset architecture, includes release-owned changelog edits, and any broader wrong-provider auth loop is tracked separately.

So I’m closing this older PR as already covered on main rather than keeping a mostly-duplicated branch open.

Review details

Best possible solution:

Keep the shipped shared reset-preservation implementation, and handle any remaining wrong-provider auth loop through the narrower current thread at #85126.

Do we have a high-confidence way to reproduce the issue?

Yes for the central reset-boundary bug: current source and regression tests show auto-sourced auth/model overrides are cleared on /new and /reset while user overrides persist. I did not run a live multi-profile Telegram setup during this read-only cleanup review.

Is this the best way to solve the issue?

No, merging this branch is no longer the best way to solve it. Current main’s shared reset-preservation helper is the cleaner shipped owner boundary, and any remaining resolver-only gap should be a new focused PR against that code.

Security review:

Security review cleared: The diff touches auth/session routing but does not add permissions, dependency sources, secret handling, network calls, or a concrete new security regression beyond the merge risks already called out.

AGENTS.md: found and applied where relevant.

What I checked:

  • Current main reset policy: Current main centralizes reset preservation in resolveResetPreservedSelection, which preserves only user-driven auth profile overrides and drops auto-created runtime fallback auth overrides so resets return to configured defaults. (src/config/sessions/reset-preserved-selection.ts:16, 37e3e895b020)
  • Current main callers: Both /new//reset session initialization and gateway sessions.reset call the shared reset preservation helper before minting the replacement session entry. (src/auto-reply/reply/session.ts:538, 37e3e895b020)
  • Current main regression tests: Current tests cover both preserving explicit user auth overrides across /new and /reset and clearing auto-sourced model/provider/auth overrides on those resets. (src/auto-reply/reply/session.test.ts:2639, 37e3e895b020)
  • Fix provenance: Commit 5d46e4dc4f458d3ef2097c881eab3a78f2abee2b merged the central shipped behavior via fix(gateway): clear auto-fallback model override on session reset, explicitly describing that auto fallback auth/profile overrides are dropped on /reset and /new while user selections persist. (src/gateway/session-reset-service.ts:985, 5d46e4dc4f45)
  • Release provenance: git tag --contains shows the fix is included in v2026.4.9, and that tag's changelog records the gateway/sessions fix for clearing auto-fallback-pinned model overrides on /reset and /new. (CHANGELOG.md:42, 0512059dd4e6)
  • Remaining branch diff: The PR still patches the old in-place gateway reset helper shape and adds normal PR changelog entries; current main has moved the reset decision to src/config/sessions/reset-preserved-selection.ts, so the branch is no longer the clean landing path. (src/gateway/session-reset-service.ts:92, a16e13f7cb6a)

Likely related people:

  • frankekn: Auth/session reset behavior matching the central PR request was merged through fix(gateway): clear auto-fallback model override on session reset. (role: implemented shipped fix; confidence: high; commits: 5d46e4dc4f45; files: src/gateway/session-reset-service.ts, src/auto-reply/reply/agent-runner-execution.ts, src/sessions/model-overrides.ts)
  • vincentkoc: Current blame attributes the shared reset helper and current reset/auth override lines to recent main-line work in the session/auth area. (role: recent area contributor; confidence: medium; commits: c60b42412482, 37e3e895b020; files: src/config/sessions/reset-preserved-selection.ts, src/auto-reply/reply/session.ts, src/gateway/session-reset-service.ts)
  • steipete: The auth profile session override helper and its original tests were introduced in fix: normalize model override auth handling. (role: introduced auth-profile resolver; confidence: medium; commits: 1e05925e47b2; files: src/agents/auth-profiles/session-override.ts, src/agents/auth-profiles/session-override.test.ts)
  • Takhoffman: Commit cb0a75215688 added reset-session preservation behavior that later needed the shipped auto-fallback cleanup. (role: introduced adjacent reset preservation behavior; confidence: medium; commits: cb0a75215688; files: src/gateway/session-reset-service.ts, src/gateway/server.sessions.gateway-server-sessions-a.test.ts)

Codex review notes: model internal, reasoning high; reviewed against 37e3e895b020; fix evidence: release v2026.4.9, commit 5d46e4dc4f45.

@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label May 3, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels May 19, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 19, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Jun 5, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 5, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 6, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling gateway Gateway runtime merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: New sessions inherit authProfileOverride from cooldown/rate-limited backup profile instead of using default

1 participant