diff --git a/docs/UNFIXED_ISSUES_20260329.md b/docs/UNFIXED_ISSUES_20260329.md index e4b3bd2..7db4476 100644 --- a/docs/UNFIXED_ISSUES_20260329.md +++ b/docs/UNFIXED_ISSUES_20260329.md @@ -31,27 +31,8 @@ for _, code := range codes { ## 2. social_account_repo.go 使用原生 SQL 而非 GORM -**严重程度**: 中危 -**文件**: `internal/repository/social_account_repo.go` -**问题描述**: 该仓库实现使用原生 SQL 而非 GORM ORM,与其他仓库实现不一致。 - -**影响**: -- 代码风格不统一 -- 无法利用 GORM 的高级特性(如自动迁移、软删除、钩子等) -- 增加 SQL 注入风险(虽然当前代码使用了参数化查询,风险较低) - -**修复方案**: 重写为使用 GORM 的方式: -```go -func (r *SocialAccountRepositoryImpl) Create(ctx context.Context, account *domain.SocialAccount) error { - return r.db.WithContext(ctx).Create(account).Error -} -``` - -**是否可快速修复**: 否,需要: -- 大规模重构仓库实现 -- 确保所有查询逻辑与现有 SQL 语义一致 -- 更新相关测试 -- 回归测试验证 +**状态**: 已于 2026-05-29 关闭 +**关闭方式**: `internal/repository/social_account_repo.go` 已重构为统一使用 `*gorm.DB`;Create / Update / Delete / 查询 / 分页均改为 GORM 实现,并通过仓库定向测试 + 全仓 `go test ./... -count=1` + `go vet ./...` + `go build ./cmd/server` 验证。 --- @@ -119,7 +100,7 @@ const effectiveUser = user ?? getCurrentUser() | 问题 | 优先级 | 建议 | |------|--------|------| | TOTP 恢复码非原子 | 高 | 后续 sprint 修复 | -| social_account_repo GORM 重构 | 中 | 技术债务,跟踪 | +| social_account_repo GORM 重构 | 已关闭 | 2026-05-29 完成并验证 | | React 双重状态管理 | 低 | 评估后决定 | | ProfileSecurityPage 重构 | 低 | 如需维护该页面则修复 | diff --git a/docs/review-fix-closure-2026-05-28.md b/docs/review-fix-closure-2026-05-28.md index 753b48c..43414c7 100644 --- a/docs/review-fix-closure-2026-05-28.md +++ b/docs/review-fix-closure-2026-05-28.md @@ -110,10 +110,6 @@ - 真相校准:`PROJECT_REVIEW_REPORT.md` 中一批条目已不再代表当前仓库真相,至少包括: - `uploadAvatar` 字段名错误:前后端当前都使用 `avatar`,该条为陈旧误报 - `StateManager` 无法停止、`L1Cache` 无容量限制、密码强度过宽松、操作日志未转义、Webhooks 客户端全量分页、`ContactBindingsSection` 未复用:均已在后续提交中关闭 -- 仍值得继续跟踪、但已不构成功能 blocker 的尾项: - - `social_account_repo.go` 仍是原生 SQL 实现 - - `AuthProvider` 仍保留 React state + session store 双轨状态管理 - - `ApiResponse.data` 空值建模仍偏乐观(`T` 而非 `T | null`) - 本轮额外修复: - 将头像上传目录从运行时相对路径解析改为绝对路径归一化,避免 cwd 漂移导致文件落盘位置不稳定 - 扩展名校验统一转小写,避免 `.JPG/.PNG` 这类常见文件名被误拒 @@ -124,6 +120,50 @@ - `internal/api/handler/avatar_handler.go` - `internal/api/handler/avatar_handler_path_test.go` +### 11. ApiResponse 空值建模校准 +- 问题:`frontend/admin/src/types/http.ts` 之前把 `ApiResponse.data` 固定定义为 `T`,但真实后端在成功/失败分支都可能返回 `data: null`,导致类型真相偏乐观。 +- 修复: + - 将 `ApiResponse.data` 调整为 `T | null` + - 增加编译期契约文件,锁定“成功响应也允许 `data: null`”这一事实 + - 保持 HTTP client 对现有 service 调用面的兼容,不扩大本轮到全仓空值治理 +- 回归验证: + - 新增成功响应 `data: null` 的 client 单测 + - `npm run build` 编译通过,证明类型契约与实现一致 +- 涉及文件: + - `frontend/admin/src/types/http.ts` + - `frontend/admin/src/types/http.typecheck.ts` + - `frontend/admin/src/lib/http/client.ts` + - `frontend/admin/src/lib/http/client.test.ts` + +### 12. AuthProvider 状态收敛 +- 问题:`AuthProvider` 之前同时依赖 React state 和 `auth-session` 模块读路径;当 `roles` 本地 state 为空时,会在 render 期间回退读取模块态,导致 provider 显示结果会被外部 store 漂移污染。 +- 修复: + - 移除 render 阶段对 `getCurrentUser()/getCurrentRoles()` 的回退读取,改为以 provider 本地 state 为唯一展示真相 + - 抽出 `applyAuthState / clearLocalAuthState / persistSessionUser / persistSessionRoles / loadRolesForUser`,收敛重复的登录、刷新、恢复逻辑 + - `refreshUser` 失败时不再清空当前已登录视图状态,避免短暂 `/auth/userinfo` 失败导致 UI 假登出 +- 回归验证: + - 新增用例:挂载后模块 store 变更不会再漂移污染 provider 的 `roles` + - `AuthProvider` 定向测试全绿 + - 前端 full test 与真实浏览器 E2E 全绿,证明会话/导航主链路未回归 +- 涉及文件: + - `frontend/admin/src/app/providers/AuthProvider.tsx` + - `frontend/admin/src/app/providers/AuthProvider.test.tsx` + +### 13. SocialAccountRepository GORM 收敛 +- 问题:`internal/repository/social_account_repo.go` 曾长期绕过仓库层通用 GORM 模式,直接持有 `*sql.DB` 并手写 CRUD SQL,导致仓库风格与其余实现不一致。 +- 修复: + - `SocialAccountRepositoryImpl` 改为统一持有 `*gorm.DB` + - Create / Update / Delete / 查询 / 分页全部改为 GORM 链式调用 + - 保留 `*sql.DB` 构造兼容,但仅作为当前 SQLite 测试场景的 GORM 包装入口,不再保留原生 SQL CRUD 实现 + - `Update` 继续仅更新原先允许变更的字段,避免把 `provider/open_id/user_id` 这类绑定主键语义字段意外改写 +- 回归验证: + - `go test ./internal/repository -run 'TestSocialAccountRepository|TestNewSocialAccountRepository' -count=1` + - `go test ./... -count=1` + - `go vet ./...` + - `go build ./cmd/server` +- 涉及文件: + - `internal/repository/social_account_repo.go` + ## 验证结果 ### 后端 diff --git a/docs/status/REAL_PROJECT_STATUS.md b/docs/status/REAL_PROJECT_STATUS.md index 964512d..9ad1c70 100644 --- a/docs/status/REAL_PROJECT_STATUS.md +++ b/docs/status/REAL_PROJECT_STATUS.md @@ -28,11 +28,11 @@ - 浏览器级真实 E2E 已闭环 **当前活跃阻塞:** -- 无新的功能性阻塞;review 报告已完成真相校准,剩余工作以维护性尾项(如 raw SQL / 前端状态收敛 / 类型真相)和提交边界整理为主 +- 无新的功能性阻塞;review 报告中已确认的 raw SQL / 前端状态收敛 / 类型真相尾项已关闭,剩余工作以提交边界整理和文档同步为主 ### 当前可诚实复用的一句话状态 -> 后端与前端静态/单测基线、依赖审计与浏览器级真实 E2E 均已恢复绿色;当前剩余的是提交前的文档真相同步和工作树卫生收口,而非功能性阻塞。 +> 后端与前端静态/单测基线、依赖审计与浏览器级真实 E2E 均已恢复绿色;review 报告中的功能/维护性尾项已进一步收敛,当前剩余的是提交前的文档真相同步和工作树卫生收口,而非功能性阻塞。 ## 历史快照使用说明 @@ -1224,6 +1224,21 @@ - `go test ./... -count=1` - `go vet ./...` - `go build ./cmd/server` +- 前端类型真相补齐: + - `frontend/admin/src/types/http.ts` 中 `ApiResponse.data` 已从 `T` 校准为 `T | null` + - 新增编译期契约文件 `src/types/http.typecheck.ts`,锁定成功响应允许 `data: null` + - `src/lib/http/client.test.ts` 已补成功空数据返回 `null` 的回归测试 +- 本轮前端验证已执行通过: + - `cd frontend/admin && env -u NODE_ENV npm run build` + - `cd frontend/admin && env -u NODE_ENV npm run lint` + - `cd frontend/admin && env -u NODE_ENV npm run test:run` +- AuthProvider 状态收敛补充: + - provider 现已不再在 render 阶段回退读取 `auth-session` 模块态,展示真相收敛到 React provider state + - `refreshUser` 失败不再清空当前会话视图,避免瞬时 userinfo 故障造成假登出 + - 已补充 “挂载后模块 store 变更不会污染 provider roles” 回归测试 +- 本轮会话/导航真实验证已执行通过: + - `cd frontend/admin && env -u NODE_ENV npm run test:run -- src/app/providers/AuthProvider.test.tsx` + - `cd frontend/admin && env -u NODE_ENV npm run e2e:full` ## 当前运行时真实能力