From e52f46e50f0bf4716cabf721c1624935e703c338 Mon Sep 17 00:00:00 2001 From: zheng020 Date: Fri, 12 Jun 2026 13:37:39 +0800 Subject: [PATCH] =?UTF-8?q?docs(status-code):=20=E5=90=88=E5=B9=B6=205=20?= =?UTF-8?q?=E4=B8=AA=20review=20advisory=20=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §7.1 测试表 #9/#10 重复行清理 - §6.1 增加 Phase 0a Dubbo 探针(验证 dubbo-go-pixiu/triples 对 gRPC code->HTTP status 的实际行为,影响 gateway 拦截器策略) - §6.3 Day 4 与 §5.1 冲突修复(老前端拦截器保持不变,只新业务代码引入 getGrpcCode) - §5.4 / §8 文件数 '10+/15+/12+' 统一为 'TBD pending audit' - §10 E2E 测试细化(3 类断言);增加'第三方客户端风险通知'清单项 --- .../2026-06-12-status-code-refactor-design.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/superpowers/specs/2026-06-12-status-code-refactor-design.md b/docs/superpowers/specs/2026-06-12-status-code-refactor-design.md index 745eaf4..527c3d0 100644 --- a/docs/superpowers/specs/2026-06-12-status-code-refactor-design.md +++ b/docs/superpowers/specs/2026-06-12-status-code-refactor-design.md @@ -497,7 +497,7 @@ grep -rn "grpc_code" --include="*.js" --include="*.vue" frontend/ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" --include="*.vue" frontend/ ``` -涉及文件(初估):15+ 个 vue/js 文件中的业务判断。其中老逻辑(`=== 401/403`)过渡期不动;新逻辑(用 `grpc_code`)按需引入。 +涉及文件(初估):`TBD pending audit`(实施前跑 §5.4 三条 grep 确认准确数量)。其中老逻辑(`=== 401/403`)过渡期不动;新逻辑(用 `grpc_code`)按需引入。 --- @@ -507,7 +507,8 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - | 阶段 | 后端 | 前端 | 时长 | |---|---|---|---| -| **Phase 0: 准备** | 写 `ToGRPCCode`,保留 `ToStatusCode`;`BaseResponse` 加 `grpc_code` 字段 | 无变化 | 0.5 sprint | +| **Phase 0a: 探针** | 用最小 demo 验证当前 dubbo-go-pixiu/triples 版本下,Dubbo 框架对 gRPC code → HTTP status 的实际行为(响应 header、body 字段、状态码) | 无变化 | 0.5 sprint | +| **Phase 0b: 准备** | 基于 0a 探针结果写 `ToGRPCCode`,保留 `ToStatusCode`;`BaseResponse` 加 `grpc_code` 字段;实现 `GRPCStatusInterceptor` | 无变化 | 0.5 sprint | | **Phase 1: 双协议期** | 所有响应同时返 `code`(HTTP 镜像) 和 `grpc_code`(gRPC 数字) | **老前端零改动继续跑**;新前端业务代码可选用 `getGrpcCode()` 读新字段 | 2-3 sprint | | **Phase 2: 全量升级前端** | 仍双协议 | 全部前端迁移到读 `grpc_code`;移除对 `code` 的 HTTP 数字依赖 | 1 sprint | | **Phase 3: 清理** | 移除 `grpc_code` 字段,`code` 改回 gRPC 数字(此时所有前端已升级,语义统一) | 移除 `getGrpcCode` 兼容 helper | 0.5 sprint | @@ -524,9 +525,9 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - ### 6.3 灰度发布 -- **Day 1**: 后端全量上双协议 + gateway 拦截器;前端保持旧版不动 +- **Day 1**: 后端全量上双协议 + gateway 拦截器;前端**保持不动**(老前端继续读 `code` HTTP 码,无需改) - **Day 2-3**: 观察监控,确认没有 4xx/5xx 异常 -- **Day 4**: 前端拦截器升级到新逻辑(读 `code` 优先) +- **Day 4+**: 新业务代码按需引入 `getGrpcCode()` 读 `grpc_code` 字段;老前端拦截器**继续不改动**,与 §5.1 / §6.1 Phase 1 保持一致 - **Day 5+**: 全量验证 1 周后,移除 `grpc_code` 字段(此时所有前端已升级,`code` 直接改为 gRPC 数字) --- @@ -549,8 +550,6 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - | 8 | `errors.New("unknown")` | `ToStatusCode = STATUS_INTERNAL_ERROR`, `ToGRPCCode = Internal (13)` | | 9 | wrapped error `fmt.Errorf("%w: extra", ErrXxx)` | `errors.Is` 仍能识别,`ToStatusCode` 和 `ToGRPCCode` 都正确 | | 10 | `FormatErrorResponse(ErrXxx)` | `BaseResponse.Code = HTTP 镜像码`, `BaseResponse.GrpcCode = gRPC 数字`,`Message`/`Timestamp` 正确 | -| 9 | wrapped error `fmt.Errorf("%w: extra", ErrXxx)` | `errors.Is` 仍能识别,code 正确 | -| 10 | `FormatErrorResponse(ErrXxx)` | BaseResponse.Code = gRPC 数字, LegacyCode = HTTP 数字 | **新增** gateway 拦截器单测 `backend/gateway/middleware/grpc_status_interceptor_test.go` @@ -607,12 +606,12 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - | 变更 | 文件 | |---|---| | 修改 | `frontend/utils/api.js`(保留现有拦截器逻辑不动;新增 `getGrpcCode()` helper 给新业务代码) | -| 修改 | `frontend/pages/**/*.vue`(10+ 文件,业务判断从 `res.data.code === 401/403` 改为 `=== 16/7` 或读 `getBizCode` helper) | +| 修改 | `frontend/pages/**/*.vue`(TBD pending audit;过渡期老逻辑不动,新业务代码按需引入 `getGrpcCode()`) | ### 总计 -- 后端: 35+ 文件改动,3 个新文件 -- 前端: 12+ 文件改动 +- 后端: ~35 文件改动,4 个新文件(加 Phase 0a 探针 demo) +- 前端: TBD pending audit --- @@ -635,7 +634,7 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - - [ ] proto regen 后所有 service 编译通过 - [ ] gateway `GRPCStatusInterceptor` 单元测试通过(responseRecorder 正确捕获 + 重写) -- [ ] E2E 测试覆盖所有 gRPC code 路径(0/3/5/7/8/13/16) +- [ ] **E2E 测试覆盖**: (a) 所有 gRPC code 路径(0/3/5/7/8/13/16);(b) **AuthMiddleware 真鉴权失败仍返 HTTP 401**(不被 GRPCStatusInterceptor 拦截);(c) 路由不存在仍返 HTTP 404(transport 错误) - [ ] 前端拦截器向后兼容测试(老前端读 `code` HTTP 码 仍正常) - [ ] Dubbo 框架未自动把 gRPC code 转 HTTP 状态码(已被 gateway 拦截器剥除) - [ ] AuthMiddleware 顺序正确(挂在 GRPCStatusInterceptor 之前,真鉴权失败仍返 HTTP 401) @@ -643,6 +642,7 @@ grep -rn "res\.code\s*!==\s*200\|res\.data\.code\s*!==\s*200" --include="*.js" - - [ ] 灰度 10% → 50% → 100%,每阶段观察 24h - [ ] 1-2 sprint 稳定后,移除 `grpc_code` 字段,`code` 改为 gRPC 数字 - [ ] 老前端缓存清理(用户升级到新前端) +- [ ] **第三方客户端风险通知**:若有项目外客户端(合作伙伴、小程序插件)解析 `code` 字段为 HTTP 状态码,Phase 3 收尾时需提前通知(可选保留 `code` 字段为 HTTP 数字作为兼容期,但 spec 不强制) ---