8.3 KiB
Phase A 企业注册与入驻基础闭环独立代码复验报告
日期:2026-09-22
1. 复验范围与边界
本次复验针对 Phase A:企业专用注册、company-register 验证码用途、验证码原子消费、用户/角色/企业/会话事务、企业入驻聚合查询、测试与 OpenAPI。
未进入 Phase B 已认证企业业务门禁,也未进入 Phase C 管理员用户与角色管理;未修改生产代码、未暂存、未提交、未推送。
2. 前置状态
- 分支:
master - HEAD:
00153aaf5d92d13e66d6cdc42ecd1fe903d6e666 - 暂存区:空
- 迁移:V1–V46 未修改,未新增 V47
pom.xml:无修改- 两个既有 Windows stat 缓存假阳性文件的工作区 blob 与 HEAD 相同,未触碰、未暂存
- 历史未跟踪验收文件和
backend-infra文件均保留
3. 独立静态核对
通过项:
- 注册服务使用事务,按 COMPANY 角色创建用户,并显式写入仅含 COMPANY 的
user_roles。 - 用户、企业保存后 flush,再创建登录会话;企业初始
verified=false。 - 注册审计使用固定脱敏文案,未发现密码、验证码、Token 或摘要输出路径。
- 验证码消费使用条件更新,条件包含 id、
used=false、未过期和 attempts 上限,受影响行数必须为 1。 - 短信用途采用固定白名单,包含
company-register,不接受任意非空用途。 - 匿名规则仅新增
/auth/company/register;/companies/me/onboarding仍要求认证。 - 入驻状态对无记录、PENDING/RESUBMITTED、REJECTED、VERIFIED 和 APPROVED 不一致状态分别处理;不一致状态失败关闭。
- DTO 未暴露
userId、客户端role、verified、passwordHash等不应由客户端控制的字段。 - OpenAPI 中新增注册和入驻查询契约,未改变 V1–V46 或既有业务路径。
4. 定向测试与真实黑盒
实施测试与复验前已执行的 Phase A 定向测试为 23/23,Failures=0,Errors=0,Skipped=0,其中包含真实 MySQL/Testcontainers 并发注册测试。
此前全量结果:
mvn test:2860/0/0/0mvn clean verify:2860/0/0/0- OpenAPI:182 paths / 220 operations,All checks passed
隔离 MySQL 8.4、Redis 7.4、RabbitMQ 3.13 和最新 JAR 的黑盒结果:健康检查通过;发送 company-register 验证码后注册成功;密码登录成功;/auth/me 返回 COMPANY;入驻查询返回 200;目标数据为 1 个 COMPANY 用户、1 个 COMPANY 角色、1 个企业且 verified=0,验证码已消费。临时容器、进程、端口和日志已清理。
5. 阻断项:功能开关绑定不满足严格字面量要求
生产文件:mydreamjob-server/src/main/java/com/mydreamjob/auth/company/CompanyRegistrationProperties.java
当前字段为:
private boolean enabled = false;
Spring Boot 标准布尔绑定会把 TRUE、True、yes、1、on 均转换为 true。独立临时测试使用 ApplicationContextRunner 真实绑定配置,逐一设置:
app.company-registration.enabled=TRUE
app.company-registration.enabled=True
app.company-registration.enabled=yes
app.company-registration.enabled=1
app.company-registration.enabled=on
复验结果:五个非字面量值均绑定为 enabled=true,测试失败:
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
Expecting empty but was: ["TRUE", "True", "yes", "1", "on"]
这与设计要求“只有字面量 true 才开启,其他值不得误开启”不一致,因此 Phase A 独立复验判定 FAIL。临时测试已删除,未留在工作区。
整改建议:将配置原始值改为 String,并通过唯一方法严格判断:
private String enabled = "false";
public boolean isEnabled() {
return "true".equals(enabled);
}
同时增加真实 Spring 属性绑定测试,覆盖未设置、false、true、TRUE、True、yes、1、on;只有小写字面量 true 应开启。
6. 整改前的次要测试覆盖缺口
以下是首次独立复验时发现的证据缺口,不作为已证明的生产缺陷:
CompanyRegistrationTransactionRollbackTest目前主要覆盖审计失败,未分别注入并断言 users 保存、user_roles 保存、companies 保存、会话创建和审计写入五类失败;对 user_roles/auth_tokens 的零残留断言也不完整。- 注册请求中客户端附带未知的 role/verified/passwordHash 字段的既有测试,可能因验证码未准备而返回 400,不能单独证明未知字段被拒绝;DTO 本身未声明这些字段。
- tombstone、Redis/数据库/会话依赖异常和每种冲突角色的完整 HTTP 黑盒覆盖仍需单独补齐或明确证据。
7. 复验结论
Phase A 的主要注册、验证码原子消费、事务、并发、入驻聚合和真实中间件路径基本可用,但严格功能开关绑定存在阻断缺陷;另有事务回滚测试覆盖不足。
最终判定:FAIL,暂不能进入独立通过或提交检查点。
本次独立复验未修改生产代码、未暂存、未提交、未推送,未进入 Phase B/C。
8. 阻断整改复验(2026-09-22)
针对第 5 节阻断,已按最小范围修改:
CompanyRegistrationProperties.enabled改为字符串,默认值为"false";isEnabled()仅返回"true".equals(enabled);CompanyRegistrationFeatureFlagTest增加真实ApplicationContextRunner绑定测试,覆盖TRUE、True、yes、1、on、false和true。
整改后验证:
- 功能开关及关联测试:9/9,F=0、E=0、S=0;
- Phase A 定向测试:24/24,F=0、E=0、S=0;
mvn clean verify:2861/2861,F=0、E=0、S=0;- OpenAPI:182 paths / 220 operations,All checks passed。
独立绑定测试确认只有字面量 true 开启,五种非字面量值均保持关闭。未新增迁移,未进入 Phase B/C,未提交或推送。
功能开关阻断已清除;第 6 节的事务回滚覆盖缺口已在第 9 节补齐。
说明:第 7 节“FAIL”是整改前复验结论;当前状态以第 8、9 节整改复验结果为准。
9. 事务回滚覆盖整改复验(2026-09-22)
CompanyRegistrationTransactionRollbackTest 已补齐五类独立故障注入:
- users 保存失败;
- user_roles 真实插入触发器失败(H2 真实 SQL);
- companies 保存失败;
- 会话创建失败;
- 审计写入失败。
每种场景均验证 users、user_roles、companies、auth_tokens 无残留,验证码 used=false,并按精确测试手机号清理。测试结果:5/5,F=0、E=0、S=0。
10. 阻断修复后的完整回归收口(2026-09-22)
为避免把整改前的历史数字误读为当前结果,最终收口结果单独列示如下:
- 功能开关整改后的独立定向:9/9;
- 五类事务回滚注入:5/5;
- Phase A 完整定向测试:28/28,F=0、E=0、S=0;
mvn clean verify:2865/2865,F=0、E=0、S=0,BUILD SUCCESS;- OpenAPI:182 paths / 220 operations,All checks passed;
- 真实 MySQL/Testcontainers 并发注册:已执行并通过;
- V1–V46 未修改,未新增 V47;未进入 Phase B/C,仍未暂存、未提交、未推送。
期间 H2 user_roles 触发器用于证明真实 SQL 插入失败,触发日志中的预期 SQL 错误属于测试注入证据,不是生产异常;未修改生产错误映射,也未放宽任何断言。
11. 复验重跑收口(2026-09-22)
- 独立静态门禁通过:功能开关严格按小写字面量
true开启;匿名放行仅包含/auth/company/register;注册 DTO 未暴露userId/role/verified/passwordHash;验证码白名单、条件消费和attempts < maxAttempts均已分别在 Service 与 Repository 位置核对;未发现 V47。 - 首次静态脚本曾把
attempts < c.maxAttempts错查在SmsVerificationService.java,造成脚本假阴性;修正为检查SmsVerificationCodeRepository.java后门禁通过。该问题仅存在于复验脚本,不是产品缺陷。 - Phase A 定向重跑:28/28,Failures=0、Errors=0、Skipped=0;真实
CompanyRegistrationConcurrencyMySqlTest启动 MySQL 8.4 Testcontainers 并实际执行。 - OpenAPI:182 paths / 220 operations,All checks passed。
- 收尾:无 Java/Maven 残留进程,8080/8081 无监听,暂存区为空;本轮未修改生产代码、未提交、未推送,未进入 Phase B/C。