Skip to content

Add Grok token refresh - #3473

Closed
audreyt wants to merge 4 commits into
steipete:mainfrom
audreyt:feat/grok-token-refresh
Closed

Add Grok token refresh#3473
audreyt wants to merge 4 commits into
steipete:mainfrom
audreyt:feat/grok-token-refresh

Conversation

@audreyt

@audreyt audreyt commented Sep 7, 2026

Copy link
Copy Markdown

Rotates expired Grok OIDC access tokens via the xAI refresh endpoint (pure refresh call plus a needsRefresh predicate with 5-min leeway).

Previously the parsed refresh token was never used, so expired logins just failed.

Ownership note: CodexBar deliberately does not write auth.json — the CLI remains the sole writer, so there is no cross-process write race by construction. Persistence and live fetch wiring are follow-ups once a CLI coordination contract exists.

Verified: GrokTokenRefresherTests 6/6, ProviderArchitectureGatekeeperTests 41/41, SwiftFormat/SwiftLint clean.

Copilot AI lite review requested due to automatic review settings September 7, 2026 11:36
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

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

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-07T11:40:51.588156Z 19fec69 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI 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.

🟡 Changes recommended

The refresh flow can send whitespace-padded refresh tokens due to inconsistent trimming/validation, which can cause avoidable refresh failures.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds Grok OIDC access-token refresh support (via xAI’s OAuth token endpoint) and persists refreshed credentials back into auth.json, improving resilience when Grok logins expire.

Changes:

  • Introduces GrokTokenRefresher to POST an OAuth refresh request, parse token responses, and update credential timestamps.
  • Adds GrokCredentials.needsRefresh (5-minute leeway) plus a GrokCredentialsStore.save merge that preserves sibling scopes/unknown fields.
  • Adds a focused test suite covering refresh request formatting, rotation behavior, rejection handling, and on-disk merge behavior.
File summaries
File Description
Tests/CodexBarTests/GrokTokenRefresherTests.swift Adds coverage for refresh request construction, token rotation, refresh gating, and auth.json merge behavior.
Sources/CodexBarCore/Providers/Grok/GrokTokenRefresher.swift Implements the refresh flow, response parsing, and conditional refresh of stored credentials.
Sources/CodexBarCore/Providers/Grok/GrokAuth.swift Adds refresh gating logic and a save path to merge refreshed tokens back into auth.json.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +42 to +44
guard let refreshToken = credentials.refreshToken, !refreshToken.isEmpty else {
throw RefreshError.missingRefreshToken
}
Comment on lines +74 to +76
guard let expiresIn = Self.expiresIn(from: json["expires_in"]), expiresIn > 0 else {
throw RefreshError.invalidResponse("Missing expires_in")
}

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

Copy link
Copy Markdown

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: 19fec69467

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +88 to +92
teamId: credentials.teamId,
oidcIssuer: credentials.oidcIssuer,
oidcClientId: credentials.oidcClientId,
expiresAt: now.addingTimeInterval(expiresIn),
createTime: now)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the team principal across refresh

When refreshing credentials parsed from a team-scoped auth.json, this initializer omits principalType, so the returned value silently defaults it to nil. Any caller that immediately uses the refreshed credentials will then fail isTeamPrincipal; downstream classification in GrokWebBillingFetcher.classified will no longer convert the team's unsupported billing response into teamUsageUnsupported, preventing the identity-only fallback in GrokWebFetchStrategy.fetch. Pass through credentials.principalType and cover the team refresh case.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 7, 2026
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 7, 2026, 12:04 PM ET / 16:04 UTC.

ClawSweeper review

What this changes

Adds a Grok token-refresh helper, a five-minute expiry predicate, and six tests, while leaving credential persistence and live usage fetching unchanged.

Merge readiness

Blocked before merge - 3 items remain

Keep open: the narrowed helper is useful preparatory work, and the earlier persistence and principal findings are resolved. Real xAI exchange proof remains outstanding; repository policy also disables automatic cleanup closure.

Likely related people: Vincent Peng and Peter Steinberger (unverified routing candidates).

