## 后端变更 - 删除 21 个 sora_*.go 服务文件(service/handler/repository/routes) - 删除 Sora 相关 migration 文件(046/047/063/090) - 清理 config 中的 sora_* 配置项和平台常量 - 清理 wire 依赖注入中的 Sora 组件 - 修复 wire_gen.go 语法错误(缺少逗号和闭合括号) - 移除 go.mod 中的 go-sora2api 依赖 - 更新 ent schema usage_log.go 注释 ## 前端变更 - 删除 SoraView、SoraAdminView 及 8 个 Sora 子组件 - 删除 sora API 层和路由配置 - 清理 UserEditModal 中的 Sora 存储配额 UI - 清理 types/index.ts 中 Sora 相关类型定义 - 清理 stores/app.ts 默认配置 - 清理 i18n 翻译文件 en.ts/zh.ts (~110 行) - 更新相关测试文件 ## 文档更新 - README.md / README_CN.md / README_JA.md: 移除 Sora 状态说明和配置段落 - PROJECT_DIFF.md: 移除 Sora 相关差异描述 ## 验证结果 - ✅ Go 编译通过 (go build ./...) - ✅ TypeScript 类型检查通过 (vue-tsc --noEmit) - ✅ 后端测试全通过 (0 failures) - ✅ 前端测试全通过 (59 files, 329 tests, 0 failures) - ✅ 前端生产构建成功 (23.81s)
12 KiB
Sub2API 架构评审报告
评审人: 高见远(架构师)
评审日期: 2026-05-08
工作目录: d:/project/sub2api-merge
评审范围: 模型支持链路、新增模块代码质量、安全审计、合并一致性、上线风险评估
一、模型支持矩阵
| 模型/平台 | 端点 | 路由文件 | 转发服务 | 账号选择器 | 粘性会话 | 模型映射 | 状态 |
|---|---|---|---|---|---|---|---|
| Claude (Anthropic) | /v1/messages |
routes/gateway.go:44 |
GatewayService.Messages |
SelectAccountWithLoadAwareness |
Redis (sessionHash+groupID) |
账号级 model_mapping + 通配符 |
正常 |
| Claude (Anthropic) | /v1/messages/count_tokens |
routes/gateway.go:52 |
GatewayService.CountTokens |
同上 | 同上 | 同上 | 正常 |
| Claude (Anthropic) | /v1/models |
routes/gateway.go:65 |
GatewayService.Models |
N/A | N/A | 缓存 15s | 正常 |
| OpenAI GPT/Codex | /v1/chat/completions |
routes/gateway.go:84 |
OpenAIGatewayService.ChatCompletions |
OpenAIGatewayService.selectAccount |
Redis (openai:+sessionHash) |
resolveOpenAIForwardModel |
正常 |
| OpenAI GPT/Codex | /v1/responses |
routes/gateway.go:68 |
OpenAIGatewayService.Responses |
同上 | 同上 | codexModelMap 硬编码映射 |
正常 |
| OpenAI GPT/Codex | /responses (无v1) |
routes/gateway.go:116 |
OpenAIGatewayService.Responses |
同上 | 同上 | 同上 | 正常 |
| Gemini (Google) | /v1beta/models/* |
routes/gateway.go:102 |
GeminiMessagesCompatService |
SelectAccountWithLoadAwareness |
Redis (gemini:+sessionHash) |
账号级映射 | 正常 |
| Gemini (Google) | /v1beta/models/:model |
routes/gateway.go:103 |
GeminiV1BetaGetModel |
N/A | N/A | fallback list | 正常 |
| Antigravity | /antigravity/v1/messages |
routes/gateway.go:141 |
GatewayService.Messages |
SelectAccountWithLoadAwareness |
同上 | DefaultAntigravityModelMapping |
正常 |
| Antigravity | /antigravity/v1beta/models/* |
routes/gateway.go:156 |
GeminiV1BetaModels |
同上 | 同上 | 同上 | 正常 |
| Antigravity | /antigravity/models |
routes/gateway.go:129 |
GatewayService.AntigravityModels |
N/A | N/A | 动态 fetch | 正常 |
| Sora | /v1/sora/* |
routes/sora_client.go |
SoraGatewayService |
SoraAccountService |
N/A | N/A | 正常 |
关键发现
- Claude 4.6 模型已支持:
pkg/claude/constants.go:81已新增claude-opus-4-6和claude-sonnet-4-6。 - Codex 映射完整:
service/openai_codex_transform.go:8的codexModelMap覆盖gpt-5.3-codex全系,包含spark变体。 - Antigravity 默认映射完整:
domain/constants.go:73的DefaultAntigravityModelMapping覆盖 Claude 和 Gemini 白名单,并自动透传gemini-3-flash、gemini-3.1-pro-high/low。 - Sticky Session 双写兼容:OpenAI 粘性会话同时写入新格式 (
xxhash) 和旧格式 (sha256),避免升级后会话丢失。 - 平台隔离正确:
/antigravity/*路由强制使用middleware.ForcePlatform(PlatformAntigravity),不会混入其他平台账号。
二、阻塞问题清单(必须修复才能上线)
🔴 B1. 前端国际化翻译缺失 — 影响所有新管理页面
位置: frontend/src/i18n/locales/zh.ts, en.ts
问题: 运维监控 (admin.ops.*) 和 Sora 管理 (admin.sora.*) 的翻译键在前端 Vue 组件中被大量使用,但完全不存在于 zh.ts 和 en.ts 中。用户访问 /admin/ops 和 /admin/sora 时,页面将显示原始键名或空白文本。
证据:
# 组件大量使用 admin.ops 键
grep -rn "t('admin.ops" frontend/src/views/admin/ops/ | wc -l # > 200 处
# 但翻译文件中完全没有
grep "admin.ops" frontend/src/i18n/locales/zh.ts # 无输出
grep "admin.sora" frontend/src/i18n/locales/zh.ts # 无输出
建议: 立即补全 admin.ops.*、admin.sora.* 的中英文翻译。data-management 路由已废弃(deprecatedAdminFeatures.spec.ts),无需补全。
🔴 B2. 批量修改账号存在跨平台模型映射覆盖风险(DEV_GUIDE.md 坑点 #10)
位置: backend/internal/service/admin_service.go:1726 (BulkUpdateAccounts)
问题: 批量更新接口的 Credentials 字段会直接合并到所有选中账号的 credentials JSONB 中。如果批量选中了 OpenAI + Antigravity 账号,并传入包含 model_mapping 的 Credentials,将导致所有账号的映射被统一覆盖。
代码:
repoUpdates := AccountBulkUpdate{
Credentials: input.Credentials, // 直接合并,无平台过滤
Extra: input.Extra,
}
当前代码仅有混合渠道检查(checkMixedChannelRisk),但未对 model_mapping 内容进行平台隔离校验。这与 DEV_GUIDE.md 坑点 #10 描述的现象完全吻合。
建议: 在 BulkUpdateAccounts 中,当 input.Credentials 包含 model_mapping 且选中账号跨平台时,拒绝操作或按平台分组执行。
三、高风险问题清单(强烈建议修复)
🟡 H1. JWT Secret 强度校验过于宽松
位置: backend/internal/config/config_helpers.go:28
问题: isWeakJWTSecret 仅检查 8 个硬编码弱密码(如 secret、password、123456)。一个 32 位全 a 字符串(aaaaaaaa...)会通过校验,但熵为 0,极易被暴力破解。
建议: 增加最小长度校验(>=32 字符)和字符多样性校验(至少包含大写、小写、数字中的两种)。
🟡 H2. Sora S3 存储存在 SSRF 风险(上游 URL 未校验)
位置: backend/internal/service/sora_s3_storage.go:216 (UploadFromURL)
问题: 该方法从 sourceURL 下载文件并上传到 S3。sourceURL 来自上游 Sora API 的响应,但未经过 URL Allowlist 校验。如果上游被劫持或返回内网地址,可能导致 SSRF。
建议: 在 http.NewRequestWithContext 之前,使用 urlvalidator 或 config.Security.URLAllowlist 对 sourceURL 进行校验,禁止内网 IP 和非 https 协议。
🟡 H3. 前端 confirm() 调用(DEV_GUIDE.md 坑点 #10 提及)
位置: frontend/src/views/admin/SoraAdminView.vue:100
问题: 使用原生 confirm() 弹窗,与整体 UI 风格不一致,且无法国际化。
建议: 替换为项目内置的 ConfirmDialog 组件。
🟡 H4. /admin/data-management 路由已废弃但后端测试仍存在
位置: backend/internal/server/routes/admin_routes_test.go:42
问题: 前端路由测试(deprecatedAdminFeatures.spec.ts)明确断言 /admin/data-management 路由不存在,但后端路由测试仍引用该路径。虽然主路由文件 admin.go 中确实已移除,但测试残留说明清理不彻底。
建议: 清理后端 admin_routes_test.go 中的废弃路径引用,避免测试误导。
四、代码质量评分
| 模块 | 评分 | 说明 |
|---|---|---|
backend/internal/prommetrics/ |
9/10 | 结构清晰,独立包避免循环依赖,指标命名规范。建议补充 metrics_test.go 的覆盖率。 |
backend/internal/service/ops_*.go |
8/10 | 错误处理完善(fail-open 不阻塞网关),批量插入有 fallback,内存限制合理。部分函数过长(>200 行)。 |
backend/internal/service/sora_*.go |
7/10 | 流式上传、panic recovery、S3 客户端缓存均正确。SSRF 风险扣 2 分;DeleteObjects 未使用 S3 BatchDelete API 扣 1 分。 |
backend/internal/handler/admin/ |
8/10 | 路由注册完整,handler 职责分离清晰。部分 handler 缺少边界值校验(如 pageSize > 100 仅在部分接口实现)。 |
frontend/src/views/admin/ops/ |
6/10 | 组件拆分合理,但i18n 翻译完全缺失,导致上线后用户可见部分不可用。扣 4 分。 |
backend/internal/server/routes/ |
9/10 | 路由注册完整,无合并冲突标记。中间件顺序正确(auth -> platform -> handler)。 |
backend/internal/service/wire.go |
9/10 | 新增 Sora、Ops 服务均已正确注入 ProviderSet。依赖关系无循环。 |
五、合并一致性检查
| 检查项 | 结果 | 说明 |
|---|---|---|
| Go 文件合并冲突标记 | 通过 | grep '<<<<<<<' 仅命中注释分隔符,无实际冲突 |
| 后端路由注册 | 通过 | admin.go 中 registerSoraRoutes、registerOpsRoutes 均已注册 |
| 前端路由注册 | 部分通过 | /admin/ops、/admin/sora 已注册;/admin/data-management 已按预期废弃 |
| 国际化翻译 | 不通过 | zh.ts / en.ts 缺少 admin.ops.*、admin.sora.* 键 |
| Wire 依赖注入 | 通过 | wire.go 中 Sora 和 Ops 服务均已注入 |
| 健康检查端点 | 通过 | /health、/ready、/live、/metrics 均已在 common.go 注册 |
| Prometheus 指标暴露 | 通过 | /metrics 使用 prommetrics.Registry,指标定义完整 |
六、安全审计摘要
| 风险点 | 严重程度 | 状态 | 说明 |
|---|---|---|---|
| SQL 注入(ORDER BY) | 低 | 安全 | channel_repo.go:249 使用白名单模式,有安全回退 |
| SQL 注入(动态 SQL) | 低 | 安全 | 所有 ops_repo*.go 使用参数化查询 |
| JWT Secret 管理 | 中 | 需改进 | 弱密码校验列表太短,未校验熵 |
| CORS 配置 | 低 | 安全 | 配置化,默认不允许任意 origin |
| URL Allowlist | 低 | 安全 | 可关闭,但关闭时日志告警 |
| 文件上传/SSRF | 中 | 需改进 | sora_s3_storage.go:216 未校验 sourceURL |
| 批量更新跨平台覆盖 | 高 | 阻塞 | BulkUpdateAccounts 的 Credentials 合并无平台隔离 |
七、上线建议
综合结论: CONDITIONAL(有条件上线)
必须在修复以下阻塞项后方可上线:
- 补全前端 i18n 翻译(
admin.ops.*、admin.sora.*中英文) - 批量更新增加 model_mapping 跨平台保护(或禁止批量修改跨平台账号的 Credentials)
上线前检查清单
- 补全
frontend/src/i18n/locales/zh.ts中admin.ops、admin.sora翻译键 - 补全
frontend/src/i18n/locales/en.ts中admin.ops、admin.sora翻译键 - 修复
BulkUpdateAccounts跨平台 model_mapping 覆盖风险 - 为
sora_s3_storage.UploadFromURL增加 URL 校验 - 考虑增强
isWeakJWTSecret校验逻辑(最小长度 + 字符多样性) - 运行
go test -tags=unit ./...和go test -tags=integration ./...验证 - 运行
golangci-lint run ./...确认无新增问题 - 前端
pnpm build验证通过
附录:关键文件索引
| 文件 | 说明 |
|---|---|
backend/internal/server/routes/gateway.go |
网关路由注册(Claude/OpenAI/Gemini/Antigravity) |
backend/internal/service/gateway_service.go |
核心网关服务(账号选择、粘性会话、转发) |
backend/internal/service/openai_gateway_service.go |
OpenAI 专用网关服务 |
backend/internal/service/openai_sticky_compat.go |
OpenAI 粘性会话双写兼容 |
backend/internal/service/openai_model_mapping.go |
OpenAI 模型映射解析 |
backend/internal/service/admin_service.go:1726 |
批量更新账号(风险点) |
backend/internal/service/account.go:392 |
账号级模型映射缓存与解析 |
backend/internal/domain/constants.go:73 |
Antigravity 默认模型映射 |
backend/internal/pkg/claude/constants.go |
Claude 模型与 Beta Header 常量 |
backend/internal/pkg/openai/constants.go |
OpenAI 模型列表 |
backend/internal/pkg/gemini/models.go |
Gemini fallback 模型列表 |
backend/internal/service/sora_s3_storage.go:216 |
Sora S3 流式上传(SSRF 风险) |
backend/internal/config/config_helpers.go:28 |
JWT Secret 强度校验 |
frontend/src/router/index.ts |
前端路由配置 |
frontend/src/i18n/locales/zh.ts / en.ts |
国际化翻译文件(缺失键) |