mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
feat(settings): enforce minimum client versions
Add configurable minimum versions for Codex Desktop and CLI, return 426 for unsupported recognized clients, and provide install and Windows offline download guidance. Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
+55
@@ -17,6 +17,28 @@ Client Key 通过账号分组限定路由范围:未绑定分组时可使用全
|
||||
已启用分组成员的并集。分组可以混合 `openai` 与 `xai` 账号;同一请求只会在模型能力明确匹配且满足
|
||||
重放安全边界时跨 Provider fallback。
|
||||
|
||||
运行设置可以分别配置 `minCodexDesktopVersion` 与 `minCodexCliVersion`。两者只接受 SemVer,`null`
|
||||
表示不限制。API 在 Client Key 鉴权成功后识别官方 Desktop/CLI 请求头;已识别客户端没有合法版本,或版本
|
||||
低于对应门槛时,所有 `/v1/*` HTTP 请求和新 WebSocket 握手在访问上游前返回 `426 Upgrade Required`。
|
||||
未知客户端保持兼容,不应用版本门禁。
|
||||
|
||||
低版本响应使用 OpenAI 风格错误合同:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "Codex CLI 0.151.0 is below the minimum required version 0.152.0. Upgrade Codex CLI and retry.",
|
||||
"type": "invalid_request_error",
|
||||
"code": "client_version_too_old",
|
||||
"client": "codex_cli",
|
||||
"current_version": "0.151.0",
|
||||
"min_version": "0.152.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
已识别但缺失或携带非法版本时,`code` 为 `client_version_unavailable`,`current_version` 为 `null`。
|
||||
|
||||
### 管理接口
|
||||
|
||||
除登录、会话状态和登出外,所有 `/api/admin/*` 请求都需要以下任一鉴权方式:
|
||||
@@ -375,6 +397,7 @@ PostgreSQL 或 Redis。管理端只在用户打开弹窗或点击刷新时调用
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/admin/settings` | 读取运行设置 |
|
||||
| `POST` | `/api/admin/settings/update` | 原子替换全部运行设置 |
|
||||
| `GET` | `/api/admin/settings/client-downloads/codex-desktop/windows` | 提取 Codex Desktop Windows 离线安装直链;`refresh=true` 强制刷新进程内短缓存 |
|
||||
| `GET` | `/api/admin/settings/admin-api-key` | 只返回管理 API Key 是否存在 |
|
||||
| `POST` | `/api/admin/settings/admin-api-key/delete` | 删除管理 API Key |
|
||||
| `POST` | `/api/admin/settings/admin-api-key/regenerate` | 重新生成并一次性返回完整管理 API Key |
|
||||
@@ -388,12 +411,44 @@ refreshConcurrency
|
||||
maxConcurrentPerAccount
|
||||
requestIntervalMs
|
||||
rotationStrategy
|
||||
minCodexDesktopVersion
|
||||
minCodexCliVersion
|
||||
usageRetentionDays
|
||||
opsEventRetentionDays
|
||||
auditRetentionDays
|
||||
```
|
||||
|
||||
`rotationStrategy` 可取 `smart`、`quota_reset_priority`、`round_robin`、`sticky`。
|
||||
两个 `minCodex*Version` 字段为 `string | null`,只设置最低版本,不存在最大版本字段。
|
||||
|
||||
Windows 离线包接口固定解析 Microsoft Store Product ID `9PLM9XGG6VKS` 的 Retail 包,不接受调用方提供
|
||||
产品 ID、上游地址、ring 或文件名。后端只返回通过包名、架构、Microsoft CDN host/path、scheme 和失效
|
||||
时间校验的 `x64` / `arm64` MSIX 直链,不代理安装包字节。Store 内容通道返回 HTTP/80 临时地址时保留
|
||||
原始 scheme,不强制改写为该 host 不保证支持的 HTTPS。动态链接不足 10 分钟即失效时不会下发;某个架构
|
||||
解析失败时只将该架构降级到 OpenAI 官方 HTTPS 稳定 MSIX,并通过 `warning` 说明。响应形状为:
|
||||
|
||||
```json
|
||||
{
|
||||
"resolvedAt": "2026-09-01T06:30:00Z",
|
||||
"cached": false,
|
||||
"warning": null,
|
||||
"packages": [
|
||||
{
|
||||
"architecture": "x64",
|
||||
"source": "microsoft_store",
|
||||
"version": "26.825.6671.0",
|
||||
"fileName": "OpenAI.Codex_26.825.6671.0_x64__2p2nqsd0c76g0.msix",
|
||||
"sizeBytes": 744250000,
|
||||
"downloadUrl": "http://dl.delivery.mp.microsoft.com/filestreamingservice/files/...",
|
||||
"expiresAt": "2026-09-01T07:30:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`source` 为 `microsoft_store` 或 `official_openai`。Store 的四段 package version 只用于下载展示,不参与
|
||||
Desktop 三段 SemVer 门禁,也不会自动回写最低版本设置。完整安全与回退设计见
|
||||
[客户端最低版本与下载方案](client-min-version-plan.md)。
|
||||
|
||||
## 9. 备份
|
||||
|
||||
|
||||
+13
-1
@@ -43,6 +43,8 @@ flowchart LR
|
||||
Store --> Object[(S3 / R2)]
|
||||
|
||||
Host[gateway-host] -. lifecycle / workers / update .-> API
|
||||
Host -. lazy client distribution resolver .-> Admin
|
||||
Host --> StoreLinks[RG-Adguard / Microsoft CDN]
|
||||
```
|
||||
|
||||
`backend/apps/gateway` 是唯一组合根,按 Host → Store → Provider → Core → Admin → API → Worker 的顺序
|
||||
@@ -95,9 +97,14 @@ sequenceDiagram
|
||||
E->>S: enqueue terminal observation and accounting
|
||||
```
|
||||
|
||||
请求开始时冻结 `RuntimeSnapshot`、Client Key 的账号范围、模型映射、Provider 候选顺序和调度策略。
|
||||
请求开始时冻结 `RuntimeSnapshot`、Client Key 的账号范围、模型映射、Codex 客户端最低版本、Provider
|
||||
候选顺序和调度策略。
|
||||
运行中的请求不再拼接新旧配置,也不在热路径查询分组关系。
|
||||
|
||||
Client Key 鉴权完成后,API adapter 从有界请求头识别 Codex Desktop/CLI,Core 使用同一请求冻结的
|
||||
`RuntimeSnapshot` 比较对应最低版本。Desktop 优先于其 User-Agent 内嵌的 CLI/Core 标记;未知客户端不
|
||||
应用门禁。低版本或已识别但版本不可用时,在进入 Provider 前返回稳定的 `426` 合同。
|
||||
|
||||
核心不变量:
|
||||
|
||||
- 一个客户端请求对应一条 `model_requests`;attempt 是请求内事实,不建立第二张权威表。
|
||||
@@ -190,6 +197,7 @@ PostgreSQL 周期对账才是正确性基础。
|
||||
| 日志、OAuth 恢复记录、在线更新状态、备份暂存 | `.runtime/` | 部署节点本地运行文件 |
|
||||
| 重置卡库存与消费结果 | OpenAI upstream | 后端不建立本地卡库存;前端只保留当前浏览器会话的最近查询 |
|
||||
| Provider 公开模型与请求画像 | Provider/runtime cache | 由官方目录或发布源刷新,不写成第二份业务配置 |
|
||||
| Windows 安装包临时直链 | Host 进程内短缓存 | 按需解析、严格校验、到期前丢弃;不写 PostgreSQL/Redis,也不代理包字节 |
|
||||
|
||||
账号对外状态不是独立列,而是 PostgreSQL credential/quota 事实与 Redis cooldown 的统一投影:
|
||||
`normal`、`quota_exhausted`、`rate_limited`、`disabled`、`error`。只有明确上游证据才能恢复或终态化账号,
|
||||
@@ -237,6 +245,10 @@ Worker 由各 Bundle 贡献、由 Host 统一监督:
|
||||
|
||||
启动只有在配置、PostgreSQL、Redis、Provider、Core、Admin、API 和 Worker 全部初始化成功后才进入服务。
|
||||
健康检查综合 Core、Store 与 Worker 状态,但不会把单个 Provider 的业务降级等同于整个进程失活。
|
||||
组合根在启动时只把 Host 的 `ClientDistributionResolver` 能力注入 Admin;此时不访问 RG-Adguard,下载
|
||||
HTTP Client 构造失败也不会阻断网关启动。外部解析在已认证管理员首次打开客户端下载弹窗时惰性执行,
|
||||
失败时按架构使用 OpenAI 官方稳定地址。Microsoft Store 内容通道返回的 HTTP/80 临时链接保留原始 scheme,
|
||||
不会被错误改写到该 host 不保证支持的 HTTPS 虚拟主机。
|
||||
|
||||
关闭分为两段:先停止接收新连接并 drain HTTP/WS,再取消并等待 Worker;两段各有独立预算,Compose 的
|
||||
`stop_grace_period` 必须覆盖二者之和。超时后只丢弃仍未落盘的可恢复观测,不执行隐式业务重放。
|
||||
|
||||
Reference in New Issue
Block a user