Skip to content

feat(auth): auto-reauth on expired/revoked refresh tokens (invalid_grant) - #973

Closed
inamiy wants to merge 1 commit into
openclaw:mainfrom
inamiy:feat/auto-reauth-invalid-grant
Closed

feat(auth): auto-reauth on expired/revoked refresh tokens (invalid_grant)#973
inamiy wants to merge 1 commit into
openclaw:mainfrom
inamiy:feat/auto-reauth-invalid-grant

Conversation

@inamiy

@inamiy inamiy commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

When the stored OAuth refresh token is expired or revoked (invalid_grant), gog currently fails with a hard error and requires the user to manually re-run gog auth add. This is in contrast to other CLI tools (e.g. Rust's yup-oauth2 InstalledFlowAuthenticator) which automatically fall back to a browser-based re-authorization flow when the refresh token is invalid, making the failure transparent to the user.

This PR adds auto-reauth support to gog.

How it works

API call → oauth2.Transport → refresh token exchange
  → invalid_grant (expired/revoked)
    → RetryTransport detects error
      → --no-input or non-TTY? → surface clear error: "run 'gog auth add'"
      → interactive? → call Reauth()
        → browser opens OAuth flow (with --force-consent)
        → new refresh token persisted to keyring
        → in-memory token source (resettableOAuthTokenSource) rebuilt with new token
        → retry original API request

Key design decisions

  • --force-consent always used in auto-reauth to ensure Google returns a new refresh token
  • Only retries once (retriedReauth flag) — no infinite loops
  • Respects --no-input and non-TTY stdin — CI/piped environments get a clear error with gog auth add hint, not a browser
  • Excluded for ADC, service accounts, and direct access tokens — gated by concrete type assertion (*persistingTokenSource)
  • Scope preservation — reauth loads the stored token's full scope/service set, preventing silent grant narrowing (e.g. a calendar command narrowing a gmail+calendar+drive grant)
  • Email verification — authorized identity is compared with the expected email before persisting
  • Token source reset — after successful reauth, resettableOAuthTokenSource.ResetRefreshToken rebuilds the source with the new refresh token, so the retried request doesn't reuse the revoked token

Prior art

Files changed

File Description
internal/googleauth/reauth.go Reauth() function — launches browser OAuth flow, verifies identity, persists new refresh token
internal/googleauth/reauth_test.go Tests for Reauth(), email mismatch, scope preservation, servicesFromScopes()
internal/googleapi/transport.go Reauth field on RetryTransport; invalid_grant detection + auto-reauth retry in RoundTrip
internal/googleapi/client_auth.go ResetRefreshToken on resettableOAuthTokenSource/persistingTokenSource; isInvalidGrantError() detector; refreshTokenResetter interface
internal/googleapi/client.go reauthFunctionFromContext() closure — loads stored token, calls Reauth, resets token source
internal/googleapi/auth_dependencies.go ReauthFunc type, Reauth field, WithNoInput()/NoInputFromContext()
internal/cmd/root.go Wires reauthFn into AuthDependencies; propagates --no-input + TTY detection
internal/googleapi/auto_reauth_test.go Tests for invalid_grant detection, retry state machine, NoInputFromContext
internal/googleapi/reauth_glue_test.go Integration tests for production closure + real token source chain
docs/auto-reauth-issue-draft.md Issue draft (can be split out)
CHANGELOG.md Unreleased entry

Testing

  • go build ./...
  • go vet ./...
  • go test ./internal/googleapi/... ./internal/googleauth/... -count=1
  • go test ./internal/cmd/... -count=1
  • go test -race ./internal/googleapi/... -run Reauth
  • Not yet tested against live Google APIs (see disclaimer above)

Related issue

Issue draft included in docs/auto-reauth-issue-draft.md — can be posted separately.

…ant)

When the stored OAuth refresh token is expired or revoked (invalid_grant),
gog currently fails with a hard error and requires the user to manually
re-run 'gog auth add'. This is in contrast to other CLI tools (e.g. Rust's
yup-oauth2 InstalledFlowAuthenticator) which automatically fall back to a
browser-based re-authorization flow when the refresh token is invalid.

This PR adds auto-reauth support:

