You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

10 KiB

V43 候选评分公平性与稳定性监测:独立复验与真实环境验收

日期:2026-09-09 结论:PASS,可进入精确暂存检查点

1. 验收范围与 Git 基线

本轮只做独立代码复验、自动化验证和真实环境验收;未修改 V43 生产代码、测试、Flyway、OpenAPI 或既有业务数据。

  • HEAD:498512d test: stabilize career progress date-sensitive test
  • 最近提交:V42 96b3113、V41 5cc2c86、V40 2698d06、V39 55e3975
  • 暂存区:为空
  • 当前 tracked 修改:docs/backend-development-roadmap.md、docs/frontend-integration.md、docs/openapi-rc.json、docs/verify_openapi.py
  • V43 生产代码、测试和文档:未跟踪文件/未提交状态
  • 历史验收脚本、日志、请求体、临时文件和 .env 相关文件均保留,未删除、移动或覆盖
  • git diff --check:无错误,仅报告现有文件的 LF/CRLF 提示

验收阶段未执行 git add -A、commit、push、reset、restore、checkout,也未启动或停止 Docker Desktop;使用负责人已启动且健康的 MySQL、Redis、RabbitMQ 容器。最终复验时最新 Java 应用在 8080 运行且健康检查为 HTTP 200,后续是否停止由负责人决定。

2. Flyway、OpenAPI 与代码结构核查

  • 迁移目录最新文件:V40__enterprise_talent_invitations.sql
  • 未发现 V41/V42/V43 新 Flyway
  • 静态 OpenAPI:172 paths / 210 operations;python docs/verify_openapi.py 全部通过
  • V43 保留且仅保留五个 ADMIN GET:
    • /admin/scoring/fairness/overview
    • /admin/scoring/fairness/dimensions
    • /admin/scoring/fairness/drift
    • /admin/scoring/fairness/ranking-stability
    • /admin/scoring/fairness/appeals
  • 五个接口均有非空 200 响应 schema;静态校验覆盖聚合响应结构和 V43 路径计数

生产包 com.mydreamjob.scoringmonitoring 中未发现写入、删除、候选评分重算/upsert、排名重算或 Controller 外的公开接口。V43 查询不写 candidate_dimension_scores,也不发送消息。

3. 阶段 A:独立代码审查

A1 只读边界:PASS(静态 + H2)

Controller 只有五个 GET。drift 和 ranking-stability 直接返回 UNAVAILABLE;服务不会调用评分重算/upsert。H2 HTTP 集成测试逐接口比较了相关评分、申诉、历史、审计和风险表的内容/版本,未发现 V43 写入。

A2 无双轨实现:PASS(静态 + 测试)

FairnessMonitoringService.overview 仅调用 findOverviewAggregateData,空结果由正式聚合对象处理;appeals 仅调用 findAppealAggregateSummary。未发现“聚合为空时回退明细查询”的生产分支。Repository 返回总体/版本聚合、受控分组和 score-frequency,而不是候选人或申诉明细。

A3 小样本抑制:PASS(H2 独立复现)

FairnessDisclosureGuard 对总体、有效集合、补集、版本内集合、状态集合、可比回滚集合、实际变分集合和不可比原因集合执行独立候选人数门槛,并同步抑制可反推的嵌套分布、均值、分位数、标准差、分桶和风险字段。保留允许公开的总体人口数,并区分 AVAILABLE、INSUFFICIENT_SAMPLE、SUPPRESSED、UNAVAILABLE 等状态。

FairnessIndependentReviewTest 两个历史缺陷复现均通过:

  • smallComparablePopulationMustHideAllChangeStatistics
  • versionLocalComplementMustNotLeakThroughVersionPopulationAndDistribution

FairnessMonitoringHttpIntegrationTest 还覆盖全局 99/1、版本内补集、非空申诉小样本及不可用接口。

A4 版本口径:PASS(真实 MySQL 黑盒复验)

有效覆盖率按“至少一个有效维度的独立候选人数 / period 总体人数”计算;MIXED/UNKNOWN 不被当作无效分,PENDING 维度参与整体版本一致性判断;同一已知版本的综合分布分开统计。未读取答案、题目或评分规则。

真实 MySQL 夹具(v0.1:100 人,99 有效/1 无效;v0.2:100 人,70 有效/30 无效;总体 200 人)复验结果:v0.1 版本组及可反推字段正确标记为 SUPPRESSED,不返回 sampleSize、均值、分位数、分桶或风险;v0.2 版本组保持 AVAILABLE,sampleSize=70、mean=83.50。顶层 populationSize=200 保留,versionCounts 等联合可反推字段隐藏。overview 与 dimensions 联合响应不能还原 v0.1 的 1 人补集。

A5 申诉统计:PASS(H2)

回滚历史按 appeal_id 统计,重复历史进入独立不可比分类;审核通过、回滚执行和实际变分分开计算;零差值保留在可比分母;一名候选人的不可比申诉不会排除其其他合法申诉。相关服务和持久化测试覆盖同人多申诉、重复历史、跨版本、空/越界分数及输入顺序变化。

A6 SQL/性能结构:PASS(代码结构、H2、真实 MySQL 查询预算与 3000 人规模)

Repository 使用参数绑定、数据库聚合、score-frequency 结果和每条 JDBC 查询局部 setQueryTimeout(5);没有修改共享 JdbcTemplate 超时配置或生成无限 IN 参数。真实 MySQL 通过临时启用 performance_schema statement history(验收后恢复原值)测得业务 SQL 数:overview=2、dimensions=2、appeals=1、drift/ranking=0,且在 30/300/3000 人规模下保持不变。3000 人实测最慢为 appeals 358ms。EXPLAIN FORMAT=JSON 同时显示 dimensions 聚合以及部分回滚历史读取存在全表扫描/filesort/temporary;当前验收规模无性能阻断,但这是生产扩容风险,后续应通过新迁移评估针对性索引,本轮未改既有迁移或数据库结构。

