fix(subscription): 避免临时刷新失败锁死凭据 - #499
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough本次变更为凭据刷新增加可重试失败分类,并保留 HTTP 状态码、OAuth 错误码和重试等待时间。临时失败时,凭据阶段恢复为 Merge Risk: 🟡 Moderate · up to Successful manual credential refresh can leave the credential unavailable to normal traffic until an earlier cooldown expires, delaying service recovery. Refresh failure state may also be slow to appear in the management UI, and some provider failures may lose retry guidance; these bounded issues should be fixed or explicitly accepted before merging. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/features/groups/credentials/GroupCredentialsTab.vue (1)
714-717: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win刷新失败后重新同步凭据状态。
refreshCredentialRequest失败时,服务端仍可能已将auth_state更新为ready、reauthorization_required或outcome_unknown,但catch只更新feedback,因此凭据列表和分组摘要会继续显示旧缓存。useApiClient不会自动失效查询。请在失败分支使用Promise.allSettled重新获取当前凭据页和分组摘要。
🟡 Other comments (1)
web/src/i18n/locales/ja-JP/group.ts-550-550 (1)
550-550: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win修正日文
outcome_unknown文案。
認証情報の更新結果不明です缺少が,日语表达不自然。認証情報の結果不明又省略了“更新”,没有明确说明未知的是凭据刷新结果。请统一语义。建议修改
- outcome_unknown: '認証情報の更新結果不明です。再接続または再インポートしてください', + outcome_unknown: '認証情報の更新結果が不明です。再接続または再インポートしてください', ... - outcome_unknown: '認証情報の結果不明', + outcome_unknown: '認証情報の更新結果が不明',Also applies to: 582-582
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: QUIET
Plan: Pro Plus
Run ID: 692abe5a-5b72-44a9-9d41-08682224f570
📒 Files selected for processing (34)
internal/control/credential_actions_test.gointernal/control/credential_stages.gointernal/control/credential_stages_test.gointernal/control/discover_group_test.gointernal/control/discover_subscription.gointernal/control/discover_test.gointernal/execution/contracts.gointernal/gateway/handler_test.gointernal/health/execution_judge.gointernal/health/execution_judge_test.gointernal/platform/errors/errors.gointernal/subscription/credential_manager.gointernal/subscription/credential_manager_test.gointernal/subscription/providers/antigravity/driver.gointernal/subscription/providers/antigravity/driver_test.gointernal/subscription/providers/claude/driver.gointernal/subscription/providers/claude/driver_test.gointernal/subscription/providers/codex/driver.gointernal/subscription/providers/codex/driver_test.gointernal/subscription/providers/grok/driver.gointernal/subscription/providers/grok/driver_test.gointernal/subscription/runtime/runtime.gointernal/subscription/runtime/runtime_test.gothird_party/cpaembedded/embedded/grok_oauth.gothird_party/cpaembedded/embedded/grok_test.goweb/src/features/groups/credentials/GroupCredentialsTab.vueweb/src/features/groups/credentials/SubscriptionAccountCard.vueweb/src/features/subscription-error-presenter.tsweb/src/i18n/locales/en-US/core.tsweb/src/i18n/locales/en-US/group.tsweb/src/i18n/locales/ja-JP/core.tsweb/src/i18n/locales/ja-JP/group.tsweb/src/i18n/locales/zh-CN/core.tsweb/src/i18n/locales/zh-CN/group.ts
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6551cdf540
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 75c2195eab
ℹ️ 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".
There was a problem hiding this comment.
Actionable comments posted: 1
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
third_party/cpaembedded/embedded/grok_oauth.go-127-127 (1)
127-127: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win先处理失败状态,再解析设备令牌响应。
当设备令牌端点返回 HTTP 503 和非 JSON 响应体时,Line 127 获得的
status与retryAfter会在 Line 133 的json.Unmarshal失败后丢失。调用方只会收到通用解码错误,不能识别临时端点失败或使用冷却时间。将status != http.StatusOK分支移到 JSON 解析之前,并在该分支中尽力提取 OAuth 错误码。建议修改
defer clear(body) var token grokTokenResponse + if status != http.StatusOK { + _ = json.Unmarshal(body, &token) + return GrokDevicePoll{}, &GrokTokenEndpointError{ + StatusCode: status, Code: boundedGrokOAuthCode(token.Error), RetryAfter: retryAfter, + } + } if err := json.Unmarshal(body, &token); err != nil { return GrokDevicePoll{}, fmt.Errorf("decode Grok device token response: %w", err) }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: QUIET
Plan: Pro Plus
Run ID: 6a1911d0-7fcc-4fea-83e4-b6c0451c1fd8
📒 Files selected for processing (30)
internal/health/execution_judge_test.gointernal/subscription/credential_manager.gointernal/subscription/credential_manager_test.gointernal/subscription/providers/antigravity/antigravity.gointernal/subscription/providers/antigravity/antigravity_test.gointernal/subscription/providers/antigravity/driver.gointernal/subscription/providers/antigravity/driver_test.gointernal/subscription/providers/claude/claude.gointernal/subscription/providers/claude/claude_test.gointernal/subscription/providers/claude/driver.gointernal/subscription/providers/claude/driver_test.gointernal/subscription/providers/codex/codex.gointernal/subscription/providers/codex/codex_test.gointernal/subscription/providers/codex/driver.gointernal/subscription/providers/codex/driver_test.gointernal/subscription/providers/grok/driver.gointernal/subscription/providers/grok/driver_test.gointernal/subscription/providers/grok/grok.gointernal/subscription/runtime/runtime.gothird_party/cpaembedded/embedded/antigravity_oauth.gothird_party/cpaembedded/embedded/antigravity_test.gothird_party/cpaembedded/embedded/claude_oauth.gothird_party/cpaembedded/embedded/claude_test.gothird_party/cpaembedded/embedded/embedded.gothird_party/cpaembedded/embedded/embedded_test.gothird_party/cpaembedded/embedded/grok.gothird_party/cpaembedded/embedded/grok_oauth.gothird_party/cpaembedded/embedded/grok_test.gothird_party/cpaembedded/embedded/oauth_retry_after.gothird_party/cpaembedded/embedded/oauth_retry_after_test.go
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d00cc1031
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 87bbeabbb9
ℹ️ 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".
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: QUIET
Plan: Pro Plus
Run ID: e343e649-dceb-4182-bbad-1e06a2d94c43
📒 Files selected for processing (6)
internal/control/service.gointernal/gateway/handler.gointernal/state/registry.gointernal/subscription/credential_manager.gointernal/subscription/credential_manager_test.gointernal/subscription/runtime/runtime.go
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a4f48d6c7
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2b210cbe9
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f0ea52ddf
ℹ️ 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".
| if !bypassedCooldown.IsZero() { | ||
| manager.registry.ClearCooldownIfMatch(row.ID, bypassedCooldown) |
There was a problem hiding this comment.
Preserve unrelated cooldowns after manual refresh
When a credential is cooling down because the model endpoint returned 429 or another health decision set EffectCooldownCredential, a successful control-plane token refresh reaches this code with that same shared deadline in bypassedCooldown. ClearCooldownIfMatch cannot distinguish model-request cooldowns from token-refresh cooldowns, so clicking “refresh credential” clears the upstream model cooldown and makes the credential immediately selectable again, potentially violating its Retry-After. Track cooldown provenance or clear only deadlines created by token-refresh failures.
Useful? React with 👍 / 👎.
关联 Issue / Related Issue
无
变更内容 / Change Content
Bug 修复 / Bug fix
新功能 / New feature
其他改动 / Other changes
区分 OAuth Token 端点的临时失败、确定失效与结果未知,避免明确的 429/5xx 等临时响应将订阅凭据永久锁定。
临时失败时恢复凭据为 ready,数据面冷却当前凭据并切换下一候选,同时保留手动重试能力。
网络中断、成功响应解析失败以及持久化或运行时同步失败继续进入 outcome_unknown,保持 fail closed。
非 ready 凭据不再允许单个或批量刷新,并为临时失败、重新授权和结果未知提供明确提示。
增加不包含 Token、响应正文或原始错误的结构化刷新失败日志,并修复 Grok 非 JSON Token 端点错误的状态识别。
验证:
make checkcd third_party/cpaembedded && go mod tidy -diff && go vet ./... && go test -count=1 ./...兼容性:
CREDENTIAL_REFRESH_TEMPORARILY_UNAVAILABLE。自查清单 / Checklist
make check,或在说明中写明无法运行的原因和未验证范围。 / I ranmake check, or documented why it could not run and what remains unverified.Summary by CodeRabbit
新功能
界面改进