fix(counseling): close Phase 13A KEEP-VERIFY/EXTEND — 9 real defects + 4 test-infra defects
Phase 13A(婚恋咨询与婚前辅导)复验关闭。历史 ✅ 不可信:counseling 模块存在双实现,
线上权威 CounselingService(167 行)零测试,唯一被测的 CounselingServiceApp(280 行)
是孤儿类(无注入点、无 HTTP 端点可达,生产永不执行)→ 已合并并删除。
生产缺陷(D1~D9):
- D1 Critical 生产故障 · INV-013 泄露:咨询正文 userRequestSummary 原文被写入 WARN 日志
(同 Phase 10 D2 一族)→ 改为只记 serviceId + riskLevel,绝不记正文。
- D2 High 越权:申请 userId 取自请求体而非认证主体 → Controller 强制 principal.id()。
- D3 High 并发:分配用「先读后写」→ 两管理员并发分配静默覆盖;
改 assignIfPending 条件更新(WHERE status='pending' AND assigned_operator_id IS NULL),
affectedRows=0 明确报错。
- D4 High 越权读:counseling_manager 经 getDetail 可读 followups 正文 → INV-013 绕过通道;
manager 只加回 userRequestSummary,不装配 followups。
- D5 Medium:无状态机 → 「已完成」可被再取消;新增 ALLOWED_TRANSITIONS + assertTransition。
- D6 Medium 生产故障:GET /counseling/services/intro 后端不存在(且被 /services/{id} 吞掉)
→ 小程序 intro 页 100% 无数据;补端点并声明在变量路径之前。
- D7 Medium 契约:Admin 调用 5 条不存在的 /services/operator/*(404)+ 缺四态
→ 后端补 8 个运营端端点(@PreAuthorize),前端整体重写 + 注册 /counseling 路由。
- D8 Medium 契约:小程序字段名错(userRequestSummary/preferredServiceMode)+ 无幂等
+ my-counseling 未检查 success(403 静默空列表)+ 跳转不存在的页 + WXML 内调用方法。
- D9 Medium 测试保真度:测试库 counseling 两表零 CHECK 约束,
counseling_services 未列入 EntityMigrationParityTest 任何集合(= 零覆盖)。
测试基建缺陷(T1~T4,不修即恒真假绿):
- T1 守卫找不到 DDL:surefire workingDirectory = ${project.basedir}/.. 使 CWD 为仓库根,
且 backend/ 是子目录非祖先 → 改为候选后缀 + 逐级向上定位,失败大声抛异常。
- T2 全限定 @com.baomidou...TableField(exist=false) 漏解析(假漂移警报)→ 正则放宽 + 回归守卫。
- T3 OperatorEndpointPermissionCoverageTest 扫到私有辅助方法(假阳性)→ 只扫描真实端点 + 自检。
- T4 两处测试自身逻辑缺陷:陈旧内存快照比较、Instant 纳秒 vs DB 微秒精度。
迁移:新增 V039(counseling 幂等键 + 三个 CHECK 白名单显式固化),基线 38 → 39。
负向验证两轮(均已还原,grep -c NEG-VAL = 0):
- ① DDL 常量守卫:从 V039 移除 'scheduled' → 常量守卫精准变红
(证明解析的是真实 DDL 而非副本)。
- ② 行为守卫:注入「并发回退先读后写 / manager 读 followups / 状态机守卫失效」
→ 三个用例各自精准变红。
测试:新增 CounselingPhase13ATest(25)+ CounselingConstraintGuardTest(5,解析真实 DDL);
删除孤儿类及其 3 个 DTO、删除测死代码的 CounselingDataScopeTest。
全量回归:Tests run: 420, Failures: 0, Errors: 0, Skipped: 3 / BUILD SUCCESS(4:49)。
基线 391 → 420(净 +29)。admin-web vue-tsc EXIT=0;miniapp tsc EXIT=0。
Tag: phase13a-recovery-2026-09-17
Report: docs/Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md
This commit is contained in:
+60
-25
@@ -5,6 +5,28 @@
|
||||
|
||||
> **2026-09-16 状态校正:** Phase 07 UI 已按 2026-09-13 规格重新实现,**首批 11 页于 2026-09-16 通过用户验收(结论:基本达标)**,本文件此前"视觉否决/REOPENED"口径随之关闭。
|
||||
>
|
||||
> **2026-09-17 Phase 13A 复验关闭:** EPIC-P13A 已完成。复验发现 counseling 模块存在**双实现**——
|
||||
> 线上权威 `CounselingService`(167 行)**零测试**,唯一被测的 `CounselingServiceApp`(280 行)是
|
||||
> **孤儿类**(无注入点、无 HTTP 端点可达,生产永不执行)→ 已合并并删除孤儿类。修复 **9 处缺陷**:
|
||||
> **D1(Critical,生产故障 · INV-013 泄露)** 咨询正文原文被写入 WARN 日志(同 Phase 10 D2 一族);
|
||||
> **D2(High,越权)** 申请 `userId` 取自请求体而非认证主体 → 可替他人申请;
|
||||
> **D3(High,并发)** 分配用「先读后写」→ 并发**静默覆盖**,改 `assignIfPending` 条件更新;
|
||||
> **D4(High,越权读)** manager 经 `getDetail` 可读 followups 正文(INV-013 绕过通道);
|
||||
> **D5(Medium)** 无状态机 → 「已完成」可被再取消;
|
||||
> **D6(Medium,生产故障)** `GET /counseling/services/intro` 后端不存在 → 小程序 intro 页 100% 无数据
|
||||
> (且被 `/services/{id}` 吞掉,需置于变量路径之前);
|
||||
> **D7(Medium,契约)** Admin 调用 5 条不存在的 `/services/operator/*`(404)+ 缺四态 → 后端补 8 端点;
|
||||
> **D8(Medium,契约)** 小程序字段名错 + 无幂等 + 未检查 `success`(403 静默空列表)+ 跳转不存在的页;
|
||||
> **D9(Medium,测试保真度)** 测试库 counseling 两表**零 CHECK 约束**,`counseling_services` 零覆盖。
|
||||
> **另修 4 处测试基建缺陷**:守卫因 surefire `workingDirectory` 指向仓库根而**找不到 DDL**(恒真假绿);
|
||||
> 全限定 `@TableField(exist=false)` 漏解析(假警报);权限守卫扫到私有辅助方法(假阳性);
|
||||
> 两处测试自身逻辑缺陷(陈旧快照 / Instant 精度)。
|
||||
> **关键结论**:负向验证两轮均证明守卫会红——① 从 `V039` 移除 `scheduled` → 常量守卫精准变红
|
||||
> (证明解析的是**真实 DDL** 而非副本);② 注入并发/INV-013/状态机三个行为缺陷 → 三个用例各自精准变红。
|
||||
> 迁移基线 38 → 39(新增 `V039`)。证据:`docs/Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md`。
|
||||
> 后端全量 **420 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS**(4 分 49 秒)。
|
||||
> **Phase 14 需用户确认后启动。**
|
||||
>
|
||||
> **2026-09-16 Phase 13 复验关闭:** EPIC-P13-V11 已完成。复验中发现并修复 7 处缺陷——
|
||||
> **D1(Critical,生产故障)** `matchmaker_recommendations.status` 代码写入 `liked`/`passed`/`confirmed_mutual`,
|
||||
> 而生产 `V009 chk_rec_status` 只允许 `pending_view/viewed/responded` → **真实 PG 上用户接受/跳过推荐必崩**;
|
||||
@@ -80,6 +102,7 @@
|
||||
| Phase 11 Notification 复验 | 已完成(2026-09-16) | 见 `Phase-11-V11-Recovery-Completion-Report-2026-09-16.md`;修复 3 处缺陷(10 种通知 type 违反生产 CHECK 约束致全部落库失败、幂等无 DB 兜底、婚前辅导通知未接线),后端 346 tests 全绿 |
|
||||
| Phase 12 Relationship Progress 复验 | 已完成(2026-09-16) | 见 `Phase-12-V11-Recovery-Completion-Report-2026-09-16.md`;修复 4 处缺陷(**实体↔生产迁移系统性漂移 23 表 50 列**、双路径 episode/NPE、测试库缺 7 表致首页零覆盖、计划项 2 未实现),新增永久守卫 `EntityMigrationParityTest`,删除 2 个假测试类,后端 371 tests 全绿 |
|
||||
| Phase 13 公益红娘转介复验 | 已完成(2026-09-16) | 见 `Phase-13-V11-Recovery-Completion-Report-2026-09-16.md`;修复 7 处缺陷(**2 处生产故障级 CHECK 约束缺口致推荐接受/服务提交必崩**、推荐与转介三处越权、`getServiceDetail` 越权读、Mapper 缺 `@Select` 致必崩、前端 5 处契约缺口),测试库补 3 张 matchmaker 表,迁移基线 V038;新增 `MatchmakerReferralPhase13Test`(17 用例)+ 重写 `MatchmakerServiceTest`(6 用例,解析真实 DDL),删除 3 处假测试,后端 **391 tests 全绿**;**Phase 13A 尚未获准** |
|
||||
| Phase 13A 婚恋咨询与婚前辅导复验 | 已完成(2026-09-17) | 见 `Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md`;发现 counseling **双实现**(权威类零测试 / 孤儿类被单测),已合并删除孤儿类;修复 **9 处缺陷**(**D1 咨询正文写日志=INV-013 泄露**、D2 申请 userId 取请求体、**D3 分配先读后写并发静默覆盖**、D4 manager 可读 followups=INV-013 绕过、D5 无状态机、**D6 `/services/intro` 后端不存在致小程序 intro 页 100% 无数据**、D7 Admin 5 端点 404、D8 小程序字段名/幂等/静默失败、D9 测试库 counseling 零 CHECK 约束)+ **4 处测试基建缺陷**(守卫找不到 DDL 恒真假绿、全限定 `@TableField` 漏解析、权限守卫假阳性、测试自身逻辑缺陷);迁移基线 V039;新增 `CounselingPhase13ATest`(25)+ `CounselingConstraintGuardTest`(5,解析真实 DDL),两轮负向验证证明守卫会红;后端 **420 tests 全绿**;**Phase 14 尚未获准** |
|
||||
| UI-CLEANUP-20260913 | 已完成 | 废弃 UI 代码、冲突规范、旧计划和无效验收证据已清理;`ui-document-baseline-contracts` 锁定唯一视觉入口 |
|
||||
| UI-ADMIN-20260913 | 已完成(待桌面端目视复验) | 管理端全局框架与工作台已按规格交付;18 modules + 22 routes,vue-tsc 与 vite build 全绿 |
|
||||
| UI-MINIAPP-20260913 | 已完成 | 小程序 11 个核心页面已重构;11/11 页 TS-only,2026-09-16 通过用户验收 |
|
||||
@@ -114,7 +137,7 @@
|
||||
| EPIC-P11-V11 | P11 | 公益服务通知扩展 | P0 | ✅
|
||||
| EPIC-P12-V11 | P12 | 关系状态轻量扩展 | P1 | ✅
|
||||
| EPIC-P13-V11 | P13 | 红娘服务转介扩展 | P1 | ✅
|
||||
| EPIC-P13A | P13A | 公益婚恋咨询与婚前辅导 | P1 |
|
||||
| EPIC-P13A | P13A | 公益婚恋咨询与婚前辅导 | P1 | ✅
|
||||
| EPIC-P14-V11 | P14 | 多类型公益活动 | P1 |
|
||||
| EPIC-P15-V11 | P15 | 活动签到回归测试 | P1 |
|
||||
| EPIC-P16-V11 | P16 | 活动互选二阶段同意重构 | P0 |
|
||||
@@ -305,56 +328,68 @@
|
||||
|
||||
---
|
||||
|
||||
## EPIC-P13A: 公益婚恋咨询与婚前辅导 ✅ 核心链路已完成(V1.1 MVP)
|
||||
## EPIC-P13A: 公益婚恋咨询与婚前辅导 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验关闭)
|
||||
|
||||
### Story: 数据模型
|
||||
- P13A-T01 counseling_services migration ✅ (V022)
|
||||
- P13A-T02 counseling_followups migration ✅ (V022)
|
||||
- P13A-T03 indexes ✅ (V022)
|
||||
- P13A-T04 migration tests ⏳ 待补全
|
||||
- P13A-T04 migration tests ✅ 已补全(`MigrationValidationTest` 基线 38 → 39;测试库补 3 个 CHECK 约束 + 新建 `counseling_followups` 表)
|
||||
- P13A-T04b **V039 幂等键 + CHECK 白名单显式固化** ✅ 新增(`idempotencyKey` 列 + `uk_counseling_idem` 唯一索引)
|
||||
|
||||
### Story: 用户咨询
|
||||
- P13A-T05 GET counseling service intro ✅
|
||||
- P13A-T06 POST counseling request ✅
|
||||
- P13A-T07 GET my counseling ✅
|
||||
- P13A-T08 GET counseling detail ✅
|
||||
- P13A-T09 cancel counseling ✅
|
||||
- P13A-T05 GET counseling service intro ✅ **修复:后端端点此前不存在**(被 `/services/{id}` 吞掉)→ 已补并置于变量路径之前
|
||||
- P13A-T06 POST counseling request ✅ **修复:userId 改从认证主体取;补幂等键;字段名对齐**
|
||||
- P13A-T07 GET my counseling ✅ **修复:检查 `success`(403 静默空列表);移除跳转不存在的页**
|
||||
- P13A-T08 GET counseling detail ✅ **修复:补 owner 校验 + 读侧分层(INV-013)**
|
||||
- P13A-T09 cancel counseling ✅ **修复:补 owner 校验 + 合法状态迁移**
|
||||
|
||||
### Story: 婚前辅导
|
||||
- P13A-T10 premarital service type ✅ (service_type=premarital_guidance)
|
||||
- P13A-T11 premarital intro ✅ (复用 counseling/intro + U58页面)
|
||||
- P13A-T12 premarital request ✅ (复用 counseling/create,serviceType=premarital_guidance)
|
||||
- P13A-T13 optional companion support ✅ (companionUserId 字段)
|
||||
- P13A-T13 optional companion support ✅ **修复:补 `confirmCompanion`,伴侣须本人确认(INV-005)**
|
||||
|
||||
### Story: Miniapp
|
||||
- P13A-T14 U55 婚恋咨询介绍 ✅
|
||||
- P13A-T15 U56 申请咨询 ✅
|
||||
- P13A-T16 U57 我的咨询 ✅
|
||||
- P13A-T15 U56 申请咨询 ✅ **修复:字段名 `summary`/`preferredMode` + 幂等键**
|
||||
- P13A-T16 U57 我的咨询 ✅ **修复:检查 `success` + Loading/Empty/Error/Permission 四态 + 下拉刷新**
|
||||
- P13A-T17 U58 婚前辅导介绍 ✅
|
||||
- P13A-T18 U59 婚前辅导申请 ✅
|
||||
- P13A-T18 U59 婚前辅导申请 ✅ **修复:字段名对齐 + `companionUserId` 输入**
|
||||
|
||||
### Story: 后台
|
||||
- P13A-T19 Counseling Queue ✅ (getPendingQueue)
|
||||
- P13A-T20 Counseling Detail ✅ (getCounselingDetail)
|
||||
- P13A-T21 Assign Counselor ✅
|
||||
- P13A-T22 Schedule ✅
|
||||
- P13A-T23 Start ✅
|
||||
- P13A-T24 Followup ✅
|
||||
- P13A-T25 Complete ✅
|
||||
- P13A-T19 Counseling Queue ✅ `GET /services/operator/queue`
|
||||
- P13A-T20 Counseling Detail ✅ `GET /services/operator/{id}`
|
||||
- P13A-T21 Assign Counselor ✅ **修复:改 `assignIfPending` 条件更新(并发防静默覆盖)**
|
||||
- P13A-T22 Schedule ✅ **修复:补状态迁移断言 + INV-012 归属校验**
|
||||
- P13A-T23 Start ✅ **修复:同上**
|
||||
- P13A-T24 Followup ✅ **修复:同上**
|
||||
- P13A-T25 Complete ✅ **修复:同上**
|
||||
- P13A-T26 Close ✅
|
||||
- P13A-T26b **Admin Web `CounselingView.vue` 重写 + `/counseling` 路由注册** ✅ 新增(四态 + 二次确认 + 防重复提交)
|
||||
|
||||
### Story: 权限与隐私
|
||||
- P13A-T27 counselor assigned scope ✅ (getCounselorAssignedServices)
|
||||
- P13A-T28 counseling_manager scope ⏳ 待补充(Admin Web Phase 19)
|
||||
- P13A-T29 matchmaker deny counseling notes ✅ (常量隔离,INV-013)
|
||||
- P13A-T30 generic admin deny sensitive note ⏳ 待补充(Admin Web Phase 19)
|
||||
- P13A-T31 SensitiveAccessLog ⏳ 待补充(随访内容写入审计日志)
|
||||
- P13A-T28 counseling_manager scope ✅ **已补全**(可看申请摘要,但**不装配 followups** —— 避免 INV-013 绕过通道)
|
||||
- P13A-T29 matchmaker deny counseling notes ✅ **已由行为测试证明**(INV-013 七用例)
|
||||
- P13A-T30 generic admin deny sensitive note ✅ **已由行为测试证明**(`strangerGetsNothing` / `plainOperatorSeesSanitizedDetail`)
|
||||
- P13A-T31 SensitiveAccessLog ⏳ 待补充(随访内容写入审计日志)—— **不阻塞本 Phase Gate**
|
||||
|
||||
### Story: 风控联动
|
||||
- P13A-T32 counseling risk referral ⏳ 待补充(后续 Phase)
|
||||
- P13A-T32 counseling risk referral ✅ **已接线**(`RiskReferralService.detectCounselingRisk`;**修复:不再把正文写入日志**)
|
||||
- P13A-T33 RiskEvent source=counseling ⏳ 待补充(后续 Phase)
|
||||
|
||||
**备注**:V1.1 MVP 核心链路已实现,Admin Web 前端、高级权限细分、风控联动在后续 Phase 补充。
|
||||
### Story: 复验(2026-09-17 KEEP-VERIFY/EXTEND)
|
||||
- P13A-T34 删除孤儿类 `CounselingServiceApp` 及 3 个仅其使用的 DTO ✅
|
||||
- P13A-T35 删除测死代码的 `CounselingDataScopeTest` ✅
|
||||
- P13A-T36 新增 `CounselingPhase13ATest`(25 用例,真实运行时路径)✅
|
||||
- P13A-T37 新增 `CounselingConstraintGuardTest`(5 用例,**解析真实 `db/migration/V*.sql`**)✅
|
||||
- P13A-T38 修复 4 处测试基建缺陷(守卫找不到 DDL 恒真假绿 / 全限定 `@TableField` 漏解析 / 权限守卫假阳性 / 测试自身逻辑缺陷)✅
|
||||
- P13A-T39 两轮负向验证证明守卫会红 ✅
|
||||
|
||||
**备注**:V1.1 核心链路已实现并完成 KEEP-VERIFY/EXTEND 复验,修复 9 处真实缺陷。
|
||||
仅剩 SensitiveAccessLog 与 RiskEvent source=counseling 两项属后续 Phase 增强,不阻塞本 Phase Gate。
|
||||
后端全量 **420 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS**。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user