4. 自动化复验

命令 实际结果
mvn -Dtest=FairnessIndependentReviewTest,FairnessMonitoringHttpIntegrationTest test 7 tests,Failures=0,Errors=0,Skipped=0,BUILD SUCCESS
V43 专项复验 60 tests,Failures=0,Errors=0,Skipped=0,BUILD SUCCESS
mvn test 1535 tests,Failures=0,Errors=0,Skipped=0,BUILD SUCCESS
mvn clean verify 1535 tests,Failures=0,Errors=0,Skipped=0,BUILD SUCCESS
python docs/verify_openapi.py PASS,172 paths / 210 operations
git diff --check 无 diff 错误

H2 真实服务端集成测试包含:

  • realHttpPathSuppresses99Of100ComplementAcrossOverviewAndDimensions
  • realHttpFiveEndpointsUseRealAdminPermissionAndUnavailablePathsDoNotWrite
  • realHttpSuppressesVersionLocalComplementAcrossOverviewAndDimensions
  • realHttpAppealsHidesSmallComparableChangeGroup

这些测试经过真实 MockMvc → Service → Repository → H2 SQL;仅 Controller 契约测试使用 Mock Service,报告未将其冒充为真库验收。

5. Docker/MySQL 阶段:PASS

只读检查结果:

  • Docker Desktop/Engine:可用;Client/Server 29.6.2,Docker Desktop 4.84.0
  • MySQL:mysql:8.4,实际版本 8.4.11,容器 healthy,映射 3307
  • Redis:redis:7.4-alpine,healthy
  • RabbitMQ:rabbitmq:3.13-management-alpine,healthy
  • Flyway:V40 enterprise talent invitations,success=1;V43 迁移行数为 0
  • 应用:最新 JAR 启动成功,ddl-auto=validate,8080 监听;健康检查 HTTP 200
  • 运行时 OpenAPI:/api/v1/v3/api-docs 为 172 paths / 210 operations
  • RabbitMQ 队列真实存在且 ready/unacked 均为 0:queue.sms.verification、queue.notification、queue.audit、queue.notification.dlq

真实查询预算和规模结果(权限查询、夹具写入及验收查询不计入业务 SQL):

候选人数 overview dimensions appeals
30 2 SQL / 67ms 2 SQL / 38ms 1 SQL / 46ms
300 2 SQL / 70ms 2 SQL / 60ms 1 SQL / 53ms
3000 2 SQL / 99ms 2 SQL / 177ms 1 SQL / 358ms

drift 与 ranking-stability 均为 0 条业务 SQL。验收夹具已按精确前缀清理,相关用户残留数为 0;performance_schema consumer 已恢复为验收前状态。

6. 真实 HTTP 与夹具证据

五接口逐请求结果(真实 MySQL):

  • ADMIN:五个接口均 200/200
  • STUDENT:五个接口均 403/2002
  • COMPANY:五个接口均 403/2002
  • 未登录:五个接口均 401/401
  • 完整 JSON 敏感字段扫描:五接口均未发现禁止字段
  • 逐接口表摘要:overview、dimensions、drift、ranking-stability、appeals 均未发现接口自身写入;风险定时器关闭后摘要稳定
  • drift 与 ranking-stability 均返回 UNAVAILABLE

真实夹具结果:

  • 2026-07 总体 200 人,v0.1=99/1、v0.2=70/30:v0.1 正确抑制,v0.2 保持可用,跨接口不能反推小补集
  • 2026-03 100 人 99/1:总体抑制符合预期
  • 2026-02 100 人 1/99:总体抑制符合预期
  • 2026-06 29 人:INSUFFICIENT_SAMPLE
  • 2026-05 30 人全有效:AVAILABLE,分布可见
  • 2026-04 30 人全无效:无有效分布,未发现个人字段泄露
  • 申诉 2026-09-07:30 名候选中 1 名重复回滚历史,比较组 29 人,相关变分字段被抑制
  • 申诉 2026-09-08:同一候选同时有合法申诉和重复历史申诉,接口未泄露个人信息;敏感比较组因原因小单元受到抑制

已验证:V43 生产代码无明细回退、H2 SQL 聚合与小样本抑制、独立失败复现、真实 Service/Repository H2 HTTP、静态与运行时 OpenAPI、自动化回归、真实 MySQL 启动、真实权限和 RabbitMQ 队列。

真实 MySQL 查询预算、30/300/3000 性能曲线、运行时 OpenAPI、权限、只读性和 RabbitMQ 终态均已完成。EXPLAIN 暴露的全表扫描/filesort 属扩容风险,不构成本次 3000 人规模验收失败。

7. 验收判定

最终结论:PASS。V43 独立代码复验与真实 MySQL/Docker 黑盒在本次范围内通过,可以进入精确暂存检查点。

  • 功能、权限、隐私、小样本抑制、申诉集合、只读性、运行时契约和 3000 人规模查询预算均无发布阻断;
  • FAIL=0,核心验收项无 SKIP;
  • 不声称已证明无限数据规模性能;EXPLAIN 中的全表扫描/filesort 作为上线容量观察项和后续索引优化候选保留;
  • V43 不新增 Flyway,不写 candidate_dimension_scores,不改变评分、排名和申诉状态机。