Files
user-system/docs/code-review/REMEDIATION_PLAN_2026-05-30.md
2026-05-30 21:29:24 +08:00

437 lines
13 KiB
Markdown
Raw Permalink 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.
# user-system 修复执行计划(按 P0 / P1 / P2 排序)
**计划日期**2026-05-30
**输入依据**`docs/code-review/FULL_REVIEW_2026-05-30.md`
**目标**:修复本轮 review 暴露出的安全、正确性、测试与文档一致性问题,并形成新的可审计验证证据。
---
## 一、执行原则
1. **先修协议与契约,再修测试与文档**
- 先修 SSO / Swagger / 路由契约错误
- 再收敛测试与静态检查
2. **每一类问题修完都必须立即验证**
3. **文档只能反映已验证事实,不能提前宣称完成**
4. **对外可见契约必须单点真实**
- 路由
- Swagger
- 前端调用
- 测试断言
- 状态文档
5. **修复计划必须覆盖 review 报告中的全部问题**
- 不能只修“代表性问题”
- 必须处理系统性问题源头
---
## 二、P0 修复计划(必须最优先)
### P0-1把空壳 Swagger 修成真实有效文档
#### 目标
`/swagger/*any` 对应的不是空 `paths`,而是真实可用 OpenAPI 文档。
#### 具体动作
1. 梳理 Swagger 生成入口与当前生成流程
2. 确认 `swag init` 或项目既定生成方式
3. 生成有效 `docs/swagger.go` / `docs/docs.go`
4. 校验 `paths` 非空
5. 校验至少以下路径存在:
- `/api/v1/auth/login`
- `/api/v1/auth/register`
- `/api/v1/admin/users/export`
- `/api/v1/users/{id}`
#### 验证
- 生成 Swagger
- 检查 `docs/swagger.go``paths` 非空
- 如可本地启动,验证 `/swagger/index.html``/swagger/doc.json` 可用
---
### P0-2系统性修正 Swagger 注释与真实路由的漂移
> 这是对报告中“系统性契约漂移”的完整修复,不再只处理导入导出接口。
#### 目标
统一以下来源的 API 契约:
- `internal/api/router/router.go`
- `internal/api/handler/*.go` 中全部 `@Router`
- `docs/API.md`
- 前端调用与测试
- 生成后的 Swagger 文档
#### 具体动作
1. 全量审计并修复以下类别的 `@Router` 漂移:
- export/importadmin 路径
- refresh`/refresh-token``/refresh`
- email-code login`/login-by-email-code``/login/email-code`
- resend activation`/resend-activation-email``/resend-activation`
- TOTP`/auth/totp/*``/auth/2fa/*`
- captcha`/captcha/*``/auth/captcha*`
- password reset`/auth/password/*``/forgot-password` / `/reset-password` / phone 变体
- custom fields`/fields/*``/custom-fields/*`
- logs`/users/me/*logs``/logs/*/me`
- admins`/users/admins``/admin/admins`
- users/me 绑定类接口bind-email / bind-phone / social accounts
2. 修复 HTTP method 漂移:
- `AssignRoles``POST``PUT`
- `AssignPermissions``POST``PUT`
- `SetupTOTP`:注释 method 与真实 method 对齐
3. 对照 `router.go` 做一次全量注释-路由对账,直到关键差异清零
4. 更新 `docs/API.md` 中对应路径
5. 重新生成 Swagger 文档
#### 验证
- `go test ./internal/api/handler ./internal/api/router -count=1`
- 生成 Swagger 后检查关键路径与 method 全部正确
- 使用脚本或审查清单确认:关键业务路由不再存在注释/注册漂移
---
### P0-3修复 SSO 授权码模式未绑定 `redirect_uri` 的问题
#### 目标
让 authorization code 与 client / redirect URI 形成强绑定。
#### 具体动作
1.`internal/auth/sso.go``SSOSession` 中加入 `RedirectURI`
2. `GenerateAuthorizationCode(...)` 保存该字段
3. `Token(...)` 兑换令牌时校验:
- `session.ClientID == req.ClientID`
- `session.RedirectURI == req.RedirectURI`
4. 对不匹配场景返回明确错误
5. 为此补回归测试
#### 验证
- `go test ./internal/auth ./internal/api/handler -count=1`
- 增加测试覆盖:
- 正确 client + redirect_uri 成功
- 错误 redirect_uri 失败
- 错误 client_id 失败
---
### P0-4禁用 implicit flow
#### 目标
系统只支持更安全的授权码模式,不再通过 fragment 返回 access token。
#### 具体动作
1. 修改 `internal/api/handler/sso_handler.go`
2.`response_type=token`
- 返回 `400 unsupported response_type`
- 或仅允许 `code`
3. 清理相应的宽松测试
4. 同步文档说明只支持 code flow
#### 验证
- `response_type=token` 应明确失败
- `response_type=code` 正常工作
---
### P0-5重构 SSO 路由分组与鉴权模型,使 `/token`、`/introspect`、`/revoke`、`/userinfo` 语义正确
> 这是第二轮新增问题若不修P0-3/P0-4 仍不完整。
#### 目标
让 SSO/OAuth 相关端点符合正确的访问控制模型,而不是错误复用平台用户 BearerAuth。
#### 具体动作
1. 将 SSO 路由按语义拆分,不再整体挂在 `protected`
2. 至少区分:
- `/authorize`:需要当前平台登录用户完成授权
- `/token`:客户端凭证 + 授权码模型,不依赖当前平台 BearerAuth
- `/introspect`:客户端认证模型
- `/revoke`:客户端认证模型或 token-owner 受控模型,必须明确
- `/userinfo`:基于 SSO access token而不是平台 JWT 上下文
3.`/token``/introspect``/revoke` 设计明确的 client auth 机制
4. 修正 `UserInfo` 的 token 解析来源,不能继续直接读平台 auth middleware 的 `user_id`
5. 同步更新测试与文档
#### 验证
- `/token` 在无平台 BearerAuth、仅有正确 client/code 条件下可成功
- `/introspect` / `/revoke` 不接受任意平台登录用户代操作
- `/userinfo` 返回的是 SSO token subject而不是平台当前 session user
---
## 三、P1 修复计划(紧随 P0
### P1-1修复 `go vet ./...` 失败并收口静态分析门禁
#### 目标
让项目重新具备诚实宣称 `go vet` 通过的资格。
#### 具体动作
1. 修复:
- `internal/api/handler/avatar_handler_test.go`
- `internal/api/handler/export_handler_test.go`
2. 所有 `resp` 使用前先检查 `err`
3. 扫描同类 helper/测试模式,避免只修报错行
#### 验证
- `go vet ./...`
- `go test ./... -count=1`
---
### P1-2把宽松状态码测试改成严格契约测试
#### 目标
让测试真正约束行为,而不是“什么都算通过”。
#### 具体动作
1. 优先重写以下测试文件:
- `internal/api/handler/export_handler_test.go`
- `internal/api/handler/sso_handler_test.go`
2. 逐场景收紧断言:
- 未认证 → 401
- 未授权 → 403
- 参数错误 → 400
- 成功 → 200 / 302
3. 删除允许 `500` 的正常断言路径
4. 对有环境差异的场景,先修被测逻辑,再收紧测试
5. 针对 SSO 补充协议级回归测试:
- `/token` 不再被平台 BearerAuth 门禁误拦
- `/introspect` / `/revoke` 权限模型正确
- `/userinfo` 基于 SSO token而不是平台 session
6. 对关键契约类 handler 增加“路由/方法/状态码固定断言”
#### 验证
- 受影响包 `go test -count=1`
- 必须确保断言收紧后仍稳定通过
---
### P1-3强化 JWT secret 治理为启动硬门禁
#### 目标
让 release 模式下的 JWT 配置符合项目自身文档标准。
#### 具体动作
1. 明确 `config.Load()` 下的正常启动规则
2. 在 release/standard 服务路径中强制:
- secret 缺失 → fail fast
- weak secret → fail fast
3. 保留 `LoadForBootstrap()` 仅用于初始化场景
4. 增加配置单元测试
#### 验证
- `go test ./internal/config -count=1`
- 缺失/弱 secret 场景必须失败
---
### P1-4接通用户状态 / 权限变更后的缓存失效链路
#### 目标
避免密码、状态、角色、权限变更后继续使用陈旧缓存。
#### 具体动作
1. 梳理以下写路径:
- `ChangePassword`
- `UpdateStatus`
- `BatchUpdateStatus`
- `AssignRoles`
- `DeleteAdmin`
- `AssignPermissions`
2. 设计缓存失效注入方式
- 推荐通过依赖注入引入失效能力
- 不要让 service 直接依赖具体 middleware 实现细节
3. 在写路径完成后主动失效:
- user_state
- user_perms
- 受影响角色下的用户权限缓存
#### 验证
- 增加回归测试:
- 改密码后旧 token / 旧状态缓存失效
- 改角色/权限后权限即时生效
---
### P1-5清理拟真 secret 示例
#### 目标
恢复文档敏感边界清洁度。
#### 具体动作
1. 清理 `docs/archive/OAUTH_INTEGRATION.md` 中拟真值
2. 全仓搜索其它类似格式示例
3. 统一替换为显式占位符
#### 验证
- 搜索确认无拟真 secret 示例残留
---
## 四、P2 修复计划(在 P0/P1 收口后处理)
### P2-1修复 `strconvAtoi` 吞错问题
#### 目标
非法 status 参数返回显式错误,而不是静默当作 0。
#### 动作
1. 修改 `internal/api/handler/export_handler.go``strconvAtoi`
2. 非数字输入返回 error
3. `ExportUsers` 中对非法 `status` 返回 400
4. 增加回归测试
#### 验证
- `status=abc` → 400
---
### P2-2头像上传改为流式写盘
#### 目标
消除不必要的整块内存分配。
#### 动作
1.`os.Create` + `io.Copy` 代替 `Read + WriteFile`
2. 保持现有 magic bytes 校验逻辑
3. 确保失败时清理半成品文件
#### 验证
- 头像上传相关测试通过
- 文件写入失败场景仍能回滚
---
### P2-3头像上传响应改为明确 struct
#### 目标
让返回 schema 与注释一致。
#### 动作
1. 引入明确响应 struct
2. 更新 Swagger 注释 / handler 返回值
3. 同步前端类型
#### 验证
- 相关 handler test
- 前端编译通过
---
### P2-4前端构建大 chunk 警告优化
#### 目标
降低主包体积,改善生产可维护性。
#### 动作
1. 识别大 chunk 页面
2. 做路由级动态拆分
3. 必要时拆分 antd 重型页面模块
#### 验证
- `npm run build`
- 观察 chunk 体积变化
---
## 五、修复计划完整性审核
本节用于确认:**计划是否覆盖 review 报告中的全部问题**。
| Review 问题 | 计划覆盖项 | 覆盖状态 |
|---|---|---|
| Swagger 空壳 | P0-1 | 已覆盖 |
| Swagger 注释与真实路由系统性漂移 | P0-2 | 已覆盖 |
| SSO code 未绑定 redirect_uri | P0-3 | 已覆盖 |
| SSO implicit flow | P0-4 | 已覆盖 |
| SSO `/token` `/introspect` `/revoke` `/userinfo` 鉴权模型错误 | P0-5 | 已覆盖 |
| 宽松状态码测试掩盖问题 | P1-2 | 已覆盖 |
| `go vet` 不通过 | P1-1 | 已覆盖 |
| JWT secret 硬门禁不足 | P1-3 | 已覆盖 |
| 状态 / 权限缓存失效未接入 | P1-4 | 已覆盖 |
| 拟真 secret 示例 | P1-5 | 已覆盖 |
| `strconvAtoi` 吞错 | P2-1 | 已覆盖 |
| 头像整块读入内存 | P2-2 | 已覆盖 |
| 头像响应 schema 漂移 | P2-3 | 已覆盖 |
### 审核结论
当前修复计划已经覆盖 review 报告中的**全部问题项**。
其中最关键的改进是:
- 不再把“Swagger 路由错误”视为单点问题,而是按**系统性契约漂移**处理
- 新增 P0-5明确修复 SSO route group / auth model 的结构性错误
这两点补齐后,计划才具备“能够完整修复 review 报告问题”的条件。
---
## 六、推荐执行顺序
### 阶段 1协议与契约止血
1. P0-5 修 SSO route group / auth model
2. P0-3 修 SSO code / redirect_uri 绑定
3. P0-4 禁 implicit flow
4. P0-2 系统性修正 Swagger 注释与真实路由漂移
5. P0-1 生成有效 Swagger
### 阶段 2质量门禁与测试收口
6. P1-1 修复 `go vet`
7. P1-2 收紧 export / sso / 契约类 handler 测试
8. P1-3 强化 JWT secret 启动门禁
### 阶段 3一致性与边界治理
9. P1-4 接通缓存失效链路
10. P1-5 清理拟真 secret 示例
### 阶段 4实现质量优化
11. P2-1 修 status 参数吞错
12. P2-2 头像流式写盘
13. P2-3 头像响应 struct 化
14. P2-4 前端 chunk 优化
---
## 七、每阶段完成后的最小验证矩阵
### P0 阶段后
```bash
go test ./internal/auth ./internal/api/handler ./internal/api/router -count=1
go build ./cmd/server
```
并检查 Swagger 生成结果。
### P1 阶段后
```bash
go vet ./...
go test ./... -count=1
go build ./cmd/server
cd frontend/admin && env -u NODE_ENV npm run test:run
cd frontend/admin && env -u NODE_ENV npm run build
```
### P2 阶段后
按受影响范围重跑:
```bash
go test ./internal/api/handler ./internal/service ./internal/repository -count=1
cd frontend/admin && env -u NODE_ENV npm run build
```
---
## 八、完成标准
只有同时满足以下条件,才能把本轮问题标记为“已收口”:
1. SSO code flow 绑定完整implicit flow 已禁用
2. SSO `/token``/introspect``/revoke``/userinfo` 的访问控制模型正确
3. Swagger 文档非空且关键路径正确
4. 注释 / 路由 / 文档 / 前端 / 测试中的 API 契约一致
5. `go vet ./...` 通过
6. handler 关键测试不再接受互斥状态码混过
7. JWT secret 治理与项目文档标准一致
8. 缓存失效链路有真实接入与回归测试
9. 状态文档与 README 只保留已验证事实