All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m45s
主要变更: 1. OpenAPI 文档契约对齐 - 统一错误响应字段名为 msg(非 message) - 规范 envelope 响应结构(code, msg, data, timestamp) - 个人客户路由纳入文档体系(使用 Register 机制) - 新增 BuildDocHandlers() 统一管理 handler 构造 - 确保文档生成的幂等性 2. Service 层错误处理统一 - 全面替换 fmt.Errorf 为 errors.New/Wrap - 统一错误码使用规范 - Handler 层参数校验不泄露底层细节 - 新增错误码验证集成测试 3. 代码质量提升 - 删除未使用的 Task handler 和路由 - 新增代码规范检查脚本(check-service-errors.sh) - 新增注释路径一致性检查(check-comment-paths.sh) - 更新 API 文档生成指南 4. OpenSpec 归档 - 归档 openapi-contract-alignment 变更(63 tasks) - 归档 service-error-unify-core 变更 - 归档 service-error-unify-support 变更 - 归档 code-cleanup-docs-update 变更 - 归档 handler-validation-security 变更 - 同步 delta specs 到主规范文件 影响范围: - pkg/openapi: 新增 handlers.go,优化 generator.go - internal/service/*: 48 个 service 文件错误处理统一 - internal/handler/admin: 优化参数校验错误提示 - internal/routes: 个人客户路由改造,删除 task 路由 - scripts: 新增 3 个代码检查脚本 - docs: 更新 OpenAPI 文档(15750+ 行) - openspec/specs: 同步 3 个主规范文件 破坏性变更:无 向后兼容:是
8.0 KiB
8.0 KiB
实施进度总结
当前状态:部分完成(已归档)
完成时间:2026-01-29
完成进度:9/58 任务(15.5%)
✅ 已完成部分
阶段 1:限流覆盖真实 API 路由组(3/3 完成)
影响文件:
cmd/api/main.godocs/rate-limiting.md
变更内容:
- 调整限流中间件挂载位置,从
/api/v1改为真实业务路由组 - 限流覆盖范围:
/api/admin、/api/h5、/api/c/v1 - 明确排除:
/api/callback(回调)、/health、/ready(健康检查) - 更新文档说明限流生效范围
测试建议:
# 启用限流配置
export JUNHONG_MIDDLEWARE_ENABLE_RATE_LIMITER=true
export JUNHONG_MIDDLEWARE_RATE_LIMITER_MAX=5
export JUNHONG_MIDDLEWARE_RATE_LIMITER_EXPIRATION=1m
# 测试限流生效
for i in {1..10}; do curl http://localhost:3000/api/admin/login; done
# 验证排除路径不受限流
for i in {1..10}; do curl http://localhost:3000/health; done
阶段 2:短信验证码未配置不崩溃(3/3 完成)
影响文件:
internal/service/verification/service.go
变更内容:
SendCode方法增加 smsClient 可用性检查- 未配置短信服务时返回
errors.New(CodeServiceUnavailable)(HTTP 503) - 统一验证码链路所有错误返回为结构化错误(
errors.New/Wrap)
修复的错误点:
- 验证码发送频率限制错误:
CodeTooManyRequests - 验证码生成失败:
CodeInternalError - 短信发送失败:
CodeInternalError - Redis 存储失败:
CodeInternalError - 验证码不存在或过期:
CodeInvalidParam - 验证码错误:
CodeInvalidParam
测试场景:
- ✅ 短信服务未配置时调用发送验证码 → 返回 503
- ✅ 验证码发送过于频繁 → 返回 429
- ✅ 验证码错误 → 返回 400
- ✅ 验证码过期 → 返回 400
阶段 3:Service 层错误语义统一(部分完成:4/27 文件)
已完成文件(27 处错误修复):
verification/service.go- 10 处personal_customer/service.go- 11 处auth/service.go- 4 处device_import/service.go- 2 处
修复模式:
// ❌ 修复前
return fmt.Errorf("创建用户失败: %w", err)
// ✅ 修复后(系统错误)
return errors.Wrap(errors.CodeInternalError, err, "创建用户失败")
// ✅ 修复后(业务错误)
return errors.New(errors.CodeInvalidParam, "验证码错误")
待完成文件(24 个文件,约 224 处):
iot_card_import/service.go(2)commission_stats/service.go(3)shop_package_batch_pricing/service.go(3)commission_withdrawal_setting/service.go(4)sync/service.go(4)customer_account/service.go(6)email/service.go(6)shop_package_batch_allocation/service.go(6)commission_withdrawal/service.go(7)enterprise/service.go(7)shop_commission/service.go(7)shop/service.go(8)carrier/service.go(9)enterprise_card/service.go(9)my_commission/service.go(9)package_series/service.go(9)permission/service.go(10)shop_account/service.go(11)package/service.go(14)role/service.go(15)shop_package_allocation/service.go(17)enterprise_device/service.go(20)account/service.go(24)shop_series_allocation/service.go(24)
⏸️ 待完成部分(49/58 任务)
阶段 3 剩余:Service 层错误语义统一
工作量估算:约 224 处 fmt.Errorf 需要逐一分析并替换
- 需要区分业务错误(4xx)和系统错误(5xx)
- 需要选择合适的错误码
- 需要补充回归测试
建议执行方式:
- 按文件数量从少到多处理
- 优先处理核心业务模块(order、package、commission)
- 每完成 5-10 个文件运行一次测试
阶段 4:参数校验错误不泄露内部细节
影响范围:internal/handler/** 所有 Handler 文件(约 30-40 个)
需要修复的模式:
// ❌ 修复前
if err := c.BodyParser(&req); err != nil {
return response.Error(c, 400, errors.CodeInvalidParam, "参数解析失败: "+err.Error())
}
// ✅ 修复后
if err := c.BodyParser(&req); err != nil {
logger.GetAppLogger().Warn("参数解析失败", zap.Error(err))
return response.Error(c, 400, errors.CodeInvalidParam, "参数解析失败")
}
阶段 5:OpenAPI 响应 envelope 对齐
影响文件:
pkg/openapi/generator.go
需要修复:
- 错误响应字段名:
message→msg - 成功响应体现 envelope:
{code, data, msg, timestamp}
阶段 6:OpenAPI handlers 清单完整
影响文件:
cmd/api/docs.gocmd/gendocs/main.gointernal/bootstrap/handlers.go
需要补齐的 handlers:
- PersonalCustomer
- ShopPackageBatchAllocation
- ShopPackageBatchPricing
阶段 7:个人客户路由纳入文档体系
影响文件:
internal/routes/personal.gointernal/routes/routes.go
阶段 8:移除任务模块占位代码
影响文件:
internal/routes/task.gointernal/routes/routes.gointernal/handler/admin/task.go
阶段 9-11:规范文档更新和回归验证
建议后续工作拆分
提案 A:Service 层错误语义统一(核心模块)
范围:
- 已完成 4 个关键认证文件
- 继续完成 10 个核心业务模块(order、package、commission、shop、enterprise)
文件数:约 10 个,60-80 处错误
提案 B:Service 层错误语义统一(非核心模块)
范围:
- 剩余 14 个支持模块
文件数:约 14 个,140-150 处错误
提案 C:Handler 层参数校验安全加固
范围:
- 所有 Handler 参数校验错误处理
- 统一为不泄露内部细节
提案 D:OpenAPI 文档契约对齐
范围:
- 响应 envelope 对齐
- handlers 清单完整
- 个人客户路由纳入文档
提案 E:代码清理和规范文档更新
范围:
- 移除任务模块占位
- 清理注释一致性
- 更新规范文档
- 回归验证
技术债务记录
已解决
- ✅ 限流不覆盖真实业务路由
- ✅ 短信服务未配置时崩溃
- ✅ 核心认证链路错误语义不一致
待解决
- ⏸️ 224 处 Service 层
fmt.Errorf待替换 - ⏸️ Handler 层参数校验错误泄露内部细节
- ⏸️ OpenAPI 文档与真实响应不一致
- ⏸️ 任务模块占位代码存在鉴权风险
验证清单
已完成部分验证
限流功能:
# 1. 检查限流配置
grep -A 10 "enable_rate_limiter" pkg/config/defaults/config.yaml
# 2. 验证限流生效
source .env.local && go run cmd/api/main.go &
for i in {1..10}; do curl http://localhost:3000/api/admin/login; done
# 3. 验证健康检查不受限流
for i in {1..10}; do curl http://localhost:3000/health; done
验证码服务:
# 1. 未配置短信服务测试
unset JUNHONG_SMS_ENABLED
go test -v ./internal/service/verification/... -run TestSendCode
# 2. 验证错误码正确性
# 预期:CodeServiceUnavailable (2004) → HTTP 503
认证服务:
# 运行认证相关测试
source .env.local && go test -v ./internal/service/auth/...
source .env.local && go test -v ./internal/service/personal_customer/...
待验证部分
编译检查:
go build -o /tmp/test_build ./cmd/api
go build -o /tmp/test_build ./cmd/worker
全量测试(待完成后执行):
source .env.local && go test ./...
归档原因
由于 Service 层错误语义统一工作量巨大(224 处待处理),需要逐一分析业务语义并选择合适的错误码,继续在单一变更中完成会导致:
- 变更风险过高:单次变更影响 27 个 Service 文件
- 测试覆盖不足:无法为每个模块补充充分的回归测试
- Code Review 困难:单次 PR 包含 200+ 处修改难以审查
因此决定将已完成的高优先级部分(限流 + 验证码 + 核心认证)归档,剩余工作拆分为独立提案逐步完成。