- In interactive sessions (TTY stdin, --no-input not set), gog detects
  invalid_grant during token refresh, launches a browser-based OAuth flow
  (with --force-consent to ensure a new refresh token), persists it to the
  keyring, resets the in-memory token source, and retries the original
  API request.
- In non-interactive sessions (--no-input or non-TTY stdin), gog surfaces
  a clear error message with the manual 'gog auth add' command instead.
- Excluded for ADC, service accounts, and direct access tokens.
- The reauth preserves the stored token's full scope/service set,
  preventing silent grant narrowing.
- The authorized email is verified to match the expected account before
  persisting.
- The in-memory token source (resettableOAuthTokenSource) is rebuilt with
  the new refresh token so the retried request doesn't reuse the revoked
  token.

Design inspired by yup-oauth2's InstalledFlowAuthenticator.find_token_info()
fallback pattern: https://github.com/dermesser/yup-oauth2/blob/master/src/authenticator.rs

Co-authored-by: Yasuhiro Inami <inamiy@gmail.com>
@clawsweeper

clawsweeper Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@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 priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. labels Aug 9, 2026
@clawsweeper

clawsweeper Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed August 9, 2026, 7:58 PM ET / 23:58 UTC.

ClawSweeper review

What this changes

Adds one-time interactive browser reauthorization and request replay when a stored Google OAuth refresh token returns invalid_grant, while retaining an actionable non-interactive error path.

Merge readiness

⚠️ Needs maintainer review before merge - 3 items remain

Keep open: current main still requires manual reauthorization, and this PR has credible live proof, but its reset path can overwrite the newly stored refresh token with the revoked cached token on the first post-reauth refresh. The automatic browser-launch behavior also needs maintainer product approval.

Priority: P1
Reviewed head: 93a30061794f788d649947b00e0d8bee83e267fa
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Live provider proof is strong, but the credential-persistence defect and unapproved interaction policy keep the patch from merge readiness.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): The contributor supplied an after-fix live Google Calendar terminal transcript for both revoked-token recovery and the non-interactive guard; redact account and event details in any future proof updates.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): The contributor supplied an after-fix live Google Calendar terminal transcript for both revoked-token recovery and the non-interactive guard; redact account and event details in any future proof updates.
Evidence reviewed 6 items Current main behavior: Current main diagnoses invalid_grant and instructs users to rerun gog auth add; it does not contain the proposed automatic reauthorization fallback.
Credential persistence defect: The new reset method updates only the inner token source. It does not update persistingTokenSource.tok, whose stale refresh token is later used as the basis for persistence.
Regression coverage gap: The glue test verifies the inner resettable source receives the new token, but does not execute a subsequent refresh and assert that the store retains the new refresh token.
Findings 1 actionable finding [P1] Synchronize the persisted token cache after reauthorization
Security None None.

How this fits together

gog builds authenticated Google API clients from stored OAuth credentials. Requests pass through token refresh and retry handling before Google Workspace APIs; this PR would replace revoked credentials and replay the failed request.

flowchart LR
A[CLI command] --> B[Stored OAuth token]
B --> C[Token refresh]
C --> D{Token revoked?}
D -- No --> E[Google Workspace API]
D -- Yes --> F[Interactive reauthorization]
F --> G[Persist token and retry]
G --> E
Loading

Decision needed

Question Recommendation
After an interactive invalid_grant, should gog immediately open the OAuth browser, or require an explicit confirmation and preserve the existing manual command as the default recovery path? Require confirmation before browser launch: Keep automatic detection but ask an interactive user to confirm reauthorization, while --no-input and non-TTY sessions retain the manual command hint.

Why: This is a new user-visible recovery policy rather than an established bug contract; the repository vision requires discussion for behavior changes that may affect existing workflows.

Before merge

  • Synchronize the persisted token cache after reauthorization (P1) - ResetRefreshToken changes only p.base; p.tok.RefreshToken remains revoked. Google refresh responses commonly omit RefreshToken, so the next successful refresh copies that stale cached value into storage and undoes the reauthorization. Update p.tok under p.mu and add a subsequent-refresh regression test.
  • Resolve merge risk (P1) - Interactive users may now receive an immediate browser and keychain prompt after a token failure, changing the established manual-recovery behavior for terminal workflows.

