Skip to content

chore: update Codex channel - #5461

Merged
seefs001 merged 7 commits into
QuantumNous:mainfrom
seefs001:fix/codex-auth-modal
Jun 12, 2026
Merged

chore: update Codex channel#5461
seefs001 merged 7 commits into
QuantumNous:mainfrom
seefs001:fix/codex-auth-modal

Conversation

@seefs001

@seefs001 seefs001 commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)

  • 移除ChatGPT OAuth 授权工具,用户未来需要自己手动通过别的方式提取access_token。
  • 更新渠道名称为 ChatGPT Subscription (Codex)
  • 补充新版本前端对Codex渠道类型的禁止多密钥模式逻辑
  • 补充新版本前端对Codex渠道的警告标识

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

(请在此粘贴截图、关键日志或测试报告,以证明变更生效)

Summary by CodeRabbit

  • New Features

    • Added credential refresh endpoint and UI flow for Codex channels
    • Added Codex channel usage reporting endpoint
  • Changes

    • Renamed Codex channel display to "ChatGPT Subscription (Codex)"
    • Removed the multi-step OAuth authorization UI and replaced it with a direct credential refresh workflow (API surface updated)
    • Updated channel configuration UI, table column behavior, and provider badge rendering
    • Revised translations across locales and adjusted i18n sync handling

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a54a35d3-5e1a-4b36-88c7-c6e3d19956bb

📥 Commits

Reviewing files that changed from the base of the PR and between 829b510 and c97ca7e.

📒 Files selected for processing (8)
  • web/default/src/components/provider-badge.tsx
  • web/default/src/features/channels/components/channels-columns.tsx
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json

Walkthrough

This PR removes the Codex OAuth two-step authorization flow and replaces it with a credential refresh mechanism. Backend OAuth exchange and PKCE/state logic are removed; new admin endpoints for credential refresh and usage were added. Frontends remove OAuth UI/components, add direct refresh actions, and update channel branding and i18n to "ChatGPT Subscription (Codex)".

Changes

Codex OAuth Removal & Credential Refresh Migration

