fix(matchmaker,referral): close Phase 13 KEEP-VERIFY/EXTEND — 7 real defects
KEEP-VERIFY/EXTEND 复验(历史 ✅ 不可信;测试覆盖函数 ≠ 覆盖运行时路径)。
逐条核对运行时路径与生产约束后修复 7 处缺陷,其中 3 处「只在真实 PostgreSQL 上炸」。
D1 (Critical, 生产故障)
matchmaker_recommendations.status 代码写 liked/passed/confirmed_mutual,
而 V009 chk_rec_status 只允许 pending_view/viewed/responded 且从未扩展
→ 真实 PG 上用户接受/跳过推荐必崩。测试库未复刻该 CHECK,故长期静默。
D2 (Critical, 生产故障)
控制器缺省 serviceType="recommendation" 不在 chk_matchmaker_service_type
白名单 → 提交红娘服务必崩。
D1+D2 同修于新增 V038__align_matchmaker_status_constraints.sql
(沿用 V018/V020/V025 的 DROP CONSTRAINT IF EXISTS + 重加白名单惯例)。
D3 (High, 越权写)
MatchmakerServiceService.recommendPartner 无 assignedOperatorId 归属校验,
且可把用户推荐给自己 → 补校验 + 禁止自我推荐。
D4 (High, 越权读)
getServiceDetail 无归属校验且返回完整用户资料(userId/description/
userProfile/followups)→ 签名加 requesterId,按调用者返回完整/脱敏视图。
D5 (High, 越权写)
ReferralService 的 userId 取自请求体且零授权校验 → 新增
assertMatchmakerServesUser,在 referToServiceStation/referToActivity 入口
强制校验存在进行中的服务关系。
D6 (High, 生产故障)
MatchmakerFollowupMapper.findByServiceId 只有声明无 @Select
→ Invalid bound statement (not found),getServiceDetail 必崩。
该缺陷由本轮新增测试首次暴露(历史测试从未调用该路径)→ 补 @Select。
D7 (Medium, 契约缺口)
admin-web 5 处 API 缺口(4 条 404 + C 端端点被运营端误用)+ 小程序缺转介服务层
→ 后端补 GET /operator/matchmaker/recommendations 与
GET /referrals/operator/history 两个运营端端点;前端改路径、
assign 改 POST + body operatorId;新增 miniapp/services/referralService.js。
测试保真度
- 测试库补 matchmaker_services/recommendations/followups 三表(此前该模块零真实覆盖),
约束与 V038 对齐;EntityMigrationParityTest 三表移入 REQUIRED_IN_TEST_SCHEMA;
MigrationValidationTest LATEST_MIGRATION 37 → 38。
- 新增 MatchmakerReferralPhase13Test(17 用例,@SpringBootTest 走真实方法路径 + 真实落库)。
- 重写 MatchmakerServiceTest(6 用例):直接解析 db/migration/V*.sql,按文件名顺序应用
DROP CONSTRAINT IF EXISTS + ADD CONSTRAINT 取"最终有效"白名单,并内置解析器自检。
【关键】首版守卫硬编码白名单副本,注入 D1 后仍全绿(对漂移零反应)→ 必须解析真实 DDL。
- 删除 3 处假测试占位(MatchmakerServiceTest.testMatchmakerCannotLike 的 assertTrue(true);
CoreInvariantsTest INV-007 断言的是状态常量、INV-010 亦为 assertTrue(true)),
已如实改名并注明行为验证位置。
负向验证(两轮)
注入 D1(回退 chk_rec_status 白名单)→ 行为守卫 DataIntegrityViolation
+ 常量守卫 Multiple Failures (3 failures) → Tests run: 23, Failures: 1, Errors: 2
/ BUILD FAILURE,守卫有效性得证。缺陷已还原。
全量回归(离线容器,实测)
[WARNING] Tests run: 391, Failures: 0, Errors: 0, Skipped: 3
[INFO] BUILD SUCCESS / Total time: 04:59 min
Phase 12 基线 371 → 391(净 +20)。
报告:docs/Phase-13-V11-Recovery-Completion-Report-2026-09-16.md
Phase 13A 未自动进入,等待用户确认。
This commit is contained in:
@@ -257,12 +257,52 @@ D2——`RelationshipService.createMatch` 不写 episode/lastActivityAt,与 `M
|
||||
|
||||
**Files:** `matchmaker/**`、`referral/**`、Miniapp 红娘页面、Admin referral 页面。
|
||||
|
||||
- [ ] 保留红娘服务和人工推荐;验证任何工作人员不能替用户 Like。
|
||||
- [ ] 补齐转介咨询、活动、服务站的用户同意、来源追踪和状态记录。
|
||||
- [ ] 红娘只能看转介状态和必要摘要,不能读取 counseling followup 正文。
|
||||
- [x] 保留红娘服务和人工推荐;验证任何工作人员不能替用户 Like。
|
||||
- [x] 补齐转介咨询、活动、服务站的用户同意、来源追踪和状态记录。
|
||||
- [x] 红娘只能看转介状态和必要摘要,不能读取 counseling followup 正文。
|
||||
|
||||
**Gate:** 转介形成可追踪记录但不越权;用户决定权测试通过。
|
||||
|
||||
> **2026-09-16 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信。全仓库唯一的"INV-005 红娘不可代用户操作"
|
||||
> 证据是 `MatchmakerServiceTest#testMatchmakerCannotLike` 的 `assertTrue(true)` 占位,以及
|
||||
> `CoreInvariantsTest#testMatchmakerCannotLike`(断言的是 `MATCHMAKER_STATUS_*` **状态常量字符串**,
|
||||
> 与 Like 无关)—— 两者均为**名不副实的假测试**;且测试库 `schema-h2.sql` **完全缺失** `matchmaker_*` 三表,
|
||||
> 该模块**零真实行为覆盖**。逐条核对运行时路径后修复 7 处缺陷:
|
||||
> - **D1(Critical,生产故障)** `matchmaker_recommendations.status`:代码写
|
||||
> `liked`/`passed`/`confirmed_mutual`,而 `V009 chk_rec_status` 只允许
|
||||
> `pending_view/viewed/responded`,且**从未被后续迁移扩展** → 真实 PostgreSQL 上
|
||||
> 用户"接受/跳过"红娘推荐**必然 500**,P13 主流程不可用。
|
||||
> - **D2(Critical,生产故障)** `MatchmakerController.submit` 在请求未带 `serviceType` 时兜底写
|
||||
> `"recommendation"`,而 `V009 chk_matchmaker_service_type` 白名单只含 `recommend_partner` 等 7 个值
|
||||
> → 真实 PG 上提交红娘服务**必然 500**。(`MatchmakerService` 注释声明的
|
||||
> `referral_counseling`/`referral_activity`/`referral_station` 同样越界。)
|
||||
> - **D3(High)** `MatchmakerServiceService.recommendPartner` 缺 `assigned_operator_id` 归属校验
|
||||
> → 任何持 `matchmaker.service` 权限的 operator 可对**任意** serviceId 创建推荐(越权)。
|
||||
> - **D4(High)** `getServiceDetail` 无任何归属校验,任何 `matchmaker.view` 持有者可读**任意**服务的
|
||||
> 完整用户资料(displayName/gender/age/region/education/occupation/maritalStatus)→ 越权读。
|
||||
> - **D5(High)** `ReferralService.referToActivity` / `referToServiceStation` 的 `userId` 直接取自
|
||||
> 请求体且**无任何授权校验**(连 `MatchmakerServiceMapper` 都没注入)→ 任意红娘可把**任意用户**
|
||||
> 转介到任意活动/服务站,并顺带为该用户创建报名/预约(越权代操作)。
|
||||
> - **D6(High,生产故障)** `MatchmakerFollowupMapper.findByServiceId` **只有方法声明、没有 `@Select`**
|
||||
> → MyBatis 运行时抛 `Invalid bound statement (not found)`,`getServiceDetail` 必然 500,
|
||||
> 红娘工作台"查看服务详情"完全不可用。此前不可见:测试库缺 `matchmaker_followups` 表。
|
||||
> - **D7(Medium)** Admin referral 页面契约缺口:`/referrals/my-history`(C 端 UserPrincipal 端点)
|
||||
> 被运营端调用;`/matchmaker/services/operator/queue`、`/matchmaker/recommendations/operator`、
|
||||
> `PUT /matchmaker/services/{id}/assign`、`POST /matchmaker/services/{id}/recommendation`
|
||||
> 四条路径在后端**均不存在**(404)。
|
||||
> 修复:新增 `V038__align_matchmaker_status_constraints.sql`(沿用 V018/V020/V025 的
|
||||
> `DROP CONSTRAINT IF EXISTS` + 重加白名单惯例);测试库补 `matchmaker_*` 三表(约束对齐 V038);
|
||||
> D3/D4/D5 补归属校验与转介授权;D6 补 `@Select`;D7 补两个运营端端点并修正前端调用。
|
||||
> **新增守卫** `MatchmakerReferralPhase13Test`(17 用例,走真实服务方法 + 真实落库)替换假测试;
|
||||
> `MatchmakerServiceTest` 重写为**直接解析迁移 SQL** 的口径守卫(第一轮负向验证暴露"抄副本"守卫
|
||||
> 对漂移无反应,已修正);`CoreInvariantsTest` 的 INV-007/INV-010 假断言已如实改名并指向真实验证。
|
||||
> **两轮负向验证**:注入 D1(回退 `chk_rec_status` 白名单)→ 行为守卫抛 `DataIntegrityViolation`、
|
||||
> 常量守卫报 3 处 failure,守卫有效性得证。
|
||||
>
|
||||
> **全量回归实测**:`[WARNING] Tests run: 391, Failures: 0, Errors: 0, Skipped: 3` / `BUILD SUCCESS`(4 分 59 秒)。
|
||||
> Phase 12 基线 371 → 391(净 +20)。**Phase 13 已关闭。Phase 13A 未自动进入,等待用户确认。**
|
||||
> 报告:`docs/Phase-13-V11-Recovery-Completion-Report-2026-09-16.md`
|
||||
|
||||
### Phase 13A:婚恋咨询与婚前辅导 — REFACTOR/EXTEND
|
||||
|
||||
**Files:** `counseling/**`、`miniapp/pages/counseling-*`、`miniapp/pages/my-counseling/**`、`miniapp/pages/premarital-*`、`admin-web/src/modules/counseling/CounselingView.vue`、router。
|
||||
|
||||
Reference in New Issue
Block a user