Findings

  • [P1] Synchronize the persisted token cache after reauthorization — internal/googleapi/client_auth.go:185-188
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch footprint production +432, tests +1,100, docs/release +96 The 1,628-line, 11-file change is substantial for an auth-policy feature and merits the vision-required direction review.

Merge-risk options

Maintainer options:

  1. Repair persistence and confirm the interaction model (recommended)
    Update the persisted token cache under its lock, add a post-reauth refresh regression, and obtain approval for the browser-launch UX before merge.
  2. Accept immediate browser reauthorization
    Maintainers can retain the current immediate launch behavior after the cache defect is repaired, accepting the changed interactive workflow.
  3. Pause the automatic fallback
    Keep the established manual recovery path if the interactive browser policy is not desired.

Technical review

Best possible solution:

Repair the persistence cache, retain the explicit non-interactive fallback, and land only the interactive UX that the auth owner approves, preferably with an explicit confirmation before opening a browser.

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

Yes—source inspection gives a high-confidence path: reauthorize, then force a subsequent token refresh whose response omits RefreshToken; the stale persistence cache will write the revoked value back. The review did not execute that path in this read-only checkout.

Is this the best way to solve the issue?

No—the recovery mechanism is promising, but it must synchronize the persisting cache and receive approval for its automatic browser-launch policy before it is the safest solution.

Full review comments:

  • [P1] Synchronize the persisted token cache after reauthorization — internal/googleapi/client_auth.go:185-188
    ResetRefreshToken changes only p.base; p.tok.RefreshToken remains revoked. Google refresh responses commonly omit RefreshToken, so the next successful refresh copies that stale cached value into storage and undoes the reauthorization. Update p.tok under p.mu and add a subsequent-refresh regression test.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.99

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against bd733de86dbe.

Labels

Label justifications:

  • P1: As written, a successful recovery can persist the revoked credential again, breaking the next authenticated workflow.
  • merge-risk: 🚨 compatibility: Interactive invalid-grant failures change from a manual command to an automatic browser/keychain interaction.
  • merge-risk: 🚨 auth-provider: The patch changes OAuth refresh-token replacement and persistence behavior.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The contributor supplied an after-fix live Google Calendar terminal transcript for both revoked-token recovery and the non-interactive guard; redact account and event details in any future proof updates.
  • proof: sufficient: Contributor real behavior proof is sufficient. The contributor supplied an after-fix live Google Calendar terminal transcript for both revoked-token recovery and the non-interactive guard; redact account and event details in any future proof updates.

Evidence

Acceptance criteria:

  • [P1] go test ./internal/googleapi/... -count=1.
  • [P1] go test -race ./internal/googleapi/... -run Reauth -count=1.

What I checked:

  • Current main behavior: Current main diagnoses invalid_grant and instructs users to rerun gog auth add; it does not contain the proposed automatic reauthorization fallback. (internal/cmd/auth_doctor.go:258, bd733de86dbe)
  • Credential persistence defect: The new reset method updates only the inner token source. It does not update persistingTokenSource.tok, whose stale refresh token is later used as the basis for persistence. (internal/googleapi/client_auth.go:185, 93a30061794f)
  • Regression coverage gap: The glue test verifies the inner resettable source receives the new token, but does not execute a subsequent refresh and assert that the store retains the new refresh token. (internal/googleapi/reauth_glue_test.go:74, 93a30061794f)
  • Real behavior proof: The contributor supplied a live Google Calendar transcript covering a revoked token, successful interactive consent and replay, plus the --no-input failure path; it demonstrates the intended initial recovery but not a later refresh after that recovery. (93a30061794f)
  • Area provenance: Blame attributes the current token persistence and retry integration to the v0.35.0 release commit, making its author the strongest current-main routing candidate. (internal/googleapi/client_auth.go:158, 402def5041d6)
  • Product-direction policy: The repository VISION.md calls for discussion of large PRs and behavior changes that could affect existing scripts, while requiring live proof for Google-provider behavior. (VISION.md:23, bd733de86dbe)

