feat: migrate account usage to CLIProxyAPI
Frontend / quality (push) Canceled after 0s

This commit is contained in:
2026-09-08 09:56:08 +08:00
parent 0b2f969c6d
commit 8997886eef
35 changed files with 2778 additions and 1651 deletions
+7 -6
View File
@@ -25,9 +25,10 @@ findings 优先,按 `P0` 至 `P3` 排序。每条必须包含严重级别和
- 匿名端点是否意外扩大;session、过期检查和非只读来源头是否在所有路径生效;cookie 改动是否适配 HTTPS 反代。
- setup 是否事务化且不能覆盖管理员;登录限流是否存在竞态、无限内存或错误信任代理头。
- SQLite migration 是否可从旧 schema 启动且保留数据;查询是否带正确 `account_id`;rows、transaction 和临时文件是否关闭。
- 删除账号是否精确停止 runtime、级联历史并删除正确目录,尤其是账号 1 的旧路径。
- app-server 生命周期是否可能双启动、停止后重启、死锁或由旧进程回调污染新进程;pending 请求在所有结束路径是否释放。
- app-server optional/null、多 bucket、未知套餐和部分接口失败是否降级,而非生成错误数据或清除有效凭据。
- 删除账号是否只删除精确的本地 runtime 和级联历史,且不会调用 CPA 删除凭据或误导用户。
- CPA authIndex 是否在创建/修改前验证唯一、provider、状态和本地重复;失败是否可能留下半绑定账号。
- CPA Management API 是否有 timeout、响应体大小限制、包装状态与上游状态双重校验;错误或日志是否泄露 management key、OAuth token 或原始正文。
- `/wham/*` optional/null、多 bucket、未知套餐和部分接口失败是否按契约降级,而非生成错误数据或清除有效绑定。
- 提醒是否稳定去重、限定六小时重试、正确区分 before/after/detected reset;多渠道部分失败是否按既定语义重试。
- SMTP、Telegram 错误是否有 timeout、TLS 和 HTML 转义;设置接口、日志和错误是否泄露秘密。
- 备份是否包含 committed WAL 且不阻塞写入;文案是否误称数据库快照为完整恢复包。
@@ -35,15 +36,15 @@ findings 优先,按 `P0` 至 `P3` 排序。每条必须包含严重级别和
## 前端专项
- 初始化、未登录、登录态路由是否无闪烁或循环;401 后是否进入可恢复状态。
- 切换或删除账号时,旧 Dashboard、设备码和 localStorage 是否清理;异步旧响应是否覆盖新账号。
- 切换或删除账号时,旧 Dashboard 和 localStorage 是否清理;异步旧响应是否覆盖新账号。
- API 类型是否准确表达 `null`、optional、unknown 和空列表;错误响应是否可能被当作成功。
- 邮箱是否在所有可见位置掩码;服务端文本和外部 URL 是否以安全方式渲染。
- effect、30 秒 polling、设备码 polling、timer 和 event handler 是否在卸载时清理。
- effect、30 秒 polling、timer 和 event handler 是否在卸载时清理。
- 设置 tab 是否保持键盘操作、`inert` 隔离、表单状态、滚动位置和窄屏无溢出。
## 部署与验证专项
- 固定 Go、Node、Codex CLI 和 Playwright 版本是否同步 Dockerfile、lockfile 与文档;架构和静态构建是否匹配运行层。
- 固定 Go、Node 和 Playwright 版本是否同步 Dockerfile、lockfile 与文档;架构和静态构建是否匹配运行层。
- 静态前端是否在 Go build 前正确复制;`.dockerignore` 是否会丢失必须资源或带入运行数据。
- 最终镜像是否继续非 root,`/data` 权限是否兼容 UID `10001`;Compose 升级是否复用原卷。
- 新环境变量是否同步代码、Compose、README 和部署文档;秘密是否可能进入 build arg、镜像层或日志。
+10 -8
View File
@@ -12,17 +12,19 @@
## 数据与账号
- `internal/store/store.go` 是 SQLite schema 和兼容迁移的事实来源。启动迁移必须幂等、保留旧数据并启用 foreign keys。
- 旧单账号数据迁到账号 1;账号 1 的凭据路径永久为 `/data/codex`,不能统一搬到 `accounts/1`。
- 删除账号必须先停止并移除精确 runtime,再删除该账号数据库行和精确凭据目录;不得使用未校验路径、glob 或宽泛递归删除。
- 旧单账号数据及账号 1 历史必须保留;迁移只为旧账号补空 `auth_index`,不得因切换 CPA 删除旧快照。新数据库不再预建空账号。
- 每个非空 CPA `auth_index` 最多绑定一个本地账号。添加或修改绑定前必须验证索引唯一指向未禁用的 Codex auth,失败不得留下半创建或半更新记录;CPA 的 transient unavailable/error 可能表示额度耗尽,不能阻止额度读取。修改到不同 authIndex 时必须原子清除该本地账号的旧用量、限额和提醒历史,禁止串身份。
- 删除账号只删除本地 runtime、数据库行及其级联历史,绝不能调用 CPA 删除凭据或误导用户认为 CPA auth 已删除。
- `daily_usage` 与 `limit_snapshots` 以 `account_id` 隔离。任何查询、更新、提醒 key 或清理不得串账号。
- `expectedKind` 只是校验期望;未知套餐保持 unknown。相同邮箱提示重复不能成为自动合并依据。
## Codex 运行时
## CLIProxyAPI 运行时
- 每账号一套 app-server 和 `CODEX_HOME`。进程存活与协议 ready 是不同状态,初始化失败必须关闭旧进程。
- lifecycle mutex 串行启动/停止,syncing mutex 串行同步和 Dashboard 访问,state mutex 保护 ready/stopped;不得以无锁读写替换。
- 旧子进程晚退出不能断开新子进程或失败新请求。请求取消和 20 秒 timeout 必须清除 pending channel。
- `account/read` 是同步的硬依赖;rate limits 与 usage 是可缺失数据。optional、`null`、多 bucket 和未知字段必须安全降级。
- Codex Helper 不保存、返回或记录 CPA management key、OAuth access token、refresh token 或原始认证文件。公开账号响应必须清空 `authIndex`。
- CPA base URL 和 management key 只从服务端环境读取。未配置不得阻止 setup/login,但所有账号同步必须明确失败并保留旧 Dashboard 为 stale。
- 每账号 `syncing` mutex 继续串行同步和 Dashboard 访问;不得以无锁读写替换。
- auth-files 验证、`api-call` 包装状态和上游状态必须分别检查。请求必须保留超时和响应体大小限制,错误不得包含原始上游正文。
- `/wham/usage` 是额度同步的硬依赖;`/wham/profiles/me` Token 活动和重置卡详情是可缺失数据。optional、`null`、多 bucket、未知套餐和畸形附加限额必须安全降级或产生不泄密的同步错误,Profile 失败不得隐藏有效限额。
## 通知、外部输入与秘密
@@ -33,7 +35,7 @@
## 前端与部署
- Web 界面中的所有可见账号邮箱继续掩码;Telegram `/account` 当前会向已绑定会话显示完整邮箱。账号切换清空旧 Dashboard;删除账号清除设备码和 localStorage 选择。
- Web 界面中的所有可见账号邮箱继续掩码;Telegram `/account` 当前会向已绑定会话显示完整邮箱。账号切换清空旧 Dashboard;删除账号清除 localStorage 选择。公开账号响应不得暴露 CPA authIndex。
- 非活动设置 panel 保持 `inert`,tab 键盘和布局稳定性是现有可访问性契约。
- 前端生产资源嵌入 Go 二进制;Docker build stage 的复制顺序变化必须验证实际嵌入的是新产物。
- `/data` 是唯一完整恢复单元。数据库快照不含 `secret.key` 和 Codex 凭据;任何文档不得暗示其可完整灾难恢复。