12 KiB
Phase B「已认证企业业务门禁」独立代码复验与真实 MySQL 黑盒验收
日期:2026-09-23 范围:Phase B 独立代码复验、缺陷修复后回归、MySQL 8.4 + HTTP 黑盒 结论:通过;未暂存、未提交、未推送、未部署
1. 结论摘要
独立复核确认,招聘类受限操作由 Service 层的共用企业认证门禁保护,判定依据为 companies.verified;角色、公司归属和资源归属仍分别执行。补充修复两处复验阻断后,新增真实 MySQL 8.4 + 随机端口 HTTP 黑盒测试通过;Phase B 定向回归 208/208,全量 mvn test 与 mvn clean verify 各 2884/2884,Failures=0、Errors=0、Skipped=0。OpenAPI 检查 182 paths / 220 operations,All checks passed。
本轮没有连接或修改服务器生产数据库,没有部署服务,没有修改迁移文件或 docs/openapi-rc.json。测试中 Redis 使用 mock,RabbitMQ listener 被关闭,因此本文不把本轮结论扩展为真实 Redis/RabbitMQ 黑盒验收。
2. Git 与工作区边界
- 分支:
master - HEAD:
8c9429108cbd5d85e5245f6c404b2172bf6dd7f3 - upstream:
8c9429108cbd5d85e5245f6c404b2172bf6dd7f3;ahead/behind0/0 - 暂存区:空;
git diff --check:exit 0(仅有 Git 的 LF/CRLF 提示) - 本地工作区存在既有未暂存改动与历史未跟踪材料。没有清理、覆盖、暂存或删除这些文件。
- Phase B 现有差异包含 22 个已跟踪生产文件 + 新增
VerifiedCompanyGuard.java,以及 28 个已跟踪测试文件 + 4 个 Phase B 新测试类。本报告和 Phase B 实施报告均未跟踪;本轮没有执行任何 Git 写入操作。 - V1–V46 未修改;未新增 V47;
docs/openapi-rc.json未修改。 - 未进入 Phase C。
3. 独立审查范围与规则
复核了 Phase B 实施报告、企业入驻设计及复审文档、VerifiedCompanyGuard、服务层调用点、岗位资源归属查询、错误码映射、认证边界测试,以及候选人/简历下载入口。
规则核对结果:
- 未认证、审核中、已拒绝企业均以
companies.verified=false拒绝受限招聘业务;未使用users.is_verified代替企业认证。 - 认证门禁在 Service 业务路径执行,不只依赖 Controller;角色/企业归属/资源可见性仍单独保留。
- 企业资料与认证申请、入驻状态等允许操作未被本轮认证门禁一并封锁。
- 错误使用固定
COMPANY_NOT_VERIFIED(HTTP 403),经统一ErrorHttpStatusRegistry映射,不在 Controller 复制转换逻辑。 - 岗位访问必须按企业范围查找;对外企业岗位记录不存在与不属于当前企业均按相同
JOB_NOT_FOUND/ 404 处理。
4. 复验阻断及修复
4.1 岗位资源边界与检查顺序
复验期间确认岗位接口需要同时满足两个条件:未认证企业发布岗位时应被认证门禁拒绝;已认证企业也不能借岗位 ID 探测或操作其他企业的岗位。已调整为:
- 发布状态转换在读取目标岗位前先执行认证门禁,使未认证企业对目标 ID 不获得差异化响应;
- 已认证企业的岗位读取/更新使用
findByIdAndCompanyId范围查询;跨企业与不存在资源统一返回JOB_NOT_FOUND/ 404; - 企业自己的草稿维护及既有关闭行为按设计保留。
覆盖测试:JobServiceTest、AuthenticationBoundaryIntegrationTest,以及本报告新增的真实 MySQL + HTTP 黑盒。
4.2 持久化认证会话测试接线
原持久化测试通过静态 Token 测试助手建会话,不能确保会话写入当前 Testcontainers 数据源。测试现改为从 Spring 上下文调用 AuthSessionService.createSession,令令牌与当前测试数据库一致,避免测试仅凭伪造/错库 Token 得出授权结论。
5. 新增真实 MySQL + HTTP 黑盒
新增测试:mydreamjob-server/src/test/java/com/mydreamjob/phaseb/VerifiedCompanyGateMySqlBlackboxTest.java。
- Testcontainers 使用真实
mysql:8.4,创建隔离数据库phase_b_gate_blackbox,正式执行 Flyway,并使用 Hibernateddl-auto=validate。 - Spring Boot 完整应用在随机端口启动;通过 HTTP socket 请求
/api/v1/...,覆盖 Spring Security、Controller、Service、Repository 和真实 MySQL。 - 使用精确假号段夹具,测试结束按本类登记的主键清理;容器随后由 Testcontainers 回收。
结果 2/2,F=0、E=0、S=0:
- UNVERIFIED、PENDING、REJECTED 三种
companies.verified=false企业对岗位发布均返回 403 与COMPANY_NOT_VERIFIED。每个拒绝前后比较 15 张表的稳定行快照,并核对岗位仍为 DRAFT。 - 未认证企业读取候选人列表、候选人详情与简历下载均被拒绝。简历存储
read()计数为 0;响应非 PDF;15 张表拒绝前后逐行快照相同。 - VERIFIED 企业能够发布自己的岗位;不能读取、更新或发布另一企业岗位。外企业资源与不存在资源均返回相同 404/
JOB_NOT_FOUND,跨企业拒绝前后数据库快照无变化。 - 用户夹具的
users.is_verified被有意设为 true,而公司认证状态分别按测试构造。这证明被测门禁取决于companies.verified,而不是用户通用 verified 字段。
此黑盒未启动真实 Redis 或 RabbitMQ:RedisTemplate 为 mock,RabbitMQ listener 显式禁用。拒绝请求的数据库快照覆盖 notifications、audit_logs、messages 等表;但这不能替代 broker 队列深度检查,也不能证明真实 Redis 可用性。
6. 测试结果
| 验证 | 结果 |
|---|---|
| Phase B 定向(门禁/角色/岗位/投递/简历/Offer/面试/邀约/消息等 12 类) | 208/208,F=0、E=0、S=0 |
| 真实 MySQL + HTTP 黑盒 | 2/2,F=0、E=0、S=0(包含在定向结果内) |
mvn test |
2884/2884,F=0、E=0、S=0 |
mvn clean verify |
2884/2884,F=0、E=0、S=0 |
| 全量 Surefire XML | 277 个测试类;2884 项;F/E/S 均为 0 |
python ..\docs\verify_openapi.py |
182 paths / 220 operations,All checks passed |
MySQL/Testcontainers 在本机 Docker 上真实运行;新增黑盒类标记 disabledWithoutDocker=false,不会在 Docker 缺失时静默跳过。全量测试 Skipped=0。
7. 测试驱动器自身问题记录
初次黑盒执行出现 HTTP 404,是 TestRestTemplate 测试 URL 使用相对路径造成的 harness 错误;随后改为以 @LocalServerPort 构造 127.0.0.1 绝对 URL,黑盒 2/2 通过。测试初次编译还因 DirtiesContext 导入包路径错误失败,改为 Spring Test 正确包后通过。两项均为测试代码接线问题,不是产品缺陷;修正后定向与全量测试均已重跑通过。
8. 运行环境收尾
检查时 Docker 容器列表为空;8080/8081 无监听;无残留 java 或 mvn 进程。黑盒使用随机端口,并未占用上述端口。临时 MySQL 为 Testcontainers 隔离容器,没有触及本机开发库或服务器库。
9. 未执行/不在本轮结论内
- 未做生产服务器部署或真实公网 MySQL/Redis/RabbitMQ 验收。
- 未做运行时 OpenAPI 路径集合与静态 OpenAPI 的双集合比较;本轮运行的是仓库 OpenAPI 检查器,且
docs/openapi-rc.json保持未改。 - 未覆盖到的每一个招聘入口仍以既有 Phase B 结构/服务测试清单和全量回归为依据;本轮新增真实黑盒聚焦岗位发布、候选人列表/详情/简历,以及跨企业岗位访问,不能解读为每个业务端点都由真实 HTTP 重放。
- 未实现 Phase C 管理员用户与角色管理;未修改短信服务;未伪造任何真实企业认证状态。
10. 最终判定
Phase B 独立代码复验及真实 MySQL + HTTP 黑盒验收通过。 两处复验阻断已修复;定向、全量测试及 OpenAPI 检查通过。当前仍是未暂存的本地工作区状态,后续如需提交,必须另行进行提交前精确文件范围审查;本轮没有暂存、提交、推送或部署。
11. 2026-09-29 精确暂存与隔离验证检查点
本节追加记录最新检查点,不覆盖第 1–10 节的历史执行结果与当时仓库状态。
11.1 批次边界与验证来源
- 当前分支为
feat/phase-b-company-verification-gate;基线 HEAD 为bcea6b02955f20f933572e8c8f2c85b1ad05843c,包含此前单独本地提交的短信 P0 修复。 - Phase B 暂存范围为 57 个文件:23 个生产文件、32 个测试文件、2 份报告,没有删除文件。未纳入迁移、
pom.xml、OpenAPI 文件、基础设施脚本或历史验收输出。 - 共用错误码与映射测试只暂存 Phase B 的
COMPANY_NOT_VERIFIED及其 403 映射,未纳入统一注册/身份选择的新增错误码和接口。 - 验证目录由 HEAD 归档加暂存补丁生成,不读取原工作区未暂存的统一注册/身份选择实现。57 个暂存文件与验证快照按 Git 换行规范化后的 blob 逐项比较,不一致数为 0。原工作区其他批次改动与历史未跟踪文件均保留。
11.2 本次失败记录及纠正
- 初次 32 类组合运行 928 项,F=1、E=0、S=0。简历下载测试的 OpenAPI 数量期望误混入未提交身份选择批次的 183/221,而当前隔离快照实际为 182/220。已从暂存区移除这两行无关 hunk,使用 HEAD 的 182/220 契约;原工作区 183/221 改动仍保留。没有修改生产实现或放宽授权断言。随后 12 类定向及全量验证通过。
- 9 月 28 日首次全量尝试未完成,跨库测试报告 1 项容器启动错误,根因链包含 Docker 命名管道不存在(
docker_engine)。该次没有 Maven 最终汇总,不记为通过,也不推算其全量测试总数。日志保留在系统临时验证目录,不纳入提交。Docker 恢复后确认服务版本 29.6.2,以原暂存代码快照重新执行完整clean verify。
11.3 最新验证结果
| 验证 | 实测结果 |
|---|---|
| Phase B 12 类定向测试 | 208 项,F=0、E=0、S=0,BUILD SUCCESS |
| Phase B 真实 MySQL + HTTP 黑盒 | 2 项,F=0、E=0、S=0(包含在定向与全量结果内) |
隔离暂存快照 mvn clean verify |
2889 项,F=0、E=0、S=0,BUILD SUCCESS |
| 全量 Surefire XML 独立汇总 | 281 个测试类,2889 项,F/E/S 均为 0 |
| 短信错误次数真实 MySQL 并发测试 | 1 项,F=0、E=0、S=0(基线短信批次回归) |
| 短信限流真实 Redis 测试 | 1 项,F=0、E=0、S=0(基线短信批次回归) |
| 静态 OpenAPI 检查器 | 182 paths / 220 operations,All checks passed |
| Spring 测试上下文运行时 OpenAPI 与静态集合比较 | 双方均 182/220,路径差集 0,路径/HTTP 方法 operation 差集 0 |
本次全量命令使用 -Ds03.openapi.snapshot=<临时输出目录> 留存既有简历测试通过 MockMvc 获取的运行时文档;比较以解析后的路径与 HTTP 方法集合为准,不只比较数量。该证据来自完整 Spring 测试上下文,不是独立 JAR 或公网部署版本的 OpenAPI 验收。此次没有另行宣称一次新的 mvn test 结果;clean verify 已实际执行全量测试并打包成功。
11.4 暂存安全扫描与结论边界
暂存新增行扫描发现 2 处手机号形状的既有测试夹具字面量、1 处明确仅用于临时 Testcontainers 数据库的测试口令;均不是实际用户或服务器凭据。疑似绝对路径命中均为路由数字正则或 loopback 随机端口 HTTP URL,不是本机文件路径。未发现真实 JWT、Bearer、邮箱、BCrypt 摘要、私钥、AWS key 或服务器连接密钥;原始运行日志和容器输出不暂存。
Phase B 精确暂存与隔离验证检查点通过。 本节完成后仅更新并暂存本报告,尚未创建 Phase B 本地提交,未推送、未部署,未进入 Phase C。真实 MySQL HTTP 黑盒的 Redis mock 与禁用 RabbitMQ listener 边界仍如第 5 节所述;本次全量中的真实 Redis 测试不能替代 Phase B 全链路三中间件或公网验收。