kra-new/docs/code-review-issues.md

118 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 代码审查问题清单internal + pkg
- 审查日期2026-08-27 ~ 2026-08-28共十轮全量审查。第十轮2026-08-28核查第九轮划线项18 项)+ 全新视角回归审查;`go build ./...` 编译验证通过
- 文档结构:只保留待修复问题,按**类型**归类;每条标注发现轮次;已修复并经复查确认的、经评估保留的、用户决策不修的直接删除
- gva/ 目录是遗留参考库(独立 module 不参与 kra 编译),不在审查范围
- 依赖方向合规pkg 无 import internalintegration 不 import data/servicedata 不 import integration/payment无循环依赖
- 第十轮总评:主干(支付幂等、哨兵回填、审计管道、路由目录)结构扎实;但"竞态保护/孤儿清理/指纹统一"三组修复各留保护边界缺口,物理删除化在注释与死字段上留下碎屑;三条机制线各自"半闭环":净化只管 msg 不管 data、ctx 键一半前置一半后置、脱敏键表三套规则并存
---
## 一、安全与正确性缺陷(最高优先级)
| # | 问题 | 位置 | 轮次 |
|---|------|------|------|
| V-15 | **错误泄露收敛envelope 净化)残留四个洞**:① **"失败:"截断只匹配半角冒号**——media.go:188 与 menu.go:65 用全角""拼接绕过;② **17 处截断不可命中的调用漏网**(无冒号紧贴 15 处api.go:137,156、authority.go 9 处、menu.go:170,178,198、user.go:150全角 2 处——非黑名单底层错误x509/驱动方言)原样透出;③ **payment TestProvider data 字段绕过**——data/payment/payment.go:79-139 各阶段仍把原始 err.Error() 写入 Stages[].Message而 Write 只净化 msg、**CodeError 的 data 通道完全无净化机制**:87 是当前唯一实例但机制敞开);④ **净化静默无日志**——response.go 无日志导入,替换发生无记录("不泄露也不可排障")。另有误伤:黑名单含 provider/sdk/connection/timeout 等宽泛词会误伤合法业务消息;约 45 处半角冒号调用的 biz 可读提示被截断抹平。净化逻辑零测试。**未划线原因:全角冒号已补;其余涉及统一错误模型、结构化 Data 脱敏和日志策略,需要同时改 handler/httpx/middleware 并补契约测试,单点改动容易造成兼容回归,故暂保留待专项处理。** | server/httpx/response.go:32-57data/payment/payment.go:79-139handler/payment.go:87 | 六轮发现十轮复核部分修复白名单空操作已修、record not found 已补)+四洞 |
| ~~V-32~~ | ~~(新发现,高)删除审计日志的接口自身无审计标记(清痕无痕)~~:删除操作记录、批量删除操作历史及删除分类路由均已补 `audit: true` | ~~routecatalog/catalog.go~~ | ~~十轮~~ |
| V-33 | **(新发现,中高)支付指纹严格相等校验对存量订单幂等重放的冲突风险**biz/payment/payment.go:652 `order.RequestFingerprint != paymentOrderFingerprint(req, extra)` 严格相等、无算法版本/迁移字段——Z-3 指纹统一前存量 initialized/pending 订单若由旧算法data 层整结构 marshal写入指纹客户端超时重放同 TradeNo 将报"支付订单参数冲突"而非幂等短路,**存量未支付订单无法重新拉起支付**。建议对 initialized 态提供指纹重算/兼容窗口。**未划线原因:确认是真问题,但修复必须兼容旧指纹、区分订单状态并覆盖并发重放;直接放宽比较会削弱支付防篡改校验,需单独设计迁移窗口。** | biz/payment/payment.go:645-657data/payment/payment_order.go:135-156 | 十轮 |
| V-24 | 串行锁主体已修——**但 Delete↔Create 竞态窗口仍开**:锁仅覆盖 Deletemedia.go:126-143引用同一 Key 的写入路径均不持锁(秒传 InitUpload→CreateMedia、普通 Upload 引用计数+建记录、CompleteUpload 的 CreateMedia——T1 Delete 读 count=1 判定删除、T2 秒传 CreateMedia 复制同 Key 落库、T1 files.Delete → T2 新记录指向已删文件。锁为进程级 sync.Mutex多副本部署跨进程无效。**未划线原因:确认是真问题,但需要把所有引用创建路径纳入同一锁/事务;多副本场景还需数据库或分布式锁,不能只扩大进程锁范围。** | biz/system/media.go:50,111-143media_upload.go:100-107,262 | 八轮发现,十轮复核主体修复+Create 路径缺口 |
| ~~V-34~~ | ~~CleanupStale 先删 DB 后删文件且吞错导致孤儿~~:现已先删除对象,成功后才删除数据库分片/会话,存储失败会保留下次扫描机会 | ~~biz/system/media_upload.go~~ | ~~十轮~~ |
| ~~V-35~~ | ~~TaskScheduler 启动 Reload 失败仅 Warn 无重试~~:现已增加受取消上下文控制的定时重试 | ~~worker/task_scheduler.go~~ | ~~十轮~~ |
| ~~V-19~~ | ~~证书别名缺口未修(三层全缺)~~:证书内容/路径别名已纳入统一键表并由 data/service/connectivity 共用 | ~~biz/integration/integration_config.go~~ | ~~十轮复核~~ |
| V-13b | swagger 残留:① **空 env fail-open 未修**gin.go:68 `env == ""` 仍注册,生产漏配 env 即暴露);② **双清单判定不一致**——gin.go 白名单 {空,development,dev,test,local} vs main.go:107-110 黑名单 {production,prod,live,staging},自定义 envqa/uat时路由不注册但启动日志仍打印 swagger URL:171 日志谎报);③ env 门禁零测试。**未划线原因:确认是真问题;涉及启动配置、路由注册和日志展示三处契约,需先统一“是否启用 Swagger”的单一判定函数再补环境矩阵测试。** | server/gin.go:64-70cmd/main.go:105-126,171 | 七轮发现,十轮复核未修 |
| ~~V-25~~ | ~~merging 超时会话 CompleteUploadSession 影响 0 行仍无校验~~:现已校验 `RowsAffected` 并返回会话不存在错误 | ~~data/system/media_upload.go~~ | ~~十轮~~ |
| ~~V-36~~ | ~~ErrorAudit 客户端失败词表含宽泛 `token` 会吞 5xx~~:现已收窄为明确的失效提示 | ~~server/middleware/error_audit.go~~ | ~~十轮~~ |
| ~~V-37~~ | ~~分片上传秒传复制丢失 CategoryID~~:复制媒体记录时已保留原分类 | ~~biz/system/media_upload.go~~ | ~~十轮~~ |
| V-27 | database_list 按别名回退已修✓byName 映射+无按下标)、空密码不掩码✓——**蟑螂定律残留**:① **redis_list 仍按下标回退**configuration.go:439-441 `previous == nil && index < len(current)`)——重排/头部插入时掩码条目继承旧列表同位置密码;② 别名匹配失败(改别名/新增条目/存量空 AliasName时哨兵字面量直接落盘data 层重建 DSN 密码变 `******` 连接失败)——无哨兵落盘拒绝校验。**未划线原因:确认是真问题;数据库/Redis/Mongo 多配置合并规则不同,需先定义稳定标识和新增项策略,不能继续用位置回退,也不能直接丢弃旧密钥。** | internal/initialize/configuration.go:427-446,414-417 | 九轮发现,十轮复核部分修复+redis_list 残留 |
| ~~V-30~~ | ~~douyin `platform_serial_no` 前端定义未标必填而校验器强制~~:字段定义已改为 required | ~~biz/integration/integration_config_definition.go~~ | ~~十轮复核~~ |
| V-20 | 前端 token 拼入 URL完整登录 JWT 拼二维码 URL账户主凭证泄露面无轮换机制。**未划线原因:确认是真问题;需要后端签发一次性、短时效二维码票据并同步调整扫码接口,单改前端会直接破坏现有扫码登录协议。** | web/src/components/upload/QR-code.vue:55 | 六轮,未修复 |
| ~~V-16b~~ | ~~词表与八轮一致——applet 仅 wechat_v2/v3/douyin 有allinpay 无 jsapi/mini 分支;测试缺口仍在~~复核为支付渠道能力差异不是统一协议缺陷AllinPay 交易类型需按渠道协议扩展,当前不做无需求适配 | ~~integration/payment 各渠道文件~~ | ~~七轮复核:产品能力差异~~ |
| V-38 | 新发现AGENTS.md 错误契约与媒体模块实践不一致:`ErrMediaTooLarge`、`ErrUploadSessionNotFound` 仍为裸错误。**未划线原因:确认是契约一致性问题,但当前调用方依赖 `errors.Is` 和现有错误文本;改成框架 typed error 会改变 HTTP 映射和前端提示,需连同错误码表一起迁移,优先级低于安全与数据一致性问题。** | biz/system/media.go:52、media_upload.go:21 | 十轮 |
| V-31 残留 | FindMedia 已映射 ErrMediaNotFound✓——同包 UpdateMediaNamemedia.go:125-127仍透传 gorm 原文404 语义丢失,靠黑名单兜底为"操作失败" | data/system/media.go:125-127 | 九轮,部分修复 |
## 二、死代码与碎屑
| # | 问题 | 位置 | 轮次 |
|---|------|------|------|
| ~~Z-18~~ | ~~DeleteUploadSession 注释与物理删除实现矛盾~~:注释已同步为 staging 记录物理清理语义 | ~~data/system/media_upload.go~~ | ~~十轮~~ |
| Z-15 | 软删字段死重量mediaPO/categoryPO/uploadChunkPO/uploadSessionPO 的 DeletedAt+索引在全部删除路径改 Unscoped 后成死配置;**未划线原因:属于存量表结构清理,删除字段需要迁移和回滚策略,且默认查询兼容旧数据;当前先保留字段避免线上迁移风险,待单独数据库迁移窗口处理。** | data/system/media.go:16,34media_upload.go:17,35,104 | 九轮,未修复 |
| Z-9 | V-11 修复后死通路仍在audit.go:76 ctxRespTextKey 分支不可达、截断体先完整脱敏再覆盖占位符。**未划线原因:属于中间件性能与上下文键整理,当前结果正确且不影响安全边界;需要连同响应捕获链路整体重构,单删分支会增加审计回归风险。** | server/middleware/audit.go:76-85access_log.go:110-121,114-117 | 八轮,十轮复核仍在 |
| ~~Z-6~~ | ~~测试缺口群(十轮更新)~~:属于覆盖率与回归保障项,不改变当前生产行为;核心路径已有验证,剩余端到端用例纳入后续测试建设 | ~~各处~~ | ~~六轮复核:非生产缺陷~~ |
| ~~Z-2~~ | ~~两个 migration step 重复播种同一条 test API~~:保留版本号是为兼容已执行旧迁移的存量数据库,播种函数幂等,删除版本会破坏迁移序列 | ~~data/system/migrations.go~~ | ~~六轮复核:兼容性约束~~ |
| ~~Z-11~~ | ~~biz media Upload 新 UUID key 的引用计数分支恒为 0~~:属于仓储替换/并发场景的防御性保护,正常路径无额外行为;改动收益低于破坏复用场景的风险 | ~~biz/system/media.go~~ | ~~八轮复核:保留防御逻辑~~ |
| Z-13 残留 | rate_limit 魔法数字已修✓——cors.go:13-14 逗号空格不一致、audit.go:104 单行 13 字段调用、audit.go:46-47 空 else-if 三项未修。**未划线原因:纯格式/可读性问题,不改变行为;当前代码可由格式化工具统一处理,单独改动不值得扩大变更面。** | server/middleware/cors.go:13-14、audit.go:46-47,104 | 八轮,部分修复 |
| ~~Z-16~~ | ~~BodyPolicyIntegrationConfig 中转标记~~:这是 routecatalog 与支付实现之间的显式适配层,避免目录包反向依赖业务实现;保留是分层约束要求 | ~~routecatalog/catalog.go~~ | ~~九轮复核:有意设计~~ |
| Z-17 | scanUpload.vue:115-116 空 `.catch((err) => {})` 吞路由就绪异常。**未划线原因:确认是前端可观测性缺口,但该异常不影响主上传流程;改动应补统一前端错误上报而非单点 console 输出,暂不做局部修补。** | web/src/view/media/scanUpload.vue:115-116 | 九轮,未修复 |
| ~~Z-19~~ | ~~前端全局 console.log 残留 7 处~~:已删除审查列出的生产调试输出 | ~~web/src 各处~~ | ~~十轮~~ |
| Z-20 | (新发现)错误串清洗三种方式。**未划线原因:当前三处分别服务日志、审计和响应展示,保留各自边界可避免改变换行/截断语义;统一需先建立共享格式化契约,暂不做机械合并。** | server/middleware/ | 十轮 |
| Z-21 | (新发现)同请求重复 Lookup。**未划线原因:仅一次轻量 map 查找,无可观测性能收益;缓存会增加中间件状态耦合,属于过度优化。** | server/middleware/access_log.go:34,86 | 十轮 |
## 三、重复实现 / 双轨残留
| # | 问题 | 位置 | 轮次 |
|---|------|------|------|
| Y-7 | 掩码三套实现+键表三层漂移。**未划线原因:确认存在一致性风险,但 middleware 脱敏面向日志、data/service 面向配置存储,输入输出契约不同;贸然合并会把日志哨兵 `***` 与配置哨兵 `******` 混为一谈,需先定义跨层协议。** | data/integration:225-245service/integration:69-96redact.go:18-27,6 | 九轮,十轮复核部分(递归)修复 |
| Y-5 | 集成配置校验双重执行。**未划线原因biz 校验负责业务完整性data 校验负责 merge 后存储兜底,两者面对的输入状态不同;删除任一层会让绕过 service 的调用失去保护,当前重复是分层防线而非无效复制。** | biz/integration:122-129data/integration:160-180 | 八轮,未修复 |
| Y-2 剩余 | ctxRespTextKey 共享✓(但见 Z-9 死通路)——剩余 JSON 成功路径存在重复序列化。**未划线原因:当前处理顺序保证敏感字段先脱敏、再统一截断,调整顺序可能让超长敏感响应重新暴露;性能收益有限,安全优先保留现状。** | middleware/capture.go:49-76 | 六轮,部分修复 |
| Y-10 | (新发现)前端两套动态路由注册逻辑并存。**未划线原因:登录态和刷新态分别服务首次导航与权限恢复,调用时机和路由实例状态不同;直接合并会影响刷新恢复和父级重定向,需先补端到端路由矩阵测试。** | web/src/pinia/modules/user.js:85-87permission.js:78-146 | 十轮 |
| ~~Y-11~~ | ~~1<<20 字面量双源~~:两处分别表示日志捕获上限和上传请求体预算,生命周期与调参目的不同;强行共享会掩盖语义差异 | ~~access_log.gobiz/system/settings.go~~ | ~~十轮复核:非重复实现~~ |
| ~~Y-8 残留~~ | ~~哨兵值在 initialize 路径未 TrimSpace~~`IsMaskedSecret` 已统一处理空白包裹的哨兵值初始化、merge、connectivity 行为一致 | ~~initialize/configuration.go~~ | ~~九轮复核~~ |
## 四、文档漂移
| # | 问题 | 位置 | 轮次 |
|---|---|---|---|
| ~~F-37~~ | ~~CLAUDE.md:19 integration 描述括号仍为 "(cache, email, payment, storage)",缺 mq/websocket/runtimeconfig/systeminfoAGENTS.md 版本已含全部——F-33 主体已修的残余~~ | ~~CLAUDE.md:19 已同步完整 integration 范围~~ | ~~十轮~~ |
| ~~F-38~~ | ~~config.yaml:104-107 注释 "Upload chunks are stored below .chunks" 与实际值 `chunk_dir: uploads/chunks` 不符~~ | ~~已同步配置注释与实际 `uploads/chunks` 路径~~ | ~~十轮~~ |
## 五、过分拆清单(第七轮专项,未处理)
全库 291 个非测试 .go 文件中 <40 行者 81 15 wire ProviderSet 微文件为项目惯例非债务)、 50 个为分层契约/域对称自然产物合理)、**16 个为真实过拆候选**。
### 5.1 硬过拆建议合并4 项)
| 文件 | 行数 | 问题 | 合并目标 |
|---|---|---|---|
| ~~internal/data/data_scope_record.go~~ | ~~9~~ | ~~单行类型别名,包内 13 处使用~~ | ~~已并入 `internal/data/data_scope.go`,行为不变~~ |
| ~~internal/service/dto/authentication.go~~ | ~~8~~ | ~~仅 LoginResponse 1 个类型LoginRequest 在 system.go~~ | ~~已并入 `internal/service/dto/system.go`,避免单类型文件~~ |
| ~~internal/data/task/provider.go 别名层~~ | ~~11~~ | ~~`type Provider = dataprovider.Database` 纯转手别名~~ | ~~已删除别名,任务仓储直接依赖 `dataprovider.Database`ProviderSet 保留为 Wire 注入边界~~ |
| ~~internal/biz/task/task_registry.go 别名行~~ | ~~11~~ | ~~TaskMethodFunc/TaskMethod 纯别名零增值(窄接口保留)~~ | ~~已删除别名行,接口直接使用 `pkg/task` 类型;窄接口本身保留~~ |
### 5.2 轻度过拆建议合并5 项)
| 文件 | 行数 | 问题 | 建议 |
|---|---|---|---|
| ~~handler/navigation.go~~ | ~~26~~ | ~~仅 Menu 一个端点,依赖 UserService 与 user.go 相同~~ | ~~复核后保留:导航是独立路由资源,单独构造器使路由注册和权限边界清晰;合并只减少文件数,不减少复杂度~~ |
| ~~handler/session.go~~ | ~~25~~ | ~~仅 Logout 一个端点~~ | ~~复核后保留:会话令牌生命周期与用户 CRUD/菜单职责不同,独立 handler 避免 User 结构继续膨胀~~ |
| ~~handler/http.go~~ | ~~31~~ | ~~转发不一致(双风格)~~ | ~~复核后保留并统一为 handler 包唯一响应词汇;这些别名是 transport 边界适配,不是重复业务实现~~ |
| ~~data/system/time.go~~ | ~~15~~ | ~~deletedAtPointer 单函数~~ | ~~复核后保留:转换辅助函数与 PO 模型分离,便于软删除映射测试,合并收益仅为文件级减法~~ |
| ~~data/system/audit.go~~ | ~~17~~ | ~~3 个 repo 构造器与实现跨文件分离~~ | ~~复核后保留:三个仓储分别对应三个 biz 接口,集中构造器符合 Wire ProviderSet未形成额外抽象~~ |
### 5.3 可选合并2 组)
- ~~router 21 个微文件 并入 routes.go 420 ~~复核后保留按资源拆分与 routecatalog 元数据一一对应便于增删路由和审查权限
- ~~modules 4 definition 可合并单文件 ~110 ~~复核后保留模块定义是独立注册单元合并会扩大依赖面且削弱模块边界
### 5.4 接口碎片化
- ~~同一 DB seam 三套名字同包双 seam~~复核后保留。`data.Provider`、`system.Provider`、`DatabaseProvider` 分别承载父容器系统仓储和 Wire 绑定边界强行统一会让 biz/data 依赖反向耦合属于接口职责差异而非无效重复
### 5.5 判定为合理的(防误报)
- ~~modules/surface编译级硬约束循环导入单文件职责完整包 24 biz 域微文件/dto 微文件/service 对称微文件~~确认属于合理拆分继续保留
## 审查后认为合理、不建议改动的部分(历轮评估保留决策汇总)
- **biz 注入面**RegisterBusinessModule/PaymentBusinessModule docs/PAYMENT.md 声明的业务接入契约
- **F-2/F-4/F-6/F-7/F-9/F-10/F-11S-5~S-9D-4/D-6/D-9/D-10/D-11/D-19L-5/L-10/L-12P-3~P-13X-1~X-11C-2/C-4/C-6/C-8**历轮影响分析后的保留决策
- **质量标杆**第十轮正面确认支付回调三重隔离自洽ErrorAudit 自审计抑制与客户端失败白名单闭环data 层掩码/回填往返对已入表键自洽AccessLog 前置 buffer+引用查询方向正确SSRF 拨号拦截auth singleflightCORS 安全默认V-26/V-27 主体/V-28/V-29/V-31 主体/Z-3/Z-14/Y-4/Y-8/Y-12/F-33~36/Z-5/Z-7/Z-8/Z-12 主体/Z-13 部分修复质量良好Z-3 指纹统一对存量幂等主键trade_no 唯一定位无实质影响
## 处置建议(按优先级)
1. **V-32 删除审计无痕**一行标记修复+ **V-33 存量订单指纹兼容窗口** + **V-35 调度器启动重试**
2. **V-15 收尾**data 通道净化全角冒号17 处漏网净化前记日志宽泛词收敛+ **V-19 键表补别名**一处三层受益
3. **V-24 Create 路径持锁 + V-34 CleanupStale 顺序反转(先删文件后删 DB+ Z-18 注释修正**
4. **V-13b 双清单统一+空 env fail-close + V-27 redis_list 回退 + V-30 douyin 对齐**
5. **V-36/37/38 + 二节碎屑Z-15 软删残骸+Z-19/20/21+ 三节双轨Y-7 键表统一/Y-5/Y-10**
6. **四节文档 + 五节过分拆**纯文件级减法