7.8 KiB
N03 SDD W3 聚焦复审报告
复审对象
- 代码基线:
cd9220b,修复差异仍位于工作区,未提交。 - 复审范围:W3-I1、W3-I2 两项 Important finding 的聚焦修复。
- 环境:
JAVA_HOME=D:\java\jdk,MavenD:\maven\apache-maven-3.9.7\bin\mvn.cmd。 - 对照报告:
changes/n03-skill-cloud/.superpowers/sdd/reviews/W3-wave.md。
Verdict
FAIL
W3-I1 的原始 /skills/match operationId 冲突已修复,W3-I2 要求的运行时 401 契约、Markdown 文档和静态 OpenAPI 已对齐;但本次为满足全局 operationId 唯一性而修改了两处既有 cancel 契约,新增一项 Important 问题。
因此 W3 仍不能判定通过,不能进入收尾或 TO-11。
W3-I1:operationId 冲突
关闭状态
原始 finding 已关闭。
SkillCloudController.java:44显式设置operationId=getWordCloud。SkillCloudController.java:92显式设置operationId=getSkillMatch。SkillCloudController.java:140显式设置operationId=getLearningPath。- 静态 OpenAPI 三个 Skill Cloud operationId 与上述值完全一致:
/skills/word-cloud=getWordCloud/skills/match=getSkillMatch/skills/learning-path=getLearningPath
docs/verify_openapi.py:165-168对三个 operationId 做精确断言。SkillCloudControllerTest.skillOperationIdsAreExactAndGloballyUnique通过运行时/v3/api-docs校验三个接口的 operationId,并确认每个目标 operationId 只对应目标路径。
新增问题 N-I1(Important):修改了既有 OpenAPI 契约
docs/verify_openapi.py:27-31 新增了对全文档 operationId 的无条件唯一性断言。为让该断言通过,本次修复还修改了与 N03 无关的两个既有接口:
POST /interviews/{interviewId}/cancel:cancel→cancelInterviewPOST /profile/me/deletion/cancel:cancel→cancelAccountDeletion
问题如下:
operationId属于 OpenAPI 公共契约,常用于客户端和 SDK 生成。修改既有 operationId 属于兼容性破坏,即使 HTTP 路径和运行时行为不变,也可能导致生成客户端的方法名变化或升级失败。- 两个
cancel重复值是本次变更前已经存在的历史问题,不是 N03 引入的问题,也不在 W3-I1 的修复范围内。 InterviewController.java:132-136和AccountDeletionController.java:112-115仍使用方法名cancel,且没有显式 operationId;因此静态 OpenAPI 被改为两个新名称后,静态契约与运行时 SpringDoc 文档发生漂移。SkillCloudControllerTest.skillOperationIdsAreExactAndGloballyUnique的名称虽然包含 “GloballyUnique”,但实际只验证三个 Skill Cloud operationId 各自只出现一次,并没有验证全文档唯一性。真正强制全文档唯一性的是verify_openapi.py,而它迫使本次变更修改历史契约。
严重级别:Important。
最小修复建议:
- 将
docs/openapi-rc.json中两个既有接口的 operationId 恢复为cancel,不要在本变更中修改既有接口契约。 - 将
docs/verify_openapi.py的检查改为“新增接口不得产生新冲突”,而不是“修复全部历史冲突”。例如:- 保留已知历史重复集合
{'cancel'}; - 断言除该允许集合外没有其他重复 operationId;
- 断言
getWordCloud/getSkillMatch/getLearningPath各出现且仅出现一次; - 断言它们不与历史或未来任何非允许 operationId 冲突。
- 保留已知历史重复集合
- 如果项目要求彻底消除全局 operationId 重复,应另开变更,同时在两个既有 Controller 上显式设置 operationId,并评估客户端兼容性与迁移方案。
W3-I2:401 运行时与文档契约
关闭状态
本次要求范围内的 finding 已关闭。
- 运行时实现仍由全局 Security 入口返回:
code=401message="not authenticated"timestamp=""- 不包含
requestId - 不包含
data
SkillCloudControllerTest.anonymousRequestUsesSecurityEntryPointContract对三个接口执行上述字段级断言,并额外断言响应字段集合恰好为code/message/timestamp。SkillCloudAuthorizationIntegrationTest.anonymousAndInvalidJwtUseSecurityEntryPointContract同时覆盖匿名请求和Bearer invalid-token。docs/skill-cloud-api.md已明确区分401裸 JSON 与统一ApiResponse,示例与运行时一致。- 静态 OpenAPI 三个 Skill Cloud
401响应均引用UnauthorizedResponse,示例均为:code=401message="not authenticated"timestamp=""- 无
requestId、无data
docs/verify_openapi.py:173-185精确校验上述静态 401 契约。
非阻断观察(Minor)
SkillCloudController.java:66、114、162 的 401 注解仍使用 @Schema(implementation = ApiResponse.class)。因此运行时 /v3/api-docs 的 401 schema 仍可能展示通用 ApiResponse,而静态 OpenAPI 已改为 UnauthorizedResponse。本次要求明确检查的是 Markdown 文档和静态 OpenAPI,且该问题不阻碍运行时行为或本 finding 的既定修复;如运行时 API 文档也被视为发布契约,应另行聚焦修正控制器注解并补充运行时 OpenAPI 断言。
独立验证结果
T2–T9 目标测试
命令:
$env:JAVA_HOME='D:\java\jdk'
& 'D:\maven\apache-maven-3.9.7\bin\mvn.cmd' '-Dtest=SkillTaxonomyMigrationTest,SkillCloudSeedDataIntegrationTest,SkillTaxonomyRepositoryTest,SkillCloudQueryServiceTest,SkillMatchServiceTest,SkillLearningPathServiceTest,SkillCloudControllerTest,SkillCloudAuthorizationIntegrationTest,SkillCloudEndToEndIntegrationTest' test
结果:
Tests run: 73, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Total time: 55.399 s
分类统计:
- SkillTaxonomyMigrationTest:2
- SkillCloudSeedDataIntegrationTest:8
- SkillTaxonomyRepositoryTest:6
- SkillCloudQueryServiceTest:8
- SkillMatchServiceTest:16
- SkillLearningPathServiceTest:10
- SkillCloudControllerTest:15
- SkillCloudAuthorizationIntegrationTest:3
- SkillCloudEndToEndIntegrationTest:5
OpenAPI 静态校验
命令:
python docs\verify_openapi.py
结果:
paths: 129
All checks passed!
结论:静态校验通过,但该通过依赖于 N-I1 所描述的既有 operationId 修改,不能据此判定 W3 通过。
打包
命令:
$env:JAVA_HOME='D:\java\jdk'
& 'D:\maven\apache-maven-3.9.7\bin\mvn.cmd' -DskipTests package
结果:
BUILD SUCCESS
完整 mvn test 项目级回归
命令:
$env:JAVA_HOME='D:\java\jdk'
& 'D:\maven\apache-maven-3.9.7\bin\mvn.cmd' test
结果:
Tests run: 1395, Failures: 2, Errors: 9, Skipped: 0
BUILD FAILURE
所有 Skill Cloud 目标测试在全量套件中通过;失败仍集中在既有或环境相关测试:
CareerProgressServiceTest.fullAggregation_returnsCorrectSummaries:时间依赖失败。JobReviewDimensionControllerTest.listReviews_shouldReturnDimensionScores:旧 Mock 签名导致 500。JobReviewDimensionServiceTest.listReviews_shouldReturnDimensionScoresWithoutN1:旧 Repository stub 导致 NPE。LocalResumeStorageServiceTest:Windows JUnit 临时目录AccessDeniedException,8 个错误。
因此不能声称完整 mvn test 通过。上述 2 failures + 9 errors 仍是项目级 blocker,未形成正式豁免前不能关闭变更或进入 TO-11。
剩余阻断项
- N-I1(Important):恢复既有
canceloperationId,并调整校验脚本,使唯一性检查只拦截新增冲突,不以修改历史契约为代价。 - 项目级验证 blocker:完整
mvn test仍有 2 failures + 9 errors,需修复或正式豁免。 - Minor:运行时
/v3/api-docs的 401 schema 仍可能需要从通用ApiResponse切换为UnauthorizedResponse,以避免静态/运行时 OpenAPI 漂移。