Layer / File(s) Summary
Backend OAuth Service Removal & Endpoint Addition
service/codex_oauth.go, router/api-router.go, constant/channel.go
Removes authorization-code flow types and helpers, PKCE/state generation, and authorization URL builders. Switches JWT unmarshaling to common.Unmarshal. Adds admin-protected channel endpoints: POST /:id/codex/refresh and GET /:id/codex/usage. Updates channel type label to "ChatGPT Subscription (Codex)".
Classic Frontend: OAuth Modal Removal & Credential Refresh
web/classic/src/components/table/channels/modals/EditChannelModal.jsx, web/classic/src/constants/channel.constants.js
Removes CodexOAuthModal import and modal state; introduces handleRefreshCodexCredential that posts to the new refresh endpoint and shows success/error toasts. Replaces OAuth trigger with an edit-only "刷新凭证" button and updates channel label.
Default Frontend: OAuth API & Components Removal
web/default/src/features/channels/api.ts, web/default/src/features/channels/components/dialogs/codex-oauth-dialog.tsx, web/default/src/features/channels/constants.ts
Deletes Codex OAuth API types and functions (startCodexOAuth, completeCodexOAuth) and removes CodexOAuthDialog component. Updates channel type label to "ChatGPT Subscription (Codex)".
Default Frontend: Drawer Multi-Key Support & Credential Refresh UI
web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx
Adds per-type multi-key add-mode support (supportsMultiKeyAddMode, addModeOptions) and an effect to enforce single-key mode when unsupported. Uses watched vertexKeyType for Vertex UI. Replaces prior Codex authorization UI with simplified text and an amber personal-use disclaimer alert.
Classic Frontend: i18n Updates
web/classic/src/i18n/locales/*
Removes authorization/OAuth-related translation keys and multi-step authorization instructions across classic frontend locale files (en, fr, ja, ru, vi, zh-CN, zh-TW).
Default Frontend: i18n Updates & Sync Script
web/default/src/i18n/locales/*, web/default/scripts/sync-i18n.mjs
Updates default frontend locale files to add "ChatGPT Subscription (Codex)", add a disclaimer, replace generic "Callback URL" with specific callback-related keys, remove OAuth keys, and update the i18n sync script to treat the new label as a brand literal.
UI tweaks
web/default/src/components/provider-badge.tsx, web/default/src/features/channels/components/channels-columns.tsx
Refactors ProviderBadge layout and wraps Type column ProviderBadge in a tooltip; increases Type column width to accommodate longer labels.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A rabbit trims the OAuth vine with care,
Replaces loops with one refreshing air,
Labels gleam anew, dialogs tucked away,
Credentials refreshed — a simpler day,
Hooray for ChatGPT Subscription (Codex)! 🐰✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'chore: update Codex channel' is vague and generic, using non-specific language that doesn't convey the substantive changes being made. Use a more descriptive title that reflects the main changes, such as 'chore: remove Codex OAuth flow and rename to ChatGPT Subscription' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx (1)

725-742: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the revealed key after a successful Codex refresh.

On success you invalidate the detail query, but channelKey is left untouched. If the user had already revealed the current key, the drawer keeps showing and copying the pre-refresh credential from lines 1947-2000 even though /codex/refresh has rotated it. That makes the new refresh action immediately serve stale data.

💡 Suggested fix
   const handleRefreshCodexCredential = useCallback(async () => {
     if (!channelId) return
     setIsCodexCredentialRefreshing(true)
     try {
       const res = await refreshCodexCredential(channelId)
       if (!res.success) {
         throw new Error(res.message || t('Failed to refresh credential'))
       }
+      setChannelKey(null)
       toast.success(t('Credential refreshed'))
       queryClient.invalidateQueries({
         queryKey: channelsQueryKeys.detail(channelId),
       })

If you want to keep the field populated, re-fetch it behind the existing secure-verification flow instead of reusing the old revealed value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`
around lines 725 - 742, handleRefreshCodexCredential currently refreshes the
Codex credential but leaves the revealed channelKey state intact, causing the UI
to continue showing/copying the old credential; update the handler to clear any
revealed key state after a successful refresh by resetting the channelKey (or
the state variable that holds the revealed credential) and any related
"revealed" boolean flag so the UI requires re-reveal or refetch, and ensure this
uses the same secure-verification flow that normally populates the key
(referencing handleRefreshCodexCredential, channelKey and the reveal/copy
handlers) and still invalidates the detail query via
queryClient.invalidateQueries.
service/codex_oauth.go (1)

77-81: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve upstream error details on refresh failures.

This decodes the success payload before checking resp.StatusCode, so a non-2xx response can collapse into a generic status=<code> error or a JSON decode error. With the authorization-code flow removed, this refresh path is now the only way to recover Codex credentials, so losing the upstream error body will make invalid/expired refresh tokens much harder to diagnose.

💡 Suggested fix
+import "io"
+
-	if err := common.DecodeJson(resp.Body, &payload); err != nil {
-		return nil, err
-	}
-	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
-		return nil, fmt.Errorf("codex oauth refresh failed: status=%d", resp.StatusCode)
-	}
+	body, err := io.ReadAll(io.LimitReader(resp.Body, 4096))
+	if err != nil {
+		return nil, err
+	}
+	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+		return nil, fmt.Errorf(
+			"codex oauth refresh failed: status=%d body=%s",
+			resp.StatusCode,
+			strings.TrimSpace(string(body)),
+		)
+	}
+	if err := common.Unmarshal(body, &payload); err != nil {
+		return nil, err
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@service/codex_oauth.go` around lines 77 - 81, The code decodes the response
body into payload before checking resp.StatusCode, which can lose upstream error
details; change the flow in the Codex refresh path so you first read the full
resp.Body into bytes (e.g., ioutil.ReadAll or io.ReadAll), then if
resp.StatusCode is not 2xx return an error that includes both the status code
and the response body bytes for debugging, and only on a 2xx status decode those
bytes into payload using common.DecodeJson (or decode from the already-read
bytes). Update the logic around resp, payload, and common.DecodeJson accordingly
so non-2xx bodies are preserved in the returned error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/default/src/i18n/locales/fr.json`:
- Line 1211: The French translation value for the long disclaimer JSON key is
missing several diacritics; update the value string for the key "Disclaimer:
Personal use only. Do not distribute or share any credentials. This channel has
prerequisites and requires prior setup; use it only if you understand the flow
and risks, and comply with OpenAI's terms and policies. Credentials and
configuration are for Codex CLI integration only, and are not intended for any
other client, platform, or channel." to correct accents (e.g., change
"prerequis" → "prérequis", "necessite" → "nécessite", "prealable" → "préalable",
"procedure" → "procédure", "reserves" → "réservés", "destines" → "destinés") so
the user-facing French string uses proper diacritics throughout.

---

Outside diff comments:
In `@service/codex_oauth.go`:
- Around line 77-81: The code decodes the response body into payload before
checking resp.StatusCode, which can lose upstream error details; change the flow
in the Codex refresh path so you first read the full resp.Body into bytes (e.g.,
ioutil.ReadAll or io.ReadAll), then if resp.StatusCode is not 2xx return an
error that includes both the status code and the response body bytes for
debugging, and only on a 2xx status decode those bytes into payload using
common.DecodeJson (or decode from the already-read bytes). Update the logic
around resp, payload, and common.DecodeJson accordingly so non-2xx bodies are
preserved in the returned error.

In
`@web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx`:
- Around line 725-742: handleRefreshCodexCredential currently refreshes the
Codex credential but leaves the revealed channelKey state intact, causing the UI
to continue showing/copying the old credential; update the handler to clear any
revealed key state after a successful refresh by resetting the channelKey (or
the state variable that holds the revealed credential) and any related
"revealed" boolean flag so the UI requires re-reveal or refetch, and ensure this
uses the same secure-verification flow that normally populates the key
(referencing handleRefreshCodexCredential, channelKey and the reveal/copy
handlers) and still invalidates the detail query via
queryClient.invalidateQueries.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e48fca13-8189-4788-937f-544825c888b0

📥 Commits

Reviewing files that changed from the base of the PR and between 27b2b2c and f7ca72d.

📒 Files selected for processing (25)
  • constant/channel.go
  • controller/codex_oauth.go
  • router/api-router.go
  • service/codex_oauth.go
  • web/classic/src/components/table/channels/modals/CodexOAuthModal.jsx
  • web/classic/src/components/table/channels/modals/EditChannelModal.jsx
  • web/classic/src/constants/channel.constants.js
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/ja.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/zh-TW.json
  • web/default/scripts/sync-i18n.mjs
  • web/default/src/features/channels/api.ts
  • web/default/src/features/channels/components/dialogs/codex-oauth-dialog.tsx
  • web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx
  • web/default/src/features/channels/constants.ts
  • web/default/src/i18n/locales/en.json
  • web/default/src/i18n/locales/fr.json
  • web/default/src/i18n/locales/ja.json
  • web/default/src/i18n/locales/ru.json
  • web/default/src/i18n/locales/vi.json
  • web/default/src/i18n/locales/zh.json
💤 Files with no reviewable changes (13)
  • web/classic/src/components/table/channels/modals/CodexOAuthModal.jsx
  • web/default/src/features/channels/components/dialogs/codex-oauth-dialog.tsx
  • controller/codex_oauth.go
  • router/api-router.go
  • web/classic/src/i18n/locales/zh-TW.json
  • web/default/src/features/channels/api.ts
  • web/classic/src/components/table/channels/modals/EditChannelModal.jsx
  • web/classic/src/i18n/locales/vi.json
  • web/classic/src/i18n/locales/ru.json
  • web/classic/src/i18n/locales/en.json
  • web/classic/src/i18n/locales/fr.json
  • web/classic/src/i18n/locales/zh-CN.json
  • web/classic/src/i18n/locales/ja.json

"Discount rate must be greater than 0": "Le taux de remise doit être supérieur à 0",
"Discount Rate:": "Taux de réduction :",
"Discount ratio for cache hits.": "Ratio de réduction pour les accès au cache.",
"Disclaimer: Personal use only. Do not distribute or share any credentials. This channel has prerequisites and requires prior setup; use it only if you understand the flow and risks, and comply with OpenAI's terms and policies. Credentials and configuration are for Codex CLI integration only, and are not intended for any other client, platform, or channel.": "Avertissement : usage personnel uniquement. Ne distribuez ni ne partagez aucun identifiant. Ce canal a des prerequis et necessite une configuration prealable ; utilisez-le uniquement si vous comprenez la procedure et les risques, et respectez les conditions et politiques d'OpenAI. Les identifiants et la configuration sont reserves a l'integration Codex CLI et ne sont pas destines a d'autres clients, plateformes ou canaux.",

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix French diacritics in the disclaimer copy.

The new translation has several missing accents in user-facing legal text, which degrades localization quality (e.g., prérequis, nécessite, préalable, procédure, réservés, destinés).

Suggested text update
-    "Disclaimer: Personal use only. Do not distribute or share any credentials. This channel has prerequisites and requires prior setup; use it only if you understand the flow and risks, and comply with OpenAI's terms and policies. Credentials and configuration are for Codex CLI integration only, and are not intended for any other client, platform, or channel.": "Avertissement : usage personnel uniquement. Ne distribuez ni ne partagez aucun identifiant. Ce canal a des prerequis et necessite une configuration prealable ; utilisez-le uniquement si vous comprenez la procedure et les risques, et respectez les conditions et politiques d'OpenAI. Les identifiants et la configuration sont reserves a l'integration Codex CLI et ne sont pas destines a d'autres clients, plateformes ou canaux.",
+    "Disclaimer: Personal use only. Do not distribute or share any credentials. This channel has prerequisites and requires prior setup; use it only if you understand the flow and risks, and comply with OpenAI's terms and policies. Credentials and configuration are for Codex CLI integration only, and are not intended for any other client, platform, or channel.": "Avertissement : usage personnel uniquement. Ne distribuez ni ne partagez aucun identifiant. Ce canal a des prérequis et nécessite une configuration préalable ; utilisez-le uniquement si vous comprenez la procédure et les risques, et respectez les conditions et politiques d'OpenAI. Les identifiants et la configuration sont réservés à l'intégration Codex CLI et ne sont pas destinés à d'autres clients, plateformes ou canaux.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Disclaimer: Personal use only. Do not distribute or share any credentials. This channel has prerequisites and requires prior setup; use it only if you understand the flow and risks, and comply with OpenAI's terms and policies. Credentials and configuration are for Codex CLI integration only, and are not intended for any other client, platform, or channel.": "Avertissement : usage personnel uniquement. Ne distribuez ni ne partagez aucun identifiant. Ce canal a des prerequis et necessite une configuration prealable ; utilisez-le uniquement si vous comprenez la procedure et les risques, et respectez les conditions et politiques d'OpenAI. Les identifiants et la configuration sont reserves a l'integration Codex CLI et ne sont pas destines a d'autres clients, plateformes ou canaux.",
"Disclaimer: Personal use only. Do not distribute or share any credentials. This channel has prerequisites and requires prior setup; use it only if you understand the flow and risks, and comply with OpenAI's terms and policies. Credentials and configuration are for Codex CLI integration only, and are not intended for any other client, platform, or channel.": "Avertissement : usage personnel uniquement. Ne distribuez ni ne partagez aucun identifiant. Ce canal a des prérequis et nécessite une configuration préalable ; utilisez-le uniquement si vous comprenez la procédure et les risques, et respectez les conditions et politiques d'OpenAI. Les identifiants et la configuration sont réservés à l'intégration Codex CLI et ne sont pas destinés à d'autres clients, plateformes ou canaux.",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/default/src/i18n/locales/fr.json` at line 1211, The French translation
value for the long disclaimer JSON key is missing several diacritics; update the
value string for the key "Disclaimer: Personal use only. Do not distribute or
share any credentials. This channel has prerequisites and requires prior setup;
use it only if you understand the flow and risks, and comply with OpenAI's terms
and policies. Credentials and configuration are for Codex CLI integration only,
and are not intended for any other client, platform, or channel." to correct
accents (e.g., change "prerequis" → "prérequis", "necessite" → "nécessite",
"prealable" → "préalable", "procedure" → "procédure", "reserves" → "réservés",
"destines" → "destinés") so the user-facing French string uses proper diacritics
throughout.

@seefs001
seefs001 merged commit 1292b8b into QuantumNous:main Jun 12, 2026
1 check was pending
yangshare added a commit to yangshare/new-api that referenced this pull request Jun 16, 2026
合并上游 QuantumNous/new-api v1.0.0-rc.11,主要新增 Claude Opus 4.8、
OpenAI 图片流式中继、渠道粘性清空选项、安全审计日志、模型定价双栏重构、
Dialog prop-based API 重构。

冲突解决(20 文件):
- 13 个 dialog 采用上游新结构,保留 dev sm: 响应式前缀与 ESLint 注释
- common-logs-columns / details-dialog 的 multikey 徽章功能完整保留
- channels-table 采用上游 useDebouncedColumnFilter
- model-pricing-sheet / model-ratio-visual-editor 采用 upstream 版本
- codex-oauth-dialog 删除(跟随上游 QuantumNous#5461)

撞车修复核对通过:视频任务 GET 验证(QuantumNous#4834/QuantumNous#5133)、匿名请求体限制(QuantumNous#5244)
逻辑均正确保留,无重复。

验证:前端 typecheck + 生产 build 通过,后端 go build 通过,i18n 全语言对齐。
kavoj added a commit to kavoj/35sz-api that referenced this pull request Jul 9, 2026
## 背景

newpay 分支 /channels 编辑抽屉里 Codex 渠道类型(type=57)已经显示
"Authorize" 按钮和 CodexOAuthDialog,前端会 POST 到:

- /api/channel/codex/oauth/start
- /api/channel/codex/oauth/complete

但从 git 历史查证,主分支 commit 1292b8b "chore: update Codex channel
(QuantumNous#5461)"(Jun 12 2026)**删除了**这两条路由以及对应 handler
`controller/codex_oauth.go`(247 LOC)与 `service/codex_oauth.go` 中
的 OAuth 授权流程函数。newpay 通过 4df4a8c 主动恢复了前端的
codex-oauth-dialog.tsx 与 api.ts 里的 startCodexOAuth /
completeCodexOAuth 导出,但**后端 handler 一直没有回来**,导致点击
Authorize 按钮时收到 404,Codex OAuth 授权在 newpay 上无法真正跑通。

## 修复

从 1292b8b^ 的历史快照恢复:

1. **controller/codex_oauth.go**(新增 247 LOC):包含
   - StartCodexOAuth / CompleteCodexOAuth(无渠道 ID,创建新渠道时使用)
   - StartCodexOAuthForChannel / CompleteCodexOAuthForChannel(已有渠道刷新使用)
   - codexOAuthSessionKey / parseCodexAuthorizationInput 工具函数

2. **service/codex_oauth.go**(170 → 317 LOC)恢复被 1292b8b 清理掉的:
   - CodexOAuthAuthorizationFlow 类型
   - CreateCodexOAuthAuthorizationFlow(发起 PKCE 流程)
   - ExchangeCodexAuthorizationCode / WithProxy(用 code+verifier 换 token)
   - buildCodexAuthorizeURL / createStateHex / generatePKCEPair 支持函数
   - 常量:codexOAuthAuthorizeURL、codexOAuthRedirectURI、codexOAuthScope

3. **router/channel-router.go** 注册 4 条路由,权限 = ChannelSensitiveWrite
   (AdminAuth 已在 registerChannelRoutes 中间件层强制):
   - POST /api/channel/codex/oauth/start
   - POST /api/channel/codex/oauth/complete
   - POST /api/channel/:id/codex/oauth/start
   - POST /api/channel/:id/codex/oauth/complete

## 依赖

复用现有:
- github.com/gin-contrib/sessions(main.go:197 已在全局注册 session 中间件)
- relay/channel/codex.OAuthKey(未被 1292b8b 删除,仍在库中)
- 会话存储、AdminAuth 中间件、authz.ChannelSensitiveWrite 权限

## 验证

- go build ./... 通过
- go test ./... 全部通过(controller/service/router 无回归)
- 前端 /api/channel/codex/oauth/start 现在会命中路由(原来 404),
  实际授权走 OpenAI 官方 https://auth.openai.com/oauth/authorize + PKCE 流程

## AI 辅助生成说明

本提交由 AI 辅助生成(Claude Code)从历史 commit 回捡代码后合并。

Co-Authored-By: Claude <noreply@anthropic.com>
ruanhangjian pushed a commit to ruanhangjian/new-api that referenced this pull request Jul 11, 2026
zhaodechao2008 pushed a commit to zhaodechao2008/new-api that referenced this pull request Jul 27, 2026
330079598 pushed a commit to 330079598/new-api that referenced this pull request Aug 19, 2026
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.

1 participant