Priority: P2
Reviewed head: 76bc6e0555832b3bda53475b7f11ee6020e5375e

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The focused patch resolves earlier correctness concerns, but its provider contract is supported only by mocked exchanges.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: Needs real behavior proof before merge: the supplied evidence exercises GrokTokenRefresher through stubbed HTTP responses, without showing its public entrypoint exchanging a real xAI refresh token and returning a usable access token. Persistence and live usage wiring are outside this patch's stated scope. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: Needs real behavior proof before merge: the supplied evidence exercises GrokTokenRefresher through stubbed HTTP responses, without showing its public entrypoint exchanging a real xAI refresh token and returning a usable access token. Persistence and live usage wiring are outside this patch's stated scope. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 8 items Introduced scope and clean checkout: The pinned main-to-head delta contains only the credential predicate, refresh helper, and tests: 137 production lines and 154 test lines added. git status --porcelain returned no changes.
Earlier findings resolved: The current helper trims the input token, preserves principalType, and returns credentials without writing auth.json. This matches the author's scope clarification at #3473 (comment) and removes the earlier final-write race. The previous reviewed SHA was unavailable locally, so no unchanged-code attribution is claimed.
Current-main and release boundary: Current main has no GrokTokenRefresher, needsRefresh, or OAuth token endpoint in the Grok provider. Release v0.56.7 documentation explicitly delegates refresh to the Grok CLI. The existing OAuth strategy still rejects expired credentials; this branch intentionally does not connect its helper to that strategy.
Findings None None.
Security None None.

How this fits together

CodexBar reads Grok login credentials to fetch usage and display account information. The new standalone helper exchanges a refresh token with xAI and returns renewed credentials, but the existing usage pipeline does not call it.

flowchart TD
 A[Grok credentials] --> B[Expiry predicate]
 A --> C[Standalone refresh helper]
 C --> D[xAI token endpoint]
 D --> E[Renewed credentials or error]
 A --> F[Existing usage pipeline]
 F --> G[Usage and account display]
Loading

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: Needs real behavior proof before merge: the supplied evidence exercises GrokTokenRefresher through stubbed HTTP responses, without showing its public entrypoint exchanging a real xAI refresh token and returning a usable access token. Persistence and live usage wiring are outside this patch's stated scope. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve merge risk (P1) - Compatibility of the hard-coded xAI client and token exchange with real Grok-issued refresh tokens remains unverified by the supplied proof.
  • Complete next step (P2) - Add a real exchange transcript through the public helper showing renewed-token usability; terminal screenshots, console output, or logs count. Redact tokens, account details, IP addresses, and private endpoints. Update the PR body to trigger review; if needed, ask a maintainer to comment @clawsweeper re-review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test growth production +137, tests +154 Growth implements the explicitly scoped standalone refresh primitive and six focused tests.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Keep renewal isolated from CLI-owned credential storage, establish the real exchange contract, and address automatic usage integration separately with explicit credential coordination.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Keep renewal isolated from CLI-owned credential storage, establish the real exchange contract, and address automatic usage integration separately with explicit credential coordination.

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

Not applicable to the narrowed helper addition; source confirms that automatic refresh is absent, but no real token exchange was reproduced.

Is this the best way to solve the issue?

Yes for the stated preparatory scope: the helper reuses the shared transport and avoids competing credential-file writers. It does not yet solve expired logins in the live usage pipeline.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 170a4d41c6d6.

Labels

Label justifications:

  • P2: This is a bounded Grok authentication improvement without changes to the active usage pipeline.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Needs real behavior proof before merge: the supplied evidence exercises GrokTokenRefresher through stubbed HTTP responses, without showing its public entrypoint exchanging a real xAI refresh token and returning a usable access token. Persistence and live usage wiring are outside this patch's stated scope. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

  • Introduced scope and clean checkout: The pinned main-to-head delta contains only the credential predicate, refresh helper, and tests: 137 production lines and 154 test lines added. git status --porcelain returned no changes. (Sources/CodexBarCore/Providers/Grok/GrokTokenRefresher.swift:30, 76bc6e055583)
  • Earlier findings resolved: The current helper trims the input token, preserves principalType, and returns credentials without writing auth.json. This matches the author's scope clarification at Add Grok token refresh #3473 (comment) and removes the earlier final-write race. The previous reviewed SHA was unavailable locally, so no unchanged-code attribution is claimed. (Sources/CodexBarCore/Providers/Grok/GrokTokenRefresher.swift:81, 76bc6e055583)
  • Current-main and release boundary: Current main has no GrokTokenRefresher, needsRefresh, or OAuth token endpoint in the Grok provider. Release v0.56.7 documentation explicitly delegates refresh to the Grok CLI. The existing OAuth strategy still rejects expired credentials; this branch intentionally does not connect its helper to that strategy. (docs/grok.md, d8f4cec19b82)
  • Proof remains limited to stubs: The complete supplied body and discussion report six refresher tests, architecture checks, and formatting/lint checks. All exchange tests inject ProviderHTTPTransportStub; none demonstrates the public helper using ProviderHTTPClient.shared against xAI. The previous review's real-exchange rank-up remains applicable. No tests or live account probes were executed during this read-only review. (Tests/CodexBarTests/GrokTokenRefresherTests.swift:11, 76bc6e055583)
  • Credential transport safeguards: The helper uses the shared provider transport, whose production session restricts redirects to the same HTTPS origin. The response overload used here disables retries. The patch adds no credential storage, account switching, dependencies, or execution hooks. (Sources/CodexBarCore/ProviderHTTPClient.swift, 76bc6e055583)
  • Feature-history routing: Current-main history includes Vincent Peng's team-principal work and Peter Steinberger's captured-account changes. These provide routing candidates, not verified source-line introduction attribution; deeper blame/history reads encountered unavailable objects and GitHub DNS failures. (Sources/CodexBarCore/Providers/Grok/GrokProviderDescriptor.swift, 170a4d41c6d6)

