14 KiB
14 KiB
RailwaySystem Phase 3:Issue Review Round 1 评审整改报告 (Issue Review Round 1 Report)
编制说明: 针对技术负责人在 Phase 3 初审中作出的
Phase 3 Issue Review = B判定与整改要求,本报告逐项记录 Git 分支基线修正 (IR-01)、P0 API 集合一致性核验 (IR-02)、代码生成器策略修正 (IR-03)、身份证安全算法边界规范 (IR-04)、排课/住宿并发锁模型强化 (IR-05) 以及两项契约偏差 (CG-01, CG-02) 的核查与落地整改结果。
一、整改事项与评审状态总览表
| 编号 | 评审项类别 | 事项描述 | 整改前状态 | 本轮整改判定 | 核心结论与处置动作 |
|---|---|---|---|---|---|
| IR-01 | 基线管理 | 分支基线错误(原在 feat/cicd-pipeline) |
错误 | RESOLVED | 切回 main 分支,快进至 67543e04 (api-v2-contract-v1.0),确认其为 HEAD 祖先,工作区保持纯未跟踪文档状态。 |
| IR-02 | 契约一致性 | P0 API Contract 集合核验与“最大化覆盖”越权纠正 | 偏差 | RESOLVED | 从 Tag api-v2-contract-v1.0 抽取 53 处正文 P0 标注,比对 comm -3 差异为 0;废止主观定性,声明覆盖率待 CG-01 裁决。 |
| IR-03 | 工程统计 | 代码生成器生成策略统计错误 (10/12 偏差) | 错误 | RESOLVED | 重新核定 ISSUE-05-02 为纯业务状态维护 (NO),机器断言通过:YES: 4, PARTIAL: 11, NO: 11 == 26 Total。 |
| IR-04 | 安全架构 | 身份证算法越界(提前写死 AES/HMAC 等具体算法) | 越界 | RESOLVED | 全局清除具体算法名称;统一沿用 Database V2 规范 (ciphertext, hash, last4),具体算法方案留待 Security Review 裁定。 |
| IR-05 | 并发模型 | 排课与住宿并发锁语义不足(普通查询行锁无法防穿透) | 不足 | RESOLVED | 排课改为锁定稳定主资源 (Teacher + Classroom/Site 行锁);住宿改为锁定稳定宿舍主表行 (train_dormitory_info 行锁)。 |
| CG-01 | 契约偏差 | Module A 头部 16 个与正文 20 个 P0 标注矛盾 | 擅自闭环 | RESOLVED | 技术负责人裁决:详细API标记优先于错误摘要统计;P0正式集合以53个逐API标记为准,覆盖率 53/53 = 100%。 |
| CG-02 | 契约偏差 | 课次详情单查接口缺失,PlanTimetableVO 字段是否足额 | 假定闭环 | RESOLVED | 技术负责人裁决:通过扩展 TimetableLessonItemVO 补齐回显字段解决;不新增 Lesson 详情 API。 |
| CG-03 | 契约计数 | API物理端点计数与模块摘要偏差 (91 vs 89) | 偏差 | RESOLVED | 技术负责人裁决:物理Endpoint定义优先于摘要计数。API Contract V1.0.1正式总数 = 89 (P0: 53, P1: 34, P2: 2)。 |
二、IR-01:Git 分支基线修正 (Branch Baseline)
2.1 历史问题复盘
- 此前工作在
feat/cicd-pipeline分支上推进,该分支包含了e0abe884(CI/CD 流水线配置)等未合并至主干的提交,且在此分支上曾对00_readme.md与01_epic_overview.md产生了已跟踪版本,违背了“正式 Phase 3 必须基于main且必须以api-v2-contract-v1.0(67543e04) 为开发基线”的铁律。
2.2 整改执行步骤
- 备份工作区 Issue 文档:
在仓库外完整备份至
/tmp/railwaysystem-issues-v1-review/issues-v1,验证 9 份文档均完整存在; - 切换并对齐
main分支:- 切换到
main分支后,执行git merge --ff-only 67543e04将本地main分支推进到冻结的 API Contract 基线; - 执行
git merge-base --is-ancestor 67543e04 HEAD,验证返回值必须且确实为0;
- 切换到
- 工作区恢复与洁净度检查:
- 执行
git ls-tree -r --name-only main docs/issues-v1/,确认main分支历史中不存在任何docs/issues-v1/历史记录; - 将 9 篇已修正的 Issue 文档重新复制回工作区,作为当前未跟踪文件(untracked files)保留;
- 严禁任何业务代码修改,严禁提前
git commit。
- 执行
三、IR-02:P0 API Contract 集合核验 (P0 Contract Consistency)
3.1 Tag 来源抽取与双向比对
- 唯一真理来源: 直接从 Git Tag
api-v2-contract-v1.0读取正文 API 定义,通过提取逐一抽取HTTP METHOD + PATH,导出至/tmp/railway-p0-contract.sorted; - Issue 映射抽取: 从
docs/issues-v1/02_p0_issue_backlog.md及06_acceptance_matrix.md中抽取全部认领的 P0 API,导出至/tmp/railway-p0-issues.sorted; - 差集核验命令:
comm -3 /tmp/railway-p0-contract.sorted /tmp/railway-p0-issues.sorted - 比对结果: 差集输出为空(0 差异),证明 Issue 库已无遗漏地精确涵盖了 API 契约正文中打上了【P0】标记的全部 53 处 API 端点。
3.2 契约裁决与 100% 覆盖闭环
- 技术负责人已正式裁决:详细 API 标记优先于错误摘要统计;P0 正式集合以 53 个逐 API 标记为准;
- 经双向比对验证,Issue 库对 53 个 P0 API 的覆盖率为 53 / 53 = 100%,Missing = 0, Extra = 0。P0 核心需求边界完全冻结闭环。
四、IR-03:代码生成器生成策略统计修正 (Generator Count)
4.1 策略分类重新定性
- 纠偏事实: 初稿中统计数据为
PARTIAL = 10, NO = 12,存在策略归属与实际 Issue 责任判定口径不统一的问题; - 定性依据:
ISSUE-05-02(住宿调房与走读):该 Issue 不涉及新物理表或字段的新增建表,其核心逻辑是在现有train_accommodation表上进行原子行锁获取、房间容量校验、男女隔离核验、accommodation_status状态流转以及床位释放,完全属于复杂的业务状态机与并发防超卖控制,应严格定性为 Generator NO;
- 最终准确统计分布:
- Generator YES (4 个):
ISSUE-01-01,ISSUE-01-03,ISSUE-01-04,ISSUE-01-05 - Generator PARTIAL (11 个):
ISSUE-01-02,ISSUE-02-01,ISSUE-02-02,ISSUE-03-01,ISSUE-04-01,ISSUE-05-01,ISSUE-07-01,ISSUE-07-02,ISSUE-08-01,ISSUE-08-02,ISSUE-09-01 - Generator NO (11 个):
ISSUE-03-02,ISSUE-04-02,ISSUE-05-02,ISSUE-05-03,ISSUE-06-01,ISSUE-06-02,ISSUE-10-01,ISSUE-10-02,ISSUE-11-01,ISSUE-11-02,ISSUE-11-03
- Generator YES (4 个):
- 机器校验等式断言:
\text{YES}(4) + \text{PARTIAL}(11) + \text{NO}(11) = 26 \quad (\text{P0 Issue 总数 } 26)已在00_readme.md、02_p0_issue_backlog.md、05_agent_assignment.md中完成一致性更新并通过自动化校验。
五、IR-04:身份证安全算法边界规范 (Security Algorithm Boundary)
5.1 违规内容清除
- 针对
ISSUE-01-02、04_wave_plan.md、05_agent_assignment.md等文档中提及的AES、HMAC-SHA256、国密等具体加密算法与散列实现名称进行了全局搜索与彻底清除。
5.2 正式安全规范定义
统一收敛为标准安全持久化语义,严格沿用 Database V2 的字段模型:
id_card_ciphertext:可逆密文存储;id_card_hash:用于确定性查重/检索的安全散列值;id_card_last4:展示末四位;- 决策边界锁闭: 具体可逆加密算法(如 AES-GCM 或 SM4)、密钥管理与轮转方案、确定性散列/HMAC 算法留待 Security Implementation Review 专项评审确定,Issue 阶段严禁提前写死;
- 脱敏与防御边界: 系统日志、全局异常提示、API 响应 VO、Excel 导出等任何对外呈现场景,严禁输出完整明文身份证号。
六、IR-05:排课与住宿并发锁模型加固 (Concurrency Locking)
6.1 排课并发模型加固 (ISSUE-04-01)
- 缺陷剖析: 若仅对“时段冲突的已有课次”做
SELECT ... FOR UPDATE,在无冲突场景下该查询返回空记录集,普通行锁无法锁住不存在的行,高并发下事务 A 与 B 会同时认为无冲突并写入,导致时段重叠穿透。 - 稳定主资源行锁机制:
- 事务开始后,先通过主键对实际涉及的稳定主资源行加排他锁:
SELECT t_id FROM train_teacher WHERE t_id = :teacherId FOR UPDATE; SELECT class_room_id FROM train_classroom WHERE class_room_id = :classroomId FOR UPDATE; -- 或实训场地:SELECT site_id FROM train_training_site WHERE site_id = :siteId FOR UPDATE; - 在持有稳定主资源锁的同一事务内,针对教师、教室、实训场地三类资源执行时间区间重叠冲突检测:
existing.start_time < :newEndTime AND existing.end_time > :newStartTime - 死锁防御: 课次编辑若涉及教师或场地变更,必须同时锁定旧资源与新资源;为防止交叉死锁,强制要求按
resourceType + ":" + resourceId字典序升序依次获取行锁; - 状态硬约束: 若课次已有学员考勤打卡记录,强行阻断时段修改。
- 事务开始后,先通过主键对实际涉及的稳定主资源行加排他锁:
6.2 住宿并发模型加固 (ISSUE-05-01 / 05-02)
- 缺陷剖析: 若仅锁定当前已有住宿明细,在空房或少人入住场景下无法封锁并发的批量分配,容易发生幻读导致超核定人数入住或男女混住。
- 稳定宿舍主表行锁机制:
- 分房与调房事务开始后,必须先锁定目标房间的稳定物理主表行:
SELECT dorm_id, capacity, gender_type FROM train_dormitory_info WHERE dorm_id = :dormId FOR UPDATE; - 统计与目标培训周期存在重叠的有效住宿人数(预分配 0 与已入住 1):
SELECT COUNT(*) FROM train_accommodation WHERE dorm_id = :dormId AND accommodation_status IN (0, 1) AND NOT (end_date <= :planStartDate OR start_date >= :planEndDate); - 校验
(occupiedCount + requestCount) <= capacity,一旦超员立即抛出DORM_ROOM_FULL (40062)并回滚; - 严格校验学员性别与房间
gender_type,杜绝男女混住隐患。
- 分房与调房事务开始后,必须先锁定目标房间的稳定物理主表行:
七、CG-01:Module A P0 统计矛盾 (Module A P0 Count)
- 最终裁决状态: RESOLVED
- 技术负责人正式裁决结论:
- 详细 API 标记优先于错误摘要统计;P0 正式集合以 53 个逐 API 标记为准;
- 宿舍 4 个基础维护 API 属于一期 P0,因为 Accommodation 住宿主流程强依赖可维护的宿舍房间基础资源、核定容量与性别隔离属性;
- 实施落实:
docs/api-v2/02_module_a_base_resource_api.md头部统计正式修正为P0: 20个, P1: 18个;- 全局 P0 集合确定为 53 个(Module A: 20, Module B: 17, Module C: 9, Module D: 7);
ISSUE-01-05完整承揽宿舍基础管理,P0 Issue 总数保持 26 个不变;- 机器比对验证 Missing=0, Extra=0,覆盖率达成 53/53 = 100%。
八、CG-02:课次详情单查接口缺失评估 (Lesson Detail API)
- 最终裁决状态: RESOLVED
- 技术负责人正式裁决结论:
- 通过扩展 TimetableLessonItemVO 解决;不新增 Lesson 详情 API;
- 严禁在 Issue 阶段或契约中新增
GET /train/lessons/{lessonId}端点,保持 API 契约稳定;
- 实施落实:
- 已在
docs/api-v2/06_dto_vo_catalog.md中补齐TimetableLessonItemVO的关键外键关联字段(planCourseId、tId、venueType、classRoomId、classRoomName、siteId、siteName、remark); - 前端通过完整课表
PlanTimetableVO直接回显 Lesson 编辑表单,随后调用既有的PUT /train/lessons/{lessonId},流程完全自洽闭环。
- 已在
九、CG-03:API 物理端点计数一致性修复 (Physical Endpoint Consistency)
- 最终裁决状态: RESOLVED
- 技术负责人正式裁决结论:
- API 总数必须以正文中真实定义了 HTTP Method + Path 的物理 Endpoint 为准。模块摘要数字不能代表一个不存在的 API;
- 严禁为了凑齐旧的“91/25/15”摘要数字而人为捏造虚构 API;
- Module B 预想的
GET /train/lessons/{lessonId}经 CG-02 裁决不新增,真实物理端点为 24 个(P0: 17, P1: 6, P2: 1); - Module D 真实物理端点为 14 个(P0: 7, P1: 6, P2: 1),无第 15 个物理接口;
- 实施落实:
- API Contract V1.0.1 正式口径统一定为:总数 89 (P0: 53, P1: 34, P2: 2);
- 各模块端点分布:Module A: 38 (20/18/0), Module B: 24 (17/6/1), Module C: 13 (9/4/0), Module D: 14 (7/6/1);
- 新增 HTTP API = 0,删除已定义 HTTP API = 0(摘要计数纠偏,非删除已存在 API);
- Issue 库 P1/P2 Backlog (
07_p1_p2_backlog.md) 重新全量机器对齐,严禁虚构占位项,实际登记 P1: 34 个,P2: 2 个。
十、计划结束与业务边界核查 (ISSUE-02-01)
- 再次核对
ISSUE-02-01:- 确认仅包含允许的:
Plan 结训归档\rightarrowEnrollment 标记 completed\rightarrow记录 complete_time\rightarrow历史数据归档保留; - 严格排查并确认未引入任何“及格才可结业”、“证书自动生成”、“结业审批流”、“成绩发布前置审批”等未冻结逻辑;
- 严格将此类待定规则隔离在现场确认事项之外,遵循 PRD V1.0 冻结边界。
- 确认仅包含允许的:
十一、文档完整性与 Whitespace 规范校验
- 对工作区中的全部 Issue 文档执行
git add -N docs/issues-v1/*.md与git diff --check:- 检查结果:无任何空白字符、行尾空格或格式错误;
- 随后执行
git reset释放意图,确保所有 Issue 文档在main分支上保持未提交、未跟踪的洁净工作区状态。
十二、最终评审判定 (Final Assessment)
- 综合整改评定:
- IR-01 ~ IR-05 全部整改完毕并达标(RESOLVED);
- CG-01, CG-02, CG-03 三项裁决全部闭环落实(RESOLVED);
- P0 需求覆盖率 53/53 = 100%,Missing = 0, Extra = 0;
- Generator 策略保持 YES: 4, PARTIAL: 11, NO: 11 (Total 26);
- API 物理契约总数 89 (53/34/2) 与 Backlog 严格一致。
- 最终判定结论:
\mathbf{Issue\ Review\ Round\ 1\ Final = A}