--- req_id: REQ-USR-001 date: 2026-05-15 round: 2 reviewer: superpower-code-reviewer --- # Review: REQ-USR-001 — round 2 ## 结论 approve ## Must-fix (无) ## Nice-to-have - backend/src/main/java/com/xly/erp/module/usr/mapper/SysUserMapper.java:28 — incrementFailedLoginCountAtomic 依赖 MySQL `SET` 子句左到右求值语义;建议加链接 dev.mysql.com/doc/refman/8.0/en/update.html 提醒切换数据库方言时复查 - backend/src/main/java/com/xly/erp/module/usr/service/impl/LoginServiceImpl.java:66 — lockUntil 在 service 层 ISO 字符串化;建议改为直接放 LocalDateTime 让 Jackson 全局规则统一处理 - backend/src/main/java/com/xly/erp/common/exception/BizException.java:25 — (int, String, Throwable) 构造的 data=null 是合理默认;未来若有"包装异常 + data"诉求再加 4 参构造 - backend/src/test/java/com/xly/erp/module/usr/service/LoginServiceImplTest.java:171 — 并发测试用 2×2 低于阈值;可补 3×2 高于阈值场景断言 lock 触发 + count 准确 ## 反例 / 测试覆盖缺口 Round 1 标记『推迟』的 4 项(docs/04 vs docs/05 跨文档不一致、HttpMessageNotReadableException 兜底、ErrorCode.toHttpStatus future-proof、application.yml flyway 路径)本轮未触及,符合 round 1 review 约定,不视为 gap。Reviewer 沙箱因无 MySQL 连接产生 28 个测试 error,已通过 surefire 报告确认为环境问题;主会话 34 测试全过。 ## 本轮变更归档 Round 1 修复全部正确落地: | # | 项目 | 状态 | |---|------|-----| | H1 | 42301 data.lockUntil | ✓ BizException 扩 data 链路完整 | | H2 | 失败计数原子 UPDATE | ✓ 单 SQL,去 noRollbackFor,并发回归覆盖 | | H3 | SELECT * → 显式列 | ✓ 两个 mapper 都改 | | M5 | JWT 短密钥静默补零 | ✓ < 32 字节 PostConstruct 硬抛 | | M6 | loginSuccess 双路径 | ✓ 去 entity,走 markLoginSuccess SQL | | NTH | exp-iat==7200 / lockUntil / 并发原子累加 测试 | ✓ 全部新增 | 未引入新回归。Approve。