Likely related people:

  • Vincent Peng: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

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

  • Provide redacted terminal output or logs showing a real xAI exchange through the public helper and successful use of the returned access token.

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 (4 earlier review cycles)
  • reviewed 2026-09-07T11:44:36.717Z sha 19fec69 :: needs real behavior proof before merge. :: [P1] Reject stale refresh results before replacing stored credentials | [P2] Preserve the team principal in renewed credentials
  • reviewed 2026-09-07T13:19:14.246Z sha 4b485c2 :: needs real behavior proof before merge. :: [P1] Protect the credential check through the final write
  • reviewed 2026-09-07T13:47:28.623Z sha 9364665 :: needs real behavior proof before merge. :: [P1] Protect the credential check through the final write
  • reviewed 2026-09-07T14:58:34.153Z sha 99c86ab :: needs real behavior proof before merge. :: none

@audreyt

audreyt commented Sep 7, 2026

Copy link
Copy Markdown
Author

@clawsweeper re-review

Addressed the P1 stale-refresh and P2 principal findings plus Copilot's trim/message nits. Stale results are now rejected by re-reading auth.json after the network await (intervening login wins, removed file stays removed), covered by new tests. Details in the updated PR body.

@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@audreyt

audreyt commented Sep 7, 2026

Copy link
Copy Markdown
Author

@clawsweeper re-review

Removed the persistence path per the ownership finding: no more save/stored-refresh helper, so CodexBar never writes auth.json and the final-write race is gone by construction. The PR is now the pure refresh call plus needsRefresh, covered by tests. The remaining live-proof and wiring items are owner follow-ups.

@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper clawsweeper Bot removed merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Sep 7, 2026
@audreyt
audreyt force-pushed the feat/grok-token-refresh branch from 99c86ab to 76bc6e0 Compare September 7, 2026 15:59
@audreyt

audreyt commented Sep 7, 2026

Copy link
Copy Markdown
Author

Live-load evidence (read-only, real account): the installed 0.56.8 build reads ~/.grok/auth.json (OIDC scope, refresh token present, expires today 17:41 UTC) and renders usage — Supergrok Heavy, 87% weekly left, reset in ~6d. No secrets were printed or stored; nothing was written.

Live renewal proof is intentionally not included: spending the refresh token can invalidate the CLI's stored session, so that step needs the owner's explicit go-ahead. The refresh call itself is covered by stubbed-transport tests.

@steipete

steipete commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Thank you for investigating expired Grok sessions. This revision adds an unused refresher without production recovery or persistence, while refresh-token exchange may invalidate the CLI session. Closing the standalone helper; an integrated repair needs a credential-owner coordination contract and actual expired-session recovery proof.

@audreyt

audreyt commented Sep 8, 2026

Copy link
Copy Markdown
Author

Integrated successor: #3497 (draft). It now calls the installed CLI owner from the production expired-session path, reloads the persisted credentials, and resumes billing. A live xAI refresh rotated both tokens; the CLI subsequently reused the new token successfully. CodexBar does not exchange refresh tokens or write auth.json. I have kept the successor in draft: the credential-owner account-change/logout coordination guarantee is still a release blocker, and the full-suite timeout is disclosed in the validation section. This is not a request to merge the standalone helper.

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

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants