--- req_id: REQ-USR-004 date: 2026-05-08 round: 2 reviewer: superpower-code-reviewer verdict: approve --- # Review: REQ-USR-004 — round 2 ## 结论 approve ## Round 1 Must-fix 修复确认 - [x] **[high] uk_usr_user_username 多租户唯一索引** — 已新增 `sql/migrations/V2__fix_username_unique_per_tenant.sql`,DROP 旧索引,建立 `uk_usr_user_username_tenant (sUsername, sBrandsId)` 复合唯一索引;同步更新 `docs/03`;V2 已复制至 `backend/src/main/resources/db/migration/` Flyway 可应用路径。 - [x] **[medium] UpdateWrapper → LambdaUpdateWrapper** — `AuthServiceImpl.java` 全部 `UpdateWrapper` 改为 `LambdaUpdateWrapper`,使用方法引用(`UsrUserEntity::getSId` 等),编译期类型安全,单元测试通过。 - [x] **[medium] refresh() 锁定账号检查** — 追加 `tLockUntil` 检查分支;新增 `refresh_lockedUser_throws40103` 测试,验证锁定用户刷新 token 抛 40103。 ## 本轮新增 Nice-to-have(不阻塞通过) - `docs/05` 中 40400 行仍存在;属文档小偏差,不影响运行时行为,后续 docs 统一整理。 - `JwtUtil.doParse()` access/refresh 共用 40103 错误码,低优先级语义优化。 ## 测试结果 **后端**(`JAVA_HOME=openjdk@21 mvn verify`):11 tests — 11 passed, 0 failed, 0 skipped **前端**(`npm run test -- --run`):3 tests — 3 passed, 0 failed ## 覆盖确认 | 验收标准 | 覆盖 | |---|---| | 正确凭据返回 Access + Refresh Token | ✓ login_success_resetsCountAndReturnsTokens | | 错误密码返回 40100,不区分用户名/密码 | ✓ login_wrongPassword_firstTime_throws40100 | | 品牌不存在返回 40100 | ✓ login_brandNotFound_throws40100 | | 5 次失败锁定 30 分钟 | ✓ login_wrongPassword_5thTime_setsLockAndThrows40102 | | 锁定账号返回 40102 + 剩余分钟数 | ✓ login_accountLocked_throws40102WithRemainingMinutes | | 禁用账号返回 40101 | ✓ login_accountDisabled_throws40101 | | Refresh Token 正常换新 Access Token | ✓ refresh_validRefreshToken_returnsNewAccessToken | | 无效 Refresh Token 返回 40103 | ✓ refresh_invalidRefreshToken_throws40103 | | 锁定账号的 Refresh Token 失效 | ✓ refresh_lockedUser_throws40103 | | 前端渲染版本下拉 + 默认选"标准版" | ✓ LoginPage 渲染测试 | | 前端提交调用 login API | ✓ LoginPage 提交测试 |