Likely related people:

  • Peter Steinberger: Current-main blame assigns the token persistence and retry chain to the v0.35.0 release commit; the latest main commit also documents browser-driven OAuth reauthorization. (role: recent area contributor; confidence: high; commits: 402def5041d6, bd733de86dbe; files: internal/googleapi/client_auth.go, internal/googleapi/client.go, internal/cmd/auth_doctor.go)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Synchronize persistingTokenSource.tok and test a post-reauth refresh that omits RefreshToken.
  • Obtain a maintainer decision on confirmation versus immediate browser launch.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (8 earlier review cycles)
  • reviewed 2026-08-09T15:32:43.519Z sha 93a3006 :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-09T16:59:01.271Z sha 93a3006 :: needs changes before merge. :: [P1] Synchronize the persisting token cache after reauth
  • reviewed 2026-08-09T17:32:46.530Z sha 93a3006 :: found issues before merge. :: [P1] Synchronize the persisting token cache after reauth
  • reviewed 2026-08-09T18:52:23.938Z sha 93a3006 :: needs changes before merge. :: [P1] Synchronize the persisting token cache after reauth
  • reviewed 2026-08-09T19:30:05.992Z sha 93a3006 :: found issues before merge. :: [P1] Synchronize the persistence cache after reauthorization
  • reviewed 2026-08-09T21:04:36.348Z sha 93a3006 :: found issues before merge. :: [P1] Synchronize the persistence cache after reauthorization
  • reviewed 2026-08-09T21:44:13.296Z sha 93a3006 :: needs changes before merge. :: [P1] Synchronize the persisting token cache after reauthorization
  • reviewed 2026-08-09T22:52:35.518Z sha 93a3006 :: found issues before merge. :: [P1] Synchronize the persisted token cache after reauthorization

@inamiy

inamiy commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Live behavior proof

Tested against real Google Calendar API with a revoked refresh token (revoked via https://oauth2.googleapis.com/revoke).

Test 1: --no-input path (non-interactive)

Token revoked, run with --no-input:

$ gog --no-input calendar events --today
refresh token expired or revoked: base token source: resettable oauth token source: oauth2: "invalid_grant" "Token has been expired or revoked."; run 'gog auth add' to re-authorize
EXIT_CODE=1

✅ No browser launched; clear error with actionable gog auth add hint.

Test 2: Interactive auto-reauth (TTY)

Same revoked token, run from a terminal (pseudo-TTY via script):

$ gog calendar events --today
Refresh token expired or revoked. Re-authorizing…
Opening browser for authorization…
If the browser doesn't open, visit this URL:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=…&prompt=consent&redirect_uri=http%3A%2F%2F127.0.0.1%3A56780%2Foauth2%2Fcallback&…
Authorization received. Finishing…
Re-authorization successful. Retrying request…

ID                              START                       END                         SUMMARY
ru09mkqs02fk3sr3jasauom9j0      2026-08-08T23:50:00+01:00   2026-08-09T00:10:00+01:00   バグレポート整理…
bmqd2e7keb4n13flt5hbrs6aqo      2026-08-09T00:00:00+01:00   2026-08-09T10:30:00+01:00   💤 睡眠
…

EXIT_CODE=0

✅ Full auto-reauth flow completed: browser opened → OAuth consent → new token persisted → request retried → calendar events returned.

Test 3: Post-reauth token verification

$ gog auth list --check
inamiy@gmail.com  default  calendar,drive,gmail  2026-08-09T15:42:57Z  true  oauth

✅ Token valid after auto-reauth.

What was verified against live Google APIs

  1. invalid_grant detection works with real Google OAuth responses
  2. ✅ Browser OAuth flow opens with --force-consent and include_granted_scopes=true
  3. ✅ Scope preservation — OAuth URL contained all original scopes (calendar, drive, gmail)
  4. ✅ New refresh token persisted to macOS Keychain
  5. ✅ In-memory token source reset — retried request succeeded (did not reuse revoked token)
  6. --no-input suppression — no browser launched, clear error with gog auth add hint
  7. ✅ Non-TTY suppression — no browser when stdin is piped
  8. ✅ Token revocation via Google's /revoke endpoint correctly triggers the flow

UX caveats (known rough edges for PoC)

The current auto-reauth UX has some rough edges that should be polished before merging:

  1. Browser opens suddenly without confirmation. When invalid_grant is detected in an interactive session, the browser immediately opens the Google OAuth consent screen. There is no prompt like "Your session has expired. Re-authorize now? [Y/n]" — the user might be surprised by a browser window appearing unexpectedly mid-command. A confirmation prompt (respecting --no-input) would make this feel more deliberate.

  2. Keychain password prompt may appear without explanation. The Reauth function calls EnsureKeychainAccess before launching the browser, and store.SetToken writes the new token after the flow completes. On macOS, either of these can trigger a Keychain access prompt (especially for binaries not signed with keychain-access-groups entitlement). The user sees a system dialog asking for keychain approval with no context about why gog needs keychain access at this moment. This is partially related to existing issue macOS 27 Tahoe beta: Keychain C API silently writes 0 bytes — file keyring workaround required #939 (macOS Tahoe Keychain C API issues) and may not appear in all configurations, but the UX could be smoother with a stderr message like "Storing new credentials in keychain…" before the write.

  3. The keychain access step (EnsureKeychainAccess) may be unnecessary in some cases. If the keychain is already unlocked (common for interactive sessions where the user has recently used gog), the pre-flight EnsureKeychainAccess call is redundant and may trigger an extra permission prompt that would not appear during a normal gog auth add. This is worth investigating — it may be better to skip the pre-flight check and let SetToken handle keychain access naturally, with a clear error if it fails.

These are UX polish items, not correctness issues — the core auto-reauth mechanism (detect → reauth → persist → reset → retry) works correctly as demonstrated above.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. 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. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 9, 2026
@steipete

Copy link
Copy Markdown
Collaborator

LAND verdict: I prepared the maintainer landing branch in #974 and preserved your authored feature commit.

Thank you for the unusually useful live Google proof—it made the recovery behavior much easier to validate. Before landing, the maintainer branch fixes the stale persistence cache, adds a post-reauth refresh regression, requires confirmation before browser launch, and coalesces recovery across separate service clients so one revoked account cannot trigger multiple concurrent browser flows. It also narrows detection to typed OAuth invalid_grant errors and keeps the non-interactive/manual recovery path.

Please leave this PR open while #974 receives final maintainer review. No action is requested from you.

@steipete

Copy link
Copy Markdown
Collaborator

Landed — thank you, and your commit is preserved in the merge.

This shipped as #974 (229da128), which carries your authored commit plus a
maintainer hardening pass. Closing this one in favour of that branch rather
than merging here, since the follow-up work happened there.

Your diagnosis was right and the live Google Calendar proof you attached was
genuinely useful. Four things needed tightening before it was safe to land on
the auth path, and they are worth writing down:

  1. The revoked token could come back. ResetRefreshToken updated only the
    inner source, so persistingTokenSource.tok still held the revoked token. A
    later refresh response that omits refresh_token — which is normal — would
    persist the revoked value again. Replacement metadata is now written before
    the in-memory source is swapped.

  2. Browser stampede. Retry state was bounded per HTTP request, but one
    command can build several service clients for the same account, so a single
    revocation could open several browser flows at once. Recovery is now
    serialized across every client in the command, and waiters adopt the newly
    stored token instead of starting their own flow.

  3. Consent. The interactive path opened a browser immediately. It now asks
    first, and declining fails cleanly:

    Refresh token for <account> expired or was revoked. Re-authorize now? [y/N]:
    … re-authentication failed: reauth: cancelled; run 'gog auth add' to re-authorize manually
    
  4. Detection and identity. invalid_grant was matched on arbitrary error
    text; it now matches only the typed OAuth retrieval error. An empty identity
    email also fell back to the expected email, which quietly weakened the
    identity check — mismatched or missing emails are now rejected.

The --no-input, non-TTY, ADC, service-account, direct-access-token,
non-replayable-request and one-retry boundaries are all preserved, with
regression coverage for post-reauth refresh and concurrent clients.

You are credited in the 0.35.1 changelog. Good catch on a real gap.

@steipete steipete closed this Aug 10, 2026
@inamiy
inamiy deleted the feat/auto-reauth-invalid-grant branch August 10, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants