Files
danyang-match/docs/STATUS.md
T
WorkBuddy ae2405f645 docs: 状态文件同步到 2026-09-18 实况(方案任务三)
- STATUS.md:顶部权威行由 "PHASE 20 COMPLETE"(09-17)更新为 09-18 口径(Phase 01~22 关闭 /
  Phase 23 部分关闭 / 三轮横向加固 / 669 tests / 停在 Phase 24 门前);版本演进表补 rc.11~rc.16;
  **合并三处重复的「V1.1 本地部署完成 (2026-09-09)」区块为一处**(996 行 → 946 行)并加
  「历史记录边界」声明;清「Phase 04~05 ⏳ 待开发」等与实测矛盾项。契约锚点全部保住
  (UI REDESIGN ACCEPTED BY USER / Phase 07 已通过用户验收 / 管理后台: http://localhost:13520/)。
- AGENTS.md + STATUS.md:UI 契约门禁口径 13/13 → **14/14**(历史时点行保留原值并注明,
  不篡改史实)。
- JIRA_BACKLOG.md:Epic 总览表补 P14/P15/P19~P23 的 ✅(P23 标「部分关闭」)。
- 客户需求基线计划:Phase 07 标题去 "UI REOPENED";Phase 10~15/19 补 ✅;Phase 20/21 勾选
  checkbox 并注日期;**Phase 22 如实标「未复验」**(口径澄清:计划的 Deployment/Ops 与 STATUS 的
  「部署运维配置扩展(Feature Flag)」是两份不同工作,后者复验结论不构成本节证据);
  Phase 23 标「部分关闭」,第 3/5 项(E2E 场景实现、CI 串联)**不虚勾**。
- PENDING_DECISIONS.md:历史部署声明 10 项按各 Phase Recovery 报告证据回写处置结果
  (9 项已关闭 / 1 项部分);补登 HTTP 与幂等检修遗留的第三方开放待决策 7 项。
- REMAINING_WORK.md:整体重写 —— 原文称 CHANGELOG 3.3MB(实为 4234 字节)、P1-3 指向从未存在的
  Phase-23-Completion-Report.md;改为「已关闭 / 仍未完成 / 原编号索引 / 验收标准」四段,保留原编号
  以便对照历史引用。
- database 两份:TABLE_INVENTORY 40 表 → **59 表**(带「来源迁移」列);MIGRATION_GUIDE
  V001~V011 → **V001~V046(46 个)**;两份均标注「以 backend/src/main/resources/db/migration/ 为准」。
2026-09-18 21:15:29 +08:00

951 lines
83 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目状态跟踪 — STATUS.md
> **2026-09-18 当前有效结论:`V1.1 RECOVERY PHASE 01~22 CLOSED / PHASE 23 PARTIALLY CLOSED / HORIZONTAL HARDENING DONE (HTTP SEMANTICS + IDEMPOTENCY + PORT/ENTRY GUARDS) / UI REDESIGN ACCEPTED BY USER / 669 TESTS GREEN / STOPPED BEFORE PHASE 24 (UAT) — AWAITING USER GO`。**
>
> 阶段 0(在途收口)、阶段 1(小程序 C 组 + discover 筛选重设计)、阶段 2(管理端 Vue 新框架适配)、阶段 3(CapabilityService 独立化)、阶段 4(双端总验收)全部完成。三端构建通过、**13/13 契约全绿**、核心 11 页面**全部 TS-only(11/11)**。**UI 重设计首批 11 页已于 2026-09-16 通过用户验收(结论:基本达标)**;`/me/*` 前后端契约同轮收敛,17 个 404 调用已恢复。**Phase 08(Like / Match / Block)、Phase 09(Text Chat)、Phase 10(Image & Chat Safety)、Phase 11(Notification)、Phase 12(Relationship Progress)、Phase 13(公益红娘转介)、Phase 13A(婚恋咨询与婚前辅导)、Phase 14(多类型公益活动)、Phase 15(活动报名、审核与签到)、Phase 16(活动互选与双方开启沟通确认)、Phase 17(举报与风控)、Phase 18(申诉)、Phase 19(统一运营后台 + 用户端公益服务页面)、Phase 20(Analytics 数据统计与管理驾驶舱)复验已关闭**,十四轮共修复 130+ 处真实缺陷(含 3 处隐藏编译缺陷),并各自补齐测试保真度与守卫。**Phase 21、22 复验已关闭(2026-09-18)**;**Phase 23 为「部分关闭」(2026-09-18)** —— 已清除 44 个 `pass` 空壳与 14 个只断言常量的假不变量测试,新增 4 个经负向注入验证的真实行为守卫与空壳阻断闸门,后端回归 655 全绿;但 **E2E 进入 CI 因需「活栈供给方式」基础设施决策而列为遗留,故不宣布「失败为零可进入 UAT」**。**Phase 23B(E2E 测试基建重建,33→49 passed)、HTTP 语义检修(失败响应携带真实状态码)、幂等键检修(`Idempotency-Key` 30 端点落地,V045/V046)均已于 2026-09-18 完成**,后端全量回归 **669 / 0 failures / 0 errors / 3 skipped**。**管理端入口已收敛到 `/admin/` 子路径(vite base + router base + 三处 nginx 接线),staging 端口 13521;UI 契约门禁 14/14 全绿。Phase 24(UAT)启动需用户确认。**
最后更新: 2026-09-18 — 分支 `main`(`feat-ui-v11` 保留为冗余锚点)
## 当前唯一有效状态
| 当前有效项 | 状态 | 证据 |
|---|---|---|
| Phase 01~06 Recovery | 已完成 | 各 Phase Completion Report;38+9+3+4+21 后端专项通过 |
| Phase 07 V1.1 首页业务与找对象 | **业务+UI 已通过用户验收**(2026-09-16) | HomeApplicationService 真实聚合;CapabilityService 独立化;discover 筛选完整重设计(5 chip + 4 section + 底部抽屉 + 滚动定位高亮);UI 按 2026-09-13 规格重新实现,11 页经用户验收通过 |
| **Phase 08 V1.1 Like / Match / Block** | **已完成**(2026-09-16) | KEEP-VERIFY 复验。修复 3 处真实缺陷:① `DiscoverService.searchUsers` 无查看者身份 → INV-004「搜索不可见」整体失效;② 详情路径无 Block 判断;③ `RelationshipService.like()` 把 `"liked"` 当 match source 写库 → 违反 `V003 chk_match_source`(H2 测试库无该约束故长期静默)。新增 `DiscoverBlockInvisibilityIntegrationTest`(9 用例,含反向拉黑);`schema-h2.sql` 补齐生产约束与 `user_profiles`;负向验证确认守卫会红。报告:`docs/Phase-08-V11-Recovery-Completion-Report-2026-09-16.md` |
| **Phase 09 V1.1 Text Chat** | **已完成**(2026-09-16) | KEEP-VERIFY 复验。修复 4 处真实缺陷:① WebSocket 下行整条链路是死代码(无握手鉴权/无 userId 写入/`sendToUser` 零调用点)→ 新增 `ChatHandshakeInterceptor` + 落库后推 `message.new`;② Unmatch 不联动会话 + 发消息只校验会话状态 → 解除后仍可发消息 → 新增 `assertMatchAlive` + `MatchController.unmatch` 联动;③ `RelationService.block` 调静态 `MatchService.unmatch`(只改内存态)→ Block 后 Match 未落库;④ 聊天四个接口无成员校验 → IDOR。新增 `ChatPhase09IntegrationTest`(11 用例)+ `ChatWebSocketHandlerTest`(7 用例);负向验证 3 处守卫精准变红。报告:`docs/Phase-09-V11-Recovery-Completion-Report-2026-09-16.md` |
| **Phase 10 V1.1 Image & Chat Safety** | **已完成**(2026-09-16) | KEEP-VERIFY 复验。**Gate 通过**。修复 2 处缺陷:① **D1(Critical,生产故障)** `PhotoService.uploadAndSave` 魔数校验因 `new byte[n]` 从不读取流而**恒失败** → 本地资格佐证上传 100% 失败;且 image-only MIME 在 local_eligibility 后无条件执行致 PDF 被挡 → 改为 `readNBytes` 真读取 + MIME 按 photoType 分流 + PDF 跳过图片魔数;② **D2(Low)** `ChatSafetyService` 把命中的高风险词写入 warn 日志 → 改为不记具体词汇。**推翻旧报告**「伪装恶意图片被拒(Magic Number校验)」与「EXIF清理预留(stripExif占位,符号不存在)」两声明。新增 `PhotoUploadValidationTest`(6 用例,`MockMultipartFile` 真走校验链路)+ 负向验证精准变红。报告:`docs/Phase-10-V11-Recovery-Completion-Report-2026-09-16.md` |
| **Phase 11 V1.1 Notification** | **已完成**(2026-09-16) | KEEP-VERIFY 复验。Gate 部分通过。修复 3 处缺陷:① **D3(Critical,生产故障)** `NotificationService` 全部 10 种通知传入复合 type(`appointment_submitted`/`counseling_assigned`/`le_verified` 等),违反生产 `chk_notification_type`(仅允许短名)→ 真实 PG 上**全部落库失败**,Phase 11 核心交付不可用;测试库未复刻该约束故长期静默 → type 归一为白名单短名 + 测试库补约束;② **D1(High)** 幂等仅靠 SELECT-then-INSERT 无 DB 兜底 → 新增 `V036__add_notification_idempotency_index.sql`(partial unique index);③ **D2(Medium)** 婚前辅导排期通知零调用 + 管理端排期路径完全不发通知 → 接线并按 service_type 分流。新增测试 12 用例(含**真实调用模板方法**的 type 守卫)。报告:`docs/Phase-11-V11-Recovery-Completion-Report-2026-09-16.md` |
| 阶段 0 在途收口 | 已完成 | 56 个改动分类提交为 7 个 commit;Git 清零;Flyway 实际 V036 已登记 |
| 阶段 1 小程序 C 组 + discover | 已完成 | C 组 content/anti-fraud/service-station 迁 TS 唯一源;discover 筛选从参数到 UI 完整重写 |
| 阶段 2 管理端 Vue 适配 | 已完成 | 18 modules + 22 routes + vue-tsc 全绿 + vite build 11.68s |
| 阶段 3 CapabilityService 独立化 | 已完成 | New `capability` 模块:CapabilityService(getCapabilities + 公共判断方法)+ CapabilityController(GET /api/v1/capabilities);HomeApplicationService 完全委托 |
| 阶段 4 双端总验收 | **已完成**(2026-09-14) | 三端构建全绿 + 13/13 契约全绿 + 源码健康检查通过;验收报告见 docs/superpowers/plans/2026-09-14-phase4-acceptance-report.md |
| Flyway 迁移 | V001~V046 | V028~V046 已纳入 STATUS;V037 为 Phase 12 新增(实体列与生产迁移对齐,23 表 50 列);V038 为 Phase 13 新增(`matchmaker_recommendations.status` + `matchmaker_services.service_type` 的 CHECK 白名单扩展);V039 为 Phase 13A 新增(counseling 幂等键 + 三个 CHECK 白名单显式固化);V042 为 Phase 19 新增(`service_location_announcements` 服务站临时公告表);V043 为 Phase 20 新增(授予 `data_viewer` / `platform_admin` 的 `analytics.view`);V045 为幂等键检修新增(`idempotency_records` 通用幂等表 + 唯一索引 `uk_idempotency_scope`);V046 修正其 `actor_id` 列类型(VARCHAR → uuid) |
| Backend 全量回归 | **已清偿**(最新:2026-09-18 **669 / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS**) | 离线容器(`danyang-match-backend-test`)`mvn -o test` 实测;**2026-09-18 幂等键检修订正后为 669**(HTTP 语义检修 664 → 幂等检修 +5:`GlobalExceptionHandlerTest` 3→6、新增 `IdempotencyDeclarationGuardTest` 2)。历史:2026-09-17 Phase 20 为 648;含 `CanonicalRouteContractTest`、`ChatContractJsonTest`、`MeRouteContractTest`、`DiscoverBlockInvisibilityIntegrationTest`、`ChatPhase09IntegrationTest`、`ChatWebSocketHandlerTest`、`PhotoUploadValidationTest`、`NotificationPhase11IntegrationTest`、`NotificationTemplateTypeGuardTest`、`NotificationPrivacyCopyTest`、`EntityMigrationParityTest`、`RelationshipProgressPhase12Test`、`HomePremaritalGuidancePhase12Test`、`MatchmakerReferralPhase13Test`、`MatchmakerServiceTest`、`ReportAndRiskPhase17IntegrationTest`、`AppealPhase18IntegrationTest`(Phase 18 新增 15 例:申诉真实落库+审计、仅 ban/suspend 可申诉、幂等、**Gate A 通过只解除目标处置**、**Gate B 拒绝维持原处置**、原子认领唯一赢家、二次处理被拒、escalate 后可再决策、appealType 白名单/一致性/缺省推导、证据字段映射、软删过滤、Feature Flag 关闭拦截)、`MetricCatalogGuardTest`(11)、`AnalyticsMetricsPhase20IntegrationTest`(21)、`AnalyticsSoftDeleteGuardTest`(4)、`AnalyticsPermissionGrantTest`(6)、`LocalEligibilityStatusVocabularyGuardTest`(9)、`ApiResponseCodeHttpStatusTest`(6)、`SecurityPathCoverageTest`(2)、`IdempotencyDeclarationGuardTest`(2) |
| 路由/字段契约收敛 | **已完成**(2026-09-15) | 字段:会话 `target*` + `sentAt` + `relationStatus`(commit `687a156`);路径:采用 2026-09-14 canonical(`/likes` `/passes` `/blocks` `/matches`,缘分保留 `/relations/fate/*`),旧路径与 `success` 桩实现已移除;裁决由 `CanonicalRouteContractTest` 锁定 |
| `/me/*` 路径族 | **已完成**(2026-09-16) | 小程序按 REST 规范(§16 / §22-§40 / §80 / §83-§84)调用 `/me/*`,后端此前**无 `/me` 基路径**致 17 个调用 404。新增 `MeController` 委托既有 service 暴露规范路径,旧路径全部保留,小程序三条历史写法(`/me/privacy-settings`、`/me/photos/{id}/main`、`/me/appeals`)一并兼容;由 `MeRouteContractTest` 锁定 |
| Admin Web | **验证通过** | 2026-09-14 阶段 4:vue-tsc ✅、vite build ✅ 11.68s;18 modules 齐全;壳层+工作台通过参考图 QA |
| Miniapp | **验证通过** | 2026-09-16:tsc ✅;**11 核心页全部 TS-only(11/11)**;首批 11 页于 2026-09-16 通过用户验收;discover 筛选重设计已通过 DevTools 验证 |
| UI 契约测试 | **13/13 通过** | 2026-09-16 运行:全部退出码 0;含 capability 独立化适配与文档基线口径 |
| Git 工作区 | **已清零** | 阶段 0~4 共 24+ commit 可追溯;`git status --porcelain` 0 行 |
| 核心待清债务 | 0 项 | 已全部清偿:3 页 JS→TS 迁移、backend 全量回归(420 tests)、DevTools 真机截图留档(2026-09-14)、`/me/*` 路径族收敛(2026-09-16)、实体↔生产迁移漂移修复(V037/V038/V039,2026-09-16/17) |
| UAT / RC / Production | **Phase 01~22 复验关闭;Phase 23 部分关闭;停在 Phase 24(UAT)门前** | 后端 **669 / 0 failures / 0 errors / 3 skipped**;UI 契约门禁 **14/14**;管理端入口收敛至 `/admin/` 子路径(staging 13521);HTTP 语义 + 身份收敛 + 幂等键三轮横向加固完成。**Phase 24 启动需用户确认** |
> **下一阶段计划(唯一)**:`docs/superpowers/plans/2026-09-18-phase23-closeout-and-uat-readiness.md`
> —— 批 1 快速收尾(ui-tests 接入 CI)/ 批 2 Phase 23 剩余(E2E 实现 + CI 串联,**需基础设施决策**)/
> 批 3 代码级遗留清偿 / 批 4 UAT 就绪(**需用户协作**)/ 批 5 Phase 25-26 前置登记。
---
## 版本演进
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0.0-RC.2 | 2026-09-01 | V1.0 核心功能冻结 |
| 1.1.0-dev | 2026-09-08 | V1.1 基线搭建启动(Phase 01 进行中) |
| 1.1.0-rc.3 | 2026-09-16 | Phase 08~12 复验关闭;新增 V037 对齐实体↔生产迁移;全量回归 371 tests 全绿 |
| 1.1.0-rc.4 | 2026-09-16 | Phase 13 复验关闭(公益红娘转介,修复 7 处缺陷);新增 V038 扩展 matchmaker CHECK 白名单;全量回归 **391 tests** 全绿 |
| 1.1.0-rc.5 | 2026-09-17 | Phase 13A 复验关闭(婚恋咨询与婚前辅导,9 处缺陷 + 4 处测试基建缺陷);新增 V039;全量回归 **420 tests** 全绿 |
| 1.1.0-rc.6 | 2026-09-17 | Phase 14 复验关闭(多类型公益活动,11 处后端缺陷 + 3 处前端契约缺陷 + 2 处测试保真度缺陷);新增 `ActivityManagementView` 动态表单;全量回归 **450 tests** 全绿 |
| 1.1.0-rc.7 | 2026-09-17 | Phase 15 复验关闭(活动报名/审核/签到,16 处缺陷:含**签到码一生成即作废**、**取消后永远无法再报名**两处必崩;3 处测试保真度);新增 V040 `activity_staff_assignments` 与 `ActivityCheckinView` 签到工作台;全量回归 **474 tests** 全绿 |
| 1.1.0-rc.8 | 2026-09-17 | Phase 16 复验关闭(活动互选与双方开启沟通确认,7 处缺陷 + 1 处隐藏编译缺陷 + 1 处测试保真度:含**双确认后根本不建 Match/会话(Gate 缺陷)**、**Phase 15 提交态引用未定义 `reopenEpisode` 致模块不编译("474 绿"为假象)**、**INV-006 单向意向泄露**、**复用/新建 Match 后缺会话**;统一双实现到 `RelationshipService.confirmActivityInterest`;新增 V041 `expires_at`+`match_id`;新建 `ActivityMutualConsentServiceTest`(7 用例);全量回归 **481 tests** 全绿 |
| 1.1.0-rc.9 | 2026-09-17 | Phase 17 复验关闭(举报与风控,6 处真实缺陷:含**D1 测试库缺 reports/risk_events/risk_actions 三表致风控/举报真实 DB 路径零覆盖(必崩级盲区)+ ReportServiceTest 假绿**、**D3 敏感访问(查看他人风险画像/举报)无审计(AGENTS.md #8)**、**D4 审计缺 ip/userAgent**、**D5 findByUserId 未过滤软删**、**D2 人工标记无审计**、**D6 javax→jakarta 隐藏编译缺陷 + risk_events 漏 updated_at**);补齐三表并移出白名单入 REQUIRED_IN_TEST_SCHEMA;新增 `AuditLogService.recordSensitiveAccess` 并接线三端点;新增 `ReportAndRiskPhase17IntegrationTest`(7 用例);全量回归 **488 tests** 全绿 |
| 1.1.0-rc.10 | 2026-09-17 | Phase 18 复验关闭(申诉,8 处真实缺陷:含**D1 测试库缺 appeals 表 + AppealServiceTest 6 处 assertTrue(true) 假绿 → 申诉真实 DB 路径零覆盖**、**D2 escalate 向 operator 发用户通知撞 notifications.user_id→users(id) FK → PG 上升级 100% 失败**、**D3 appealType 未校验生产 chk_appeal_type**、D4 escalated 死胡同、D5 processAppeal 先读后写并发竞态、D6 三处查询漏软删过滤、D7 硬编码 resolved、D8 证据字段契约 evidenceFileIds);补 appeals 表并移出白名单入 REQUIRED_IN_TEST_SCHEMA;新增原子认领 `markReviewingIfProcessable`;新增 `AppealPhase18IntegrationTest`(15 用例),删除假绿 `AppealServiceTest`(9 用例);全量回归 **494 tests** 全绿;admin-web `vue-tsc` EXITCODE=0 |
| 1.1.0-rc.11 | 2026-09-17 | Phase 19 复验关闭(统一运营后台 + 用户端公益服务页面,修复 25 处真实缺陷:服务站公告整条不可达、服务站越权写、Banner 500、Content 发布死路、ServiceProgram 审批死路等);新增 V042 `service_location_announcements`;全量回归 **602 tests** 全绿 |
| 1.1.0-rc.12 | 2026-09-17 | Phase 20 复验关闭(Analytics,口径造假 / 死代码 / 系统性软删缺陷 D12 修复 45 处 / 权限授予脱节);新增 V043 `analytics.view` 授权;指标字典 `docs/ANALYTICS_METRICS.md` + `MetricCatalogGuardTest`;全量回归 **648 tests** 全绿 |
| 1.1.0-rc.13 | 2026-09-18 | Phase 21 复验关闭(账户生命周期,6 处缺陷:CLOSED 可登录、注销 TODO 桩 ×2、匿名化死代码等)+ Phase 22 复验关闭(Feature Flag,D-22-A/B 修复;T01~T05 死配置如实登记);全量回归 **657 tests** 全绿 |
| 1.1.0-rc.14 | 2026-09-18 | Phase 23 **部分关闭**(44 个 `pass` 空壳清除、4 个真实 INV 行为守卫、空壳阻断闸门);Phase 23B E2E 基建重建(conftest + seed + CI e2e job,本机活栈 33 passed);全量回归 **655 tests** 全绿 |
| 1.1.0-rc.15 | 2026-09-18 | HTTP 语义检修(105 处错误响应携带真实状态码,回归 664)→ 身份收敛(运营身份禁入用户端 + PathPattern 守卫)→ 幂等键检修(`Idempotency-Key` 30 端点落地,V045/V046,前端 25 处调用点修正,E2E 49 passed);admin 端口收敛 13520(vite / 文档 / 生产 compose 三处一致);全量回归 **669 / 0 / 0 / 3** 全绿 |
| 1.1.0-rc.16 | 2026-09-18 | 管理端入口收敛(承接 rc.15 的端口收敛):staging admin 端口 3001 → **13521**(保持「生产 + 1」,同步 `run-uat.sh` 默认入口);管理端产物改为 **`/admin/` 子路径部署**(vite 构建 base + router history base + 三处 nginx 接线统一为「不剥离前缀」转发);**修复生产 nginx `/admin/` 的假成功**——原 `alias` 指向 `nginx:alpine` 自带默认页目录,访问返回 200 + nginx 欢迎页(比 404 更难发现),已改为 `upstream admin_web` + `proxy_pass` 并以真实两跳容器实测;补修 `run-uat.sh` 被截断的尾部(原文件语法不完整、无法运行)并把 `ADMIN_URL` 接到管理端可达性实测;品牌资源引用统一走 `src/brand.ts` 的 `BASE_URL` 拼接(原 5 处写死根路径,子路径下会裂图),favicon 由不存在的 `/favicon.svg` 改为存在的品牌标;UI 门控 **14/14 绿**,新增端口/入口断言 6 条(全部经负向注入验证) |
---
## V1.0 基线状态
> **历史记录边界:** 从本节起至文件末尾均为 2026-09-09 重新审查前的开发日志,仅用于追溯,不代表当前验收状态;其中所有 `✅`、`已完成`、`已部署`、测试数量和运行地址均须在对应新 Phase Completion Report 中重新举证。当前唯一有效状态如下。
| 当前有效项 | 状态 | 证据 |
|---|---|---|
| Phase 01 项目治理与检查基线 | 已交付,带阻断 | `scripts/verify-phase01.ps1` 可重复执行并真实返回 5 个失败门禁;详见 `Phase-01-V11-Recovery-Completion-Report-2026-09-09.md` |
| Git 基线 | 阻断 | 当前目录及父目录均无 `.git`,未擅自初始化新仓库 |
| Admin Web | 部分通过 | production build 通过;type-check 失败(3 个错误) |
| Miniapp | 失败 | TypeScript 检查失败(27 个错误) |
| Backend | 未验证 | 本机无 JDK/Maven,Docker Desktop 当前未运行 |
| V1.1 E2E | 失败 | 1 passed、26 failed、48 errors、9 warnings |
| Phase 02 及以后 | 未开始 | 等待 Phase 01 门禁确认 |
| UAT / RC / Production | NO-GO | 构建、权限、E2E 与页面闭环未通过 |
---
## 历史状态记录(仅供追溯,不作为验收证据)
| Phase | 名称 | 状态 |
|-------|------|------|
| P01~P26 | 全部核心功能 | **已完成** ✅ |
| 不变量 INV-001~010 | 核心不变量 | **23/23 通过** ✅ |
| 权限矩阵 9角色×18权限 | RBAC+DataScope | **已通过** ✅ |
| API 测试 | 16/16 | **通过** ✅ |
| 代码审查问题 | 16项 | **全部清零** ✅ |
| Demo数据 | 12用户+活动+红娘 | **已就绪** ✅ |
---
## V1.1 当前进度
### Phase 01 — V1.1 基线搭建 ✅ 已完成
| 任务 | 状态 |
|------|------|
| AGENTS.md 更新至 V1.1 | ✅ |
| STATUS.md 更新至 v1.1.0-dev | ✅ |
| PENDING_DECISIONS.md 新增V1.1 pending | ✅ |
| JIRA_BACKLOG.md 创建 | ✅ |
| 测试骨架(6个spec文件) | ✅ |
| Phase-01-V11-Completion-Report | ✅ |
### Phase 02 — Auth + Operator + RBAC 扩展 ✅ 已完成
| 任务 | 状态 |
|------|------|
| V015 迁移:4角色+30权限 | ✅ |
| Demo Seed 扩展:3新操作员 | ✅ |
| 角色权限分配(含边界约束) | ✅ |
| JIRA_BACKLOG 更新 | ✅ |
### Phase 03 — 实名认证扩展(人脸核验预留) ✅ 已完成
| 任务 | 状态 |
|------|------|
| V016 迁移:verification_level/liveness/provider | ✅ |
| UserIdentity 实体扩展 | ✅ |
| Feature Flag 系统配置(8项) | ✅ |
| Demo Seed 扩展 | ✅ |
### Phase 04 — Profile + Preference + 本地资格 ✅ 已完成
| 任务 | 状态 |
|------|------|
| V017 迁移:local_eligibility 表 | ✅ |
| Entity + Mapper(LocalEligibility/Evidence) | ✅ |
| API:GET/POST declaration/evidences/submit | ✅ |
| /me/status 扩展 localEligibilityStatus | ✅ |
| Miniapp U62 本地资格说明页 | ✅ |
| Miniapp U63 本地资格补充页 | ✅ |
| AuthService 注入 LocalEligibilityMapper | ✅ |
### Phase 05 — 审核模块扩展(本地资格) ✅ 已完成
| 任务 | 状态 |
|------|------|
| V018 迁移:review_type 扩展 local_eligibility | ✅ |
| ReviewService 新增本地资格审核方法 | ✅ |
| LocalEligibilityService 集成审核流程 | ✅ |
| SensitiveAccessLog 佐证访问审计 | ✅ |
| Constants 新增 REVIEW_TYPE_LOCAL_ELIGIBILITY | ✅ |
### Phase 06 — Match Engine 扩展(本地资格 Eligibility) ✅ 已完成
| 任务 | 状态 |
|------|------|
| MatchEligibilityService 接入本地资格检查 | ✅ |
| MatchRuleConfigProperties 新增 localEligibilityRequired | ✅ |
| LocalEligibilityService 缓存失效处理 | ✅ |
| eligibility test matrix 扩展 | ✅ |
### Phase 07 — V1.1首页重构 + 找对象 ✅ 已完成
| 任务 | 状态 |
|------|------|
| HomeApplicationService + HomeDTO | ✅ |
| GET /api/v1/home 聚合接口 | ✅ |
| V019 Banner + ServiceLocation 迁移 | ✅ |
| BannerService(时间/受众过滤) | ✅ |
| HomeController | ✅ |
| Miniapp 首页完整重构(U18 V1.1) | ✅ |
| 5种用户状态首页适配 | ✅ |
### Phase 08 — Like / Match / Block ✅ 已完成(2026-09-16 复验关闭)
| 任务 | 状态 |
|------|------|
| MATCH_SOURCE常量定义 | ✅ |
| createMatch 重载(autoCreateConversation参数) | ✅ |
| confirmActivityInterest 方法 | ✅ |
| ActivityInterest.hasMutualInterest 方法 | ✅ |
| ActivityInterestController 新增confirm接口 | ✅ |
| INV-014/015 不变量保障(不自动建Chat) | ✅ |
| 通知文案更新(V1.1二阶段确认规则) | ✅ |
| **INV-004 搜索不可见(双向)修复** | ✅ 新增(复验发现原实现完全绕过 Block) |
| **详情路径 Block 拦截(双向 → 404)** | ✅ 新增(复验发现两条详情路径均无检查) |
| **`matches.source` 取值越界修复** | ✅ 新增(`"liked"` → `MATCH_SOURCE_USER_LIKE`) |
| **测试库保真度对齐(`chk_match_source` + `user_profiles`)** | ✅ 新增 |
| **`DiscoverBlockInvisibilityIntegrationTest`(9 用例)** | ✅ 新增 |
### Phase 09 — Text Chat 验证 ✅ 已完成
| 任务 | 状态 |
|------|------|
| Activity Match source 聊天兼容性验证 | ✅ |
| 消息幂等性验证(client_message_id唯一索引) | ✅ |
| INV-002/003 不变量验证 | ✅ |
| WebSocket 推送机制确认 | ✅ |
| REST Send + WS Receive 架构确认 | ✅ |
### Phase 10 — Image & Chat Safety ✅ 已完成
| 任务 | 状态 |
|------|------|
| ChatController 限流检测集成 | ✅ |
| MessagingService 风险关键词检测接入 | ✅ |
| insertRiskNotice 高风险消息系统通知 | ✅ |
| sendChatSafetyTip 首次聊天安全提示 | ✅ |
| POST /messages/conversations/{id}/safety-tip API | ✅ |
| ChatController safety-tip 端点 | ✅ |
### Phase 11 — 公益服务通知扩展 ✅ 已完成
| 任务 | 状态 |
|------|------|
| V020 迁移:通知类型扩展(6种新类型) | ✅ |
| Constants 新增 5 个 NOTIFICATION_TYPE | ✅ |
| NotificationService 新增 10 个业务通知方法 | ✅ |
| ReviewService 集成本地资格审核通知 | ✅ |
| 隐私安全文案(中性化,不暴露敏感信息) | ✅ |
### Phase 14 — 多类型公益活动 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| ActivityType 分类 + 按类型报名策略(实名/本地资格/性别名额) | ✅ |
| 容量原子扣减(`insertIfCapacityAvailable` / `approveIfCapacityAvailable`) | ✅ 新增 |
| `activityType` / `orgRole` 生产 CHECK 白名单校验(D3) | ✅ 新增 |
| 多组织关系 + 容量分组落库与回读 | ✅ |
| 运营端:`/operator/activities` 建活动改走 V1.1;组织/分组 4 端点;列表补 `activityType` | ✅ |
| 用户端:删除 3 个错挂的运营写入端点(双实现) | ✅ |
| Miniapp:分类 Tabs code 对齐生产白名单(6 类)+ 类型化卡片 + 差异化资格提示 | ✅ |
| Admin:`ActivityManagementView.vue` 类型驱动动态表单 + `/activities` 路由与导航 | ✅ 新增 |
| INV-020:组织接口零用户字段;报名列表仅运营端且要求 `activity.view` | ✅ |
| 测试库补齐 V023 列/约束 + 三张缺失表;activity 五表移入必选集合 | ✅ |
| 测试:`ActivityPhase14Test`(23)+ `ActivityConstraintGuardTest`(9,解析真实 DDL 与前端源码) | ✅ 新增 |
| 全量回归 **450 tests 全绿** | ✅ |
### Phase 15 — 活动报名、审核与签到 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| **D1 必崩**:签到码一生成即作废(`generate` 写 `"used"` → 扫码 100% 失败)→ 改为 `issued` | ✅ |
| 重复签到:原子条件更新 `checkinIfNotCheckedIn` + 幂等返回 `alreadyCheckedIn` | ✅ 新增 |
| **D9 必崩**:取消/拒绝后重报名撞 `UNIQUE(activity_id,user_id)` → 复用记录 `reuseIfCapacityAvailable` | ✅ |
| 审核/取消原子化:`rejectIfPending` / `cancelIfActive`;取消补审计日志 | ✅ |
| 后台报名列表含 pending(原只查 approved,审核页无待审项) | ✅ |
| 报名窗口 `registration_start_at` / `registration_end_at` 生效 | ✅ 新增 |
| 容量分组真正参与扣减(`incrementIfAvailable` / `decrementIfPositive`) | ✅ 新增 |
| 计划项③:V040 `activity_staff_assignments` + 签到/审核数据范围校验(INV-020) | ✅ 新增 |
| Admin:`ActivityCheckinView.vue` 签到工作台 + `/activities/checkin` 路由与导航 | ✅ 新增 |
| Miniapp:`cancelRegistration` 封装(后端端点存在但前端无入口) | ✅ |
| 测试库补齐报名表 UNIQUE + 两个 CHECK;两表移入必选集合;迁移基线 39→40 | ✅ |
| 测试:`ActivityPhase15Test`(21)+ `CheckinServiceTest` 假绿改真实守卫(5)+ 约束守卫(2) | ✅ 新增 |
| 全量回归 **474 tests 全绿** | ✅ |
### Phase 16 — 活动互选与双方开启沟通确认 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| **D1(Critical,Gate 缺陷 · INV-014/015)** 双确认后不建 Match/会话 | ✅ 重写 `confirmConnection` 走 `confirmActivityInterest`,exactly-once(`both_confirmed_at` NULL→非NULL 仅一方赢家建 Match+会话并 `bindMatch`) |
| **D2(High,双实现分裂)** 旧/新路径各自为政 | ✅ 统一到 `RelationshipService.confirmActivityInterest`(返回 `matchId` + `priorUnmatch`) |
| **D3(High,隐藏编译缺陷 · 必崩级)** Phase 15 引用未定义 `matchMapper.reopenEpisode` | ✅ `MatchMapper` 补 `@Update reopenEpisode`(`WHERE status='unmatched' AND deleted_at IS NULL`);**Phase 15 提交态从未真正编译通过** |
| **D4(High,INV-006 泄露)** 本侧未确认即回显对方确认态 | ✅ `getMyConsentStatus` 改 `partnerAccepted = myAccepted && partnerSideAccepted` |
| **D5(Medium,缺会话)** 复用/新建 Match 后未显式开启会话 | ✅ `confirmActivityInterest` 显式 `getOrCreateConversation` 并返回 `conversationAutoCreated=true` |
| **D6(Medium,测试库零覆盖)** 缺 `activity_mutual_connection_consents` 表 | ✅ `schema-h2.sql` 补表(对齐 V024+V037+V041);`EntityMigrationParityTest` 移入 `REQUIRED_IN_TEST_SCHEMA`;`MigrationValidationTest` 基线 40→41 |
| **D7(Medium,无互选测试)** | ✅ 新建 `ActivityMutualConsentServiceTest`(7 用例,走真实方法路径) |
| **D8(Medium,断言与 #20 冲突)** `ChatPhase09IntegrationTest:344` 假设每次新建独立会话 | ✅ 改为 `assertEquals`(认可 AGENTS.md #20 复用语义),保留"复用同一消息管线"主断言 |
| 负向验证(注释 createMatchAndConversation → 2 用例精准变红并还原) | ✅ 守卫有牙 |
| 新增 V041 `expires_at`+`match_id` 迁移 | ✅ |
| 全量回归 **481 tests 全绿** | ✅ |
> **2026-09-17 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信。活动互选存在**核心 Gate 缺陷**——双确认后根本不建 Match/会话(INV-014/015);
> 且 Phase 15 提交态引用未定义的 `reopenEpisode`,**整个模块从未编译通过**,"474 绿"是假象。已统一双实现到
> `RelationshipService.confirmActivityInterest`,修复 7 处缺陷 + 1 处隐藏编译缺陷 + 1 处测试保真度缺陷,新建 7 用例互选测试,
> 并经负向验证证明守卫有牙。报告:`docs/Phase-16-V11-Recovery-Completion-Report-2026-09-17.md`
### Phase 17 — 举报与风控 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| **D1(Critical,必崩级测试盲区)** `reports`/`risk_events`/`risk_actions` 三表在 H2 缺失 → 风控/举报真实 DB 路径零覆盖;`ReportServiceTest` 全是 `assertTrue(true)` 假绿 | ✅ `schema-h2.sql` 补齐三表(对齐 V012,去外键留 CHECK);`EntityMigrationParityTest` 移出 `TEST_SCHEMA_OPTIONAL_TABLES` 入 `REQUIRED_IN_TEST_SCHEMA` |
| **D3(High,敏感访问无审计 · AGENTS.md #8)** 查看他人风险画像/举报详情不记录审计 | ✅ 新增 `AuditLogService.recordSensitiveAccess`;`getReportDetail`/`getUserRiskProfile`/`RiskController.getRiskEvents` 三端点接线 |
| **D4(Medium,审计完整性)** `saveAuditLog` 未填 `ip`/`userAgent` | ✅ 增强补全(与 `AuthorizationAuditListener` 同模式取 `RequestContextHolder`) |
| **D5(Medium,数据一致性)** `findByUserId` 未过滤 `deleted_at` | ✅ 补 `deleted_at IS NULL`(与 `sumScoreByUserId` 一致) |
| **D2(Medium,审计缺失)** `manualFlagRisk` 人工标记无审计 | ✅ 注入 `AuditLogMapper`,写 `MANUAL_FLAG_RISK` |
| **D6(隐藏编译缺陷)** `javax.servlet` → Spring Boot 3.x 已迁移 `jakarta.servlet`;`risk_events` 漏 `updated_at` 列 | ✅ 三处 import 改 jakarta;`risk_events` 补 `updated_at` |
| 来源接入代码层(detectCounselingRisk/detectAppointmentRisk/detectActivityRisk)运行时已被调用,非假绿 | ✅ 确认(不重写来源逻辑) |
| 最小可见(INV-006 同族):后台风险页不暴露无关咨询正文 | ✅ 延续既有约束 |
| 负向验证(注释 getReportDetail 敏感访问审计 → D3 守卫精准变红并还原) | ✅ 守卫有牙 |
| 新增 `ReportAndRiskPhase17IntegrationTest`(7 用例) | ✅ |
| 全量回归 **488 tests 全绿** | ✅ |
> **2026-09-17 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信。风控/举报整条真实 DB 路径因测试库缺三表而**零覆盖**,`ReportServiceTest`
> 假绿掩盖盲区;且敏感访问(查看他人风险画像/举报)此前**无审计**(违反 AGENTS.md #8 默认拒绝 + 查看需审计)。已修复 6 处真实缺陷
> (含 1 处必崩级测试盲区、1 处隐藏 jakarta 编译缺陷),补齐三表并新增 7 例集成测试,负向验证证明守卫有牙。报告:`docs/Phase-17-V11-Recovery-Completion-Report-2026-09-17.md`
### Phase 18 — 申诉 ✅ 已完成(2026-09-17 KEEP-VERIFY 复验通过)
| 任务 | 状态 |
|------|------|
| **D1(Critical,必崩级测试盲区)** `appeals` 表缺失 + `AppealServiceTest` 9 例中 6 例 `assertTrue(true)` 假绿 → 申诉真实 DB 路径零覆盖 | ✅ 补 `appeals` 表(对齐 V013,去外键留 `chk_appeal_status`/`chk_appeal_type`);移出白名单入 `REQUIRED_IN_TEST_SCHEMA`;删除假绿测试,新建 `AppealPhase18IntegrationTest`(15 例) |
| **D2(High,生产故障 · 只在 PG 上炸)** `escalateAppeal` 向 `operatorId` 发用户通知 → 撞 `notifications.user_id → users(id)` FK(operators 与 users 不同表)→ 升级事务整体回滚 | ✅ 移除非法通知;升级后进入后台待办队列由风控员决策 |
| **D3(High,生产故障 · 只在 PG 上炸)** `appealType` 未校验 `chk_appeal_type` 白名单 | ✅ 校验白名单 + 必须与处置类型一致;缺省按处置类型推导 |
| **D4(Medium,功能死胡同)** `escalated` 无法再处理(后端只收 pending/reviewing;前端按钮仅 pending) | ✅ 后端原子认领放行 escalated;`getPendingAppeals` 返回 pending+escalated;前端放开处理入口 |
| **D5(Medium,并发)** `processAppeal` 先读后写无原子守卫 → 并发双处理相互覆盖 | ✅ 新增 `markReviewingIfProcessable` 原子认领,仅赢家继续 |
| **D6(Low,一致性)** `findByUserId`/`findPending`/`findByStatusPaged` 未过滤 `deleted_at` | ✅ 三处补 `deleted_at IS NULL` |
| **D7(Low)** `approveAppeal` 硬编码 `"resolved"` | ✅ 改用 `Constants.RISK_ACTION_STATUS_RESOLVED` |
| **D8(Low,前后端契约)** miniapp 传 `evidenceFileIds`、后端只读 `evidence` | ✅ DTO 增 `evidenceFileIds`,服务层序列化映射进 `evidence` |
| 负向验证(误伤其他处置 → Gate 用例精准变红并还原) | ✅ 守卫有牙 |
| admin-web `vue-tsc --noEmit` EXITCODE=0 | ✅ |
| 全量回归 **494 tests 全绿** | ✅ |
> **2026-09-17 复验结论(KEEP-VERIFY)**:历史 ✅ 不可信。申诉整条真实 DB 路径因测试库缺 `appeals` 表而**零覆盖**,`AppealServiceTest` 的
> 6 处 `assertTrue(true)` 假绿恰好掩盖 Gate 四条不变量;且 `escalate` 向 operator 发用户通知会撞 `notifications.user_id → users(id)` FK
> (PG 上升级 100% 失败)、`appealType` 未校验生产 CHECK 白名单。已修复 8 处真实缺陷(含 1 处必崩级测试盲区、2 处「只在 PG 上炸」的生产故障),
> 补齐 `appeals` 表并新增 15 例集成测试、删除 9 例假绿,负向验证证明 Gate 守卫有牙。报告:`docs/Phase-18-V11-Recovery-Completion-Report-2026-09-17.md`
### Phase 13A — 公益婚恋咨询与婚前辅导(核心链路)✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| V022 counseling_services + counseling_followups 迁移 | ✅ |
| **V039 Phase 13A 迁移**(counseling 幂等键 + 三个 CHECK 白名单显式固化) | ✅ 新增 |
| `CounselingService`(权威实现,合并孤儿类 `CounselingServiceApp` 后删除) | ✅ 重写 |
| 用户端 API:intro / create / list / detail / cancel / companion-confirm | ✅ |
| 后台 API:queue / assigned / detail / assign / schedule / start / followup / complete | ✅ 8 端点 |
| INV-012 Counselor assigned scope 实现(`assignIfPending` 条件更新防并发覆盖) | ✅ |
| INV-013 正文保护(脱敏分层:user/assigned=全文;matchmaker/operator=脱敏;manager=摘要无 followups) | ✅ |
| INV-005 伴侣须本人确认 | ✅ |
| 合法状态机 `ALLOWED_TRANSITIONS` + `assertTransition` | ✅ 新增 |
| 幂等(`idempotencyKey` + `uk_counseling_idem` 唯一索引) | ✅ 新增 |
| Miniapp U55-U59 页面(咨询介绍/申请/我的/婚前辅导),字段名对齐后端 + 检查 `success` | ✅ |
| Admin `CounselingView.vue` 重写(四态 + 二次确认)+ `/counseling` 路由注册 | ✅ |
| 测试:`CounselingPhase13ATest`(25)+ `CounselingConstraintGuardTest`(5) | ✅ 新增 |
| 全量回归 **420 tests 全绿** | ✅ |
### Phase 13 — 公益红娘服务转介 ✅ 已完成
| 任务 | 状态 |
|------|------|
| P13-V11-T01 转介婚恋咨询(service_type扩展 + request_source) | ✅ |
| P13-V11-T02 转介公益活动(activity_registrations.source字段) | ✅ |
| P13-V11-T03 转介善缘服务站(service_appointments表 + 转介追踪) | ✅ |
| P13-V11-T04 referral source tracking(Constants常量 + DB字段) | ✅ |
| P13-V11-T05 user consent/confirmation(confirmReferral 两阶段确认) | ✅ |
| V021 数据库迁移(service_appointments + activity_registrations扩展) | ✅ |
| ServiceAppointment Java 模块(Entity/Mapper/Service/Controller) | ✅ |
| ReferralService + ReferralController(转介核心逻辑) | ✅ |
| NotificationService 转介通知方法 | ✅ |
| Constants 新增转介来源常量 | ✅ |
| INV-005 红娘不可代用户操作验证 | ✅ |
### Phase 12 — 关系状态轻量扩展 ✅ 已完成(2026-09-16 KEEP-VERIFY 复验通过)
| 任务 | 状态 |
|------|------|
| Successful首页服务建议(婚前辅导引导) | ✅ |
| GettingToKnow服务建议规则 | ✅ |
| Counseling recommendation rules | ✅ |
| 成功关系双确认 / 恢复 / 退出 / 历史 Episode / 并发确认 | ✅ 行为测试 14 项 |
| getting_to_know 阶段婚前辅导入口引导(计划项 2) | ✅ 已接线 `HomeApplicationService.buildServiceRecommendations` |
| 工作人员不能替用户确认成功关系(INV-005) | ✅ 非成员路径断言抛业务异常 |
> **2026-09-16 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信,逐条核对运行时路径后修复 4 处缺陷:
> - **D1(Critical,生产故障 · 同一族系统性缺陷)** 实体与生产迁移**系统性漂移**:23 张表、50 个列在
> `db/migration` 中根本不存在,而测试库 `schema-h2.sql` 手写了它们 → 全量测试绿 = 假绿。其中
> **11 张表属"INSERT 必崩"级**(缺 `id`/`created_at`/`updated_at`,被 `AutoFillHandler` 强制填充,
> 每次写入必进 SQL):`matches`(缺 `episode`/`source_id`/`last_activity_at`/`unmatched_by`/`deleted_at`)、
> `user_preferences`(缺 `id` + 11 个权重列)、`permissions`、`roles`、`consent_records`、`risk_events`、
> `review_reasons`、`match_rule_configs`、`matchmaker_followups`、`matchmaker_recommendations`、
> `user_privacy_settings`。**真实 PG 上 Match 创建、择偶偏好保存、权限/角色写入、同意记录、风险事件
> 全部失败**。修复:新增 `V037__align_entity_columns_with_migrations.sql`(幂等 `ADD COLUMN IF NOT
> EXISTS`,含存量数据 `episode` 回填与 `id` 补发)。
> - **D2(High)** `RelationshipService.createMatch` 不写 `episode`/`lastActivityAt`,与
> `MatchService.createOrReuseMatch` 形成**双路径字段填充不一致**;且 `episode` 为 null 时
> `MatchService` 的 `m.getEpisode() + 1` 对 `Integer` **自动拆箱抛 NPE**。修复:两条路径统一按
> AGENTS.md #20 推导 episode,并做 null 兜底。
> - **D3(High)** 测试库缺 `user_identities` 等 7 张表 → `GET /api/v1/home` 在测试环境直接
> `BadSqlGrammar("Table USER_IDENTITIES not found")`,**首页接口零回归覆盖**。修复:补齐
> `user_identities`/`review_tasks`/`local_eligibility_evidences`/`home_banners`/`service_locations`/
> `content_articles`/`activities` 七张表(列对齐生产迁移)。
> - **D4(Medium)** Phase 12 计划项 2 实际**未实现**:`getting_to_know` 分支只产出 `counseling`,
> 婚前辅导入口仅在 `matched_successfully` 才出现。修复:`HomeApplicationService.buildServiceRecommendations`
> 的 `getting_to_know` 分支补 `premarital` 引导(与 counseling 并列,不互相挤占)。
> - **新增永久守卫** `EntityMigrationParityTest`(5 用例):把「实体字段 ⊆ 生产迁移累积列」与
> 「测试库覆盖关键业务表」固化为**编译后自动可验证的不变量**,并区分「必崩级 / 潜伏级」。经
> **两轮负向验证**证明会变红(第一轮分级过窄已修正:`episode` 由"潜伏级"纠正为"必崩级")。
> - **删除假测试**:`RelationshipStatusServiceTest` 与 `RelationshipStatusServiceDoubleConfirmTest`
> 原含 `assertTrue(true); // 占位测试`,对 INV-005 零覆盖(AGENTS.md 明令禁止)→ 已删除占位断言,
> 行为验证移至走真实服务方法的 `RelationshipProgressPhase12Test`(14 用例,含并发确认)。
> - 报告:`docs/Phase-12-V11-Recovery-Completion-Report-2026-09-16.md`
### Phase 13 — 公益红娘转介 ✅ 已完成(2026-09-16 KEEP-VERIFY/EXTEND 复验通过)
| 任务 | 状态 |
|------|------|
| 保留红娘服务和人工推荐;任何工作人员不能替用户 Like(INV-005) | ✅ 行为测试 4 项 |
| 补齐转介咨询、活动、服务站的用户同意、来源追踪和状态记录 | ✅ 行为测试 6 项 |
| 红娘只能看转介状态和必要摘要,不能读取 counseling followup 正文(INV-013) | ✅ 行为测试 3 项 |
| 红娘归属校验(推荐/转介不得越权代操作) | ✅ 负向测试 4 项 |
> **2026-09-16 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信,逐条核对**运行时路径**与**生产约束**后修复 7 处缺陷:
> - **D1(Critical,生产故障)** `matchmaker_recommendations.status` 代码写入 `liked`/`passed`/`confirmed_mutual`,
> 而生产 `V009 chk_rec_status` 只允许 `pending_view/viewed/responded` 且从未扩展 → **真实 PG 上用户接受/跳过
> 推荐必崩**(`DataIntegrityViolation`)。测试库 `schema-h2.sql` 未复刻该 CHECK,故长期静默。修复:
> `V038__align_matchmaker_status_constraints.sql` 以 `DROP CONSTRAINT IF EXISTS` + `ADD CONSTRAINT` 扩展白名单。
> - **D2(Critical,生产故障)** `MatchmakerController` 缺省 `serviceType="recommendation"` 不在
> `chk_matchmaker_service_type` 白名单 → **提交红娘服务必崩**。修复:同 `V038` 扩展(原 7 值 +
> `recommendation`/`referral_counseling`/`referral_activity`/`referral_station`)。
> - **D3(High,越权)** `MatchmakerServiceService.recommendPartner` 无 `assignedOperatorId` 归属校验 →
> 任意红娘可替非本人负责的服务发起推荐(并可推荐给自己)。修复:补归属校验 + 禁止自我推荐。
> - **D4(High,越权读)** `getServiceDetail` 无归属校验且返回**完整**用户资料(`userId`/`description`/`userProfile`/
> `followups`)→ 任意红娘可读任意用户敏感详情。修复:签名加 `requesterId`,负责人得完整视图,
> 非负责人得脱敏视图(去 `userProfile`/`userId`/`followups`,仅 `followupCount` + `viewerIsOwner=false`)。
> - **D5(High,越权写)** `ReferralService` 的 `userId` 取自**请求体**且**零授权校验** → 任意持
> `matchmaker.service` 权限者可替任意用户发起转介。修复:新增 `assertMatchmakerServesUser`,
> 在 `referToServiceStation`/`referToActivity` 入口强制校验"存在进行中的服务关系"。
> - **D6(High,生产故障)** `MatchmakerFollowupMapper.findByServiceId` 只声明方法、**无 `@Select`** →
> 运行时 `Invalid bound statement (not found)`,`getServiceDetail` **必崩**。**该缺陷由本轮新增测试首次暴露**
> (历史测试从未调用该路径)。修复:补 `@Select`。
> - **D7(Medium,契约缺口)** admin-web 5 处 API 缺口:`/matchmaker/services/operator/queue`、
> `/matchmaker/recommendations/operator`、`PUT /matchmaker/services/{id}/assign`、
> `POST /matchmaker/services/{id}/recommendation`、`/referrals/my-history`(C 端端点被运营端误用)。
> 修复:后端补 `GET /operator/matchmaker/recommendations` 与 `GET /referrals/operator/history`
> 两个运营端端点(含 `MatchmakerServiceMapper.findActiveByOperatorAndUser`、
> `MatchmakerRecommendationMapper.findByOperatorId`、`ReferralService.getReferralHistoryByOperator`),
> 前端改路径、`assign` 改 `POST` + body `operatorId`;小程序新增 `miniapp/services/referralService.js`。
> - **测试库盲区修复**:`schema-h2.sql` 补 `matchmaker_services`/`matchmaker_recommendations`/
> `matchmaker_followups` 三表(约束与 V038 对齐);`EntityMigrationParityTest` 的 3 张 matchmaker 表
> 从 `TEST_SCHEMA_OPTIONAL_TABLES` 移入 `REQUIRED_IN_TEST_SCHEMA`;`MigrationValidationTest` 基线 37 → 38。
> - **新增永久守卫** `MatchmakerReferralPhase13Test`(17 用例,`@SpringBootTest` 走真实方法路径)+ 重写
> `MatchmakerServiceTest`(6 用例)。**关键教训**:首版常量守卫**硬编码白名单副本**,注入 D1 缺陷后
> **仍全绿**(对漂移零反应)→ 重写为**直接解析 `db/migration/V*.sql`**,按文件名顺序应用
> `DROP CONSTRAINT IF EXISTS` + `ADD CONSTRAINT` 取"最终有效"白名单,并内置解析器自检用例。
> 修正后经**第二轮负向验证**证明会红(`Tests run: 23, Failures: 1, Errors: 2 / BUILD FAILURE`)。
> - **删除假测试**:`MatchmakerServiceTest.testMatchmakerCannotLike` 原为 `assertTrue(true)`;
> `CoreInvariantsTest` 的 INV-007 断言的是 `MATCHMAKER_STATUS_*` 常量(名不副实)、INV-010 亦为
> `assertTrue(true)` → 已删除占位、如实改名并注明行为验证位置。
> - 报告:`docs/Phase-13-V11-Recovery-Completion-Report-2026-09-16.md`
### Phase 13A — 婚恋咨询与婚前辅导 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
| 计划项 | 状态 |
|------|------|
| 计划项 1 Admin Vue 修复 + `/counseling` 路由注册 | ✅ `vue-tsc` EXIT=0 |
| 计划项 2 认证主体 userId + 幂等 + 取消 + owner 校验 + 状态迁移 | ✅ 8 用例 |
| 计划项 3 条件更新解决并发 + Assigned Service 边界 | ✅ `assignIfPending` + 4 用例 |
| 计划项 4 Manager 可摘要不可读正文 | ✅ 7 用例 |
| 计划项 5 婚前辅导复用 service type + 伴侣自主确认 | ✅ 4 用例 |
| 计划项 6 U55~U59 类型/契约/四态/非医疗化文案 | ✅ 双端 type-check EXIT=0 |
> **2026-09-17 复验结论(KEEP-VERIFY/EXTEND)**:历史 ✅ 不可信。counseling 模块存在
> **双实现**——线上权威 `CounselingService`(167 行)**零测试**,唯一被测的
> `CounselingServiceApp`(280 行)是**孤儿类**(无注入点、无端点可达,生产永不执行)。
> 已将其流程合并入 `CounselingService` 并删除孤儿类及仅其使用的 3 个 DTO 与测死代码的测试。
> 修复 **9 处缺陷**:
> - **D1(Critical,生产故障 · INV-013 泄露)** 咨询正文 `userRequestSummary` **原文被写入 WARN 日志**
> (`CounselingServiceApp:81`,同 Phase 10 D2 一族)。修复:合并后只记 `serviceId` + `riskLevel`。
> - **D2(High,越权)** 申请 `userId` 取自**请求体**而非认证主体 → 可替他人提交申请。
> 修复:Controller 强制 `principal.id()`。
> - **D3(High,并发)** `assignCounselor` 用「先读后写」→ 两管理员并发分配**静默覆盖**。
> 修复:`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` **后端不存在**,小程序 intro 页
> 100% 无数据(且被 `/services/{id}` 吞掉)。修复:补端点并**声明在变量路径之前**。
> - **D7(Medium,契约)** Admin 调用 5 条不存在的 `/services/operator/*`(404)+ 缺四态。
> 修复:后端补 8 个运营端端点(`@PreAuthorize`),前端整体重写。
> - **D8(Medium,契约)** 小程序字段名错(`userRequestSummary`/`preferredServiceMode`)+ 无幂等
> + `my-counseling` **未检查 `success`**(403 静默空列表)+ 跳转不存在的页 + WXML 内调用方法(非法)。
> - **D9(Medium,测试保真度)** 测试库 counseling 两表**零 CHECK 约束**,`counseling_services`
> 未列入 `EntityMigrationParityTest` 任何集合(= 零覆盖)。修复:补 3 个 CHECK + 建
> `counseling_followups` + 两表移入 `REQUIRED_IN_TEST_SCHEMA`。
> - **另修 4 处测试基建缺陷(T1~T4)**:① 守卫因 surefire `<workingDirectory>${project.basedir}/..`
> 指向**仓库根**而**找不到 DDL**(且 `backend/` 是子目录非祖先,回溯也找不到)→ 恒真假绿;
> ② 全限定 `@com.baomidou...TableField(exist=false)` **漏解析** → 假漂移警报;
> ③ `OperatorEndpointPermissionCoverageTest` 扫到**私有辅助方法**(假阳性);
> ④ 两处测试自身逻辑缺陷(陈旧内存快照比较、Instant 纳秒 vs DB 微秒精度)。
> - **负向验证两轮**:① 从 `V039` 移除 `scheduled` → 常量守卫**精准变红**
> (证明其解析的是**真实 DDL** 而非副本);② 注入「并发回退先读后写 / manager 读 followups /
> 状态机守卫失效」→ **三个用例各自精准变红**。均已还原(`grep -c "NEG-VAL"` = 0)。
> - **全量回归**:`Tests run: 420, Failures: 0, Errors: 0, Skipped: 3 / BUILD SUCCESS`(4:49)。
> 基线 391 → 420(净 +29)。
> - 报告:`docs/Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md`
### V1.1 待实现模块(按 Phase 顺序)
| 模块 | 对应 Phase | 状态 |
|------|-----------|------|
| Home Aggregate API + V1.1首页 | Phase 07 | ✅ 已完成 |
| Banner 管理(后端+前端) | Phase 19 | ✅ 已完成(2026-09-17 复验关闭) |
| 本地资格声明与审核 | Phase 04~05 | ⏳ 待开发 |
| 公益红娘服务转介 | Phase 13 | ✅ 已完成 |
| 婚恋咨询 + 婚前辅导(Phase 13A) | Phase 13A | ✅ 已完成(2026-09-17 复验关闭) |
| 内容管理(婚恋课堂/反诈) | Phase 19 | ✅ 已完成(2026-09-17 复验关闭) |
| 专项公益服务项目 | Phase 19 | ✅ 已完成(2026-09-17 复验关闭) |
| 善缘服务站 + 用户端公益服务页面(U37/U49~U54/U60/U61/U64) | Phase 19 | ✅ 已完成(含 V042 临时公告) |
| V1.1新增不变量测试(INV-011~020) | Phase 23 | ⚠️ 部分完成(2026-09-18):原 14 个用例全为常量断言(INV-016 断言文章状态、INV-017 为自造字面量重言式);已重写为 12 个,其中 4 个为真实服务行为(INV-013/016/017/019),已过负向注入验证。详见 `docs/Phase-23-V11-Recovery-Completion-Report-2026-09-18.md` |
### 当前运行状态
```
管理后台: http://localhost:13520/ (凭证由本地环境变量或安全 Seed 提供)
API 网关: http://localhost:8085/api/v1/
PostgreSQL: localhost:5434 (danyang_match)
Redis: localhost:6381
MinIO: localhost:9003 (凭证由本地环境变量提供)
```
**管理端端口口径**(2026-09-18 对齐为 13520):
| 形态 | 端口 | 说明 |
|---|---|---|
| admin-web 本地开发(vite) | **13520** | 权威声明在 `admin-web/vite.config.ts`;`strictPort: true`,被占用直接失败而非静默漂移到 13521 |
| 生产 admin 容器发布 | **13520** | 声明在 `infrastructure/docker-compose.prod.yml`——**该文件位于 `.gitignore` 的「Secrets and certificates」段,刻意不进版本控制**,故此改动仅在部署机生效;仍绑定 `127.0.0.1`,对外访问走 nginx 80/443 + `/admin/` |
| 本地整套栈的管理端入口 | 6688 | admin 容器不发布端口,与 `/api` 同由 nginx 的 6688 暴露(6688 是 nginx 入口,不是纯管理端端口) |
| staging admin 容器发布 | 3001 | 为与生产同机共存,staging 全部端口按「生产 + 1」错开(5433/6380/8081/3001);`tests/uat/run-uat.sh` 的 `UAT_ADMIN_URL` 默认指向它 |
`ui-tests/ui-document-baseline-contracts.mjs` 钉住「本地开发 / 本文档 / 生产 compose」三者端口一致:
前两处为硬断言;生产 compose 因不在版本控制内,采取「存在才断言」——CI 上该文件不存在,
显式打印 skip 而非假红。
---
## 当前 Phase
### Phase 14 — 多类型公益活动(核心链路)✅ 已完成
| 任务 | 状态 |
|------|------|
| V023 activity_type/registration_policy/target_group/industry_scope 字段扩展 | ✅ |
| activity_organizations 多组织关联表 | ✅ |
| activity_capacity_groups 容量分组表 | ✅ |
| Activity Java实体扩展(6个新字段) | ✅ |
| ActivityOrganization + ActivityCapacityGroup 实体/Mapper | ✅ |
| ActivityService 新增4个V1.1方法 | ✅ |
| ActivityController 新增6个API端点 | ✅ |
| Constants 新增 ACTIVITY_TYPE_* + ORG_ROLE_* 常量 | ✅ |
**Phase 13A(公益婚恋咨询与婚前辅导)— 已完成** ✅
### Phase 19 — 统一运营后台 + 用户端公益服务页面 ✅ 已完成(2026-09-17 复验关闭)
> 复验报告:`docs/Phase-19-V11-Recovery-Completion-Report-2026-09-17.md`
> 后端全量回归:`Tests run: 602, Failures: 0, Errors: 0, Skipped: 3 / BUILD SUCCESS`
> admin-web:`vue-tsc --noEmit` EXIT=0、`vite build` EXIT=0;小程序:`tsc --noEmit` EXIT=0;ui-tests 14/14 PASS
| 任务 | 状态 |
|------|------|
| V026 内容+专项项目+组织关系表 | ✅ |
| V042 善缘服务站「临时公告」表(本轮新建) | ✅ |
| ContentService(分类/文章 CRUD + publish/offline) | ✅ |
| Content 运营端接口分离(修「发布死路」/「分类停用不可恢复」) | ✅ |
| ServiceProgramService(项目CRUD + 成员审批 + 退出/移除/统计) | ✅ |
| Banner 运营端(白名单校验 400 而非 500 + 软删过滤 + 禁外链 + 预览) | ✅ |
| 善缘服务站运营端(信息维护 + 公告五端点 + 权限下沉方法级) | ✅ |
| 预约 IDOR 修复(principal.id() + 归属校验 + DataScopeGuard) | ✅ |
| Admin Web 前端(Banner / 内容 / 服务项目 / 服务站公告) | ✅ |
| 用户端 U37 四组重构 + U49~U54/U60/U61/U64 页面 | ✅ |
**本轮复验修复 25 处真实缺陷**,其中高价值项:服务站公告能力**整条不可达**(Service + 表都在、零端点);
服务站 `create/update` **越权写**(写端点只受 `service_location.view` 保护,`manage` 是从未使用的死权限)
且该控制器**未纳入**权限覆盖守卫;Banner 校验抛 500;Content 发布死路;ServiceProgram 审批死路 / 草稿泄露 / 成员数恒 0 / 退出未实现;
测试库缺 `content_categories` 与 `service_location_announcements`(对应路径零覆盖)。
新增守卫:`ServiceLocationAnnouncementPhase19IntegrationTest`(24) / `ServiceLocationControllerPermissionContractTest`(5) /
`ServiceLocationAnnouncementConstraintParityTest`(5)。负向验证 3 处注入 → 4 个用例精准变红并还原(`NEG-VAL` 残留 0)。
### Phase 20 — Analytics 数据统计与管理驾驶舱 ✅ 已完成(2026-09-17 复验关闭)
> 复验报告:`docs/Phase-20-V11-Recovery-Completion-Report-2026-09-17.md`
> 指标字典:`docs/ANALYTICS_METRICS.md`(与 `MetricCatalog` 逐条对应)
> 后端全量回归:`Tests run: 648, Failures: 0, Errors: 0, Skipped: 3 / BUILD SUCCESS`
> admin-web:`vue-tsc --noEmit` EXIT=0;负向验证 2 轮 7 处注入 → 7 用例精准变红,还原后 0 残留
| 任务 | 状态 |
|------|------|
| P20-T01 指标字典(`MetricCatalog` 36 指标 × 12 字段 + 文档 + 守卫) | ✅ |
| P20-T02~T09 User / Review / Recommendation / Match / Chat Started / Matchmaker / Activity / Risk Metrics | ✅ |
| P20-T10 Daily Summary(补 days 1~365 边界校验) | ✅ |
| P20-T11/T12 Platform Dashboard(统一口径层 `AnalyticsMetricsCalculator`) | ✅ |
| P20-T13 Organization Dashboard | ✅(受 `analytics.view` + DataScope;`organization_admin` 待组织维度建模) |
| P20-T14 Analytics 权限(V043 打通 `data_viewer` / `platform_admin`) | ✅ |
| `GET /operator/analytics/v11-dashboard` 综合接口 | ✅ |
**本轮复验修复的真实缺陷(高价值项)**:
- **口径造假**:实名人数用 `profile_status != 'rejected'` 冒充(把"资料还在填"算成已实名);
Chat Started 直接数会话行数(系统通知计入);Match 不分来源(10 对互选被当 10 对成功引用);
Banner 曝光/点击**硬编码 0**(被读成"投了没人点",实为无埋点)。
- **死代码**:活动漏斗**全部硬编码 0**(不是没数据,是根本没有查询)+ 一行把"用户数"当"活动数"的死代码。
- **系统性软删缺陷(D12)**:`BaseEntity.deletedAt` 无 `@TableLogic`、全局无逻辑删除配置
→ `selectCount` 把**软删数据全部计入统计且无任何报错**。修复 45 处统计调用(2 轮复验,首轮漏扫 5 处次级路径)。
- **权限授予脱节(Gate ⑩)**:`data_viewer` 角色被定义却**从未授权**(空壳角色);
`platform_admin` 因 `id >= '20000000-…'` 条件漏掉 V1.0 老权限段 → **整个模块除 super_admin 外全员 403**。
- **假绿测试**:`AnalyticsServiceTest` = 5×`assertTrue(true)`(零断言),已删除并替换为 21 用例真实 DB 集成测试。
**跨阶段发现**(缺陷本体属 Phase 21,本轮已修 X1~X3):
`AccountLifecycleService` 注销时把 `user_identities` 状态域的 `'failed'` 写入本地资格表
→ 违反生产 `V017 chk_elig_verify_status` → **真实 PG 上 closeAccount 事务回滚、账号注销 100% 不可用**;
`checkCanWithdraw` 的资格拦截用 `submitted`/`pending`(该表永不可能出现的值)→ 死代码。
测试库补齐 `chk_elig_type` / `chk_elig_verify_status` 后立即暴露 `ActivityPhase14Test` 夹具违规。
新增 `LocalEligibilityStatusVocabularyGuardTest`(9)。
### Phase 21 — 账户生命周期增量 ✅(KEEP-VERIFY 复验关闭,2026-09-18)
| 项 | 复验结论 |
|------|------|
| P21-T01~T05 + checkCanWithdraw(原声明「✅」) | 主体实现存在,但复验发现并修复 **6 处真实缺陷** |
| Gate:注销后不能登录 | ❌→✅ `AuthService.checkAccountStatus` 原不拒 `CLOSED` → 已修复 |
| Gate:注销后不能聊天 | ❌→✅ `notifyActiveMatches` 原是 TODO 桩 → 已实现关闭 Match + 通知对方 |
| Gate:关闭未来服务(活动报名) | ❌→✅ `cancelPendingActivityRegistrations` 原是 TODO 桩 → 已实现 |
| Gate:不暴露个人/咨询正文 | ❌→✅ `anonymizeServiceHistory` 已实现却**从未被调用(死代码)** → 已接线;身份证脱敏原是 TODO → 已覆盖占位符;并脱敏 `counseling_followups` 正文 |
| 死代码矛盾 | ❌→✅ `closeAccount` 在 blockers 处硬抛异常,使 `cancelXxx` 永远不可达 → 改为信息性日志 + 继续清理 |
| 测试保真度 | 删除 7×`assertTrue(true)` 假绿 → 替换为 11 用例真实 DB 集成测试 + 3 用例登录守卫 |
| 跨模块防线(既有) | ✅ 推荐引擎 / 匹配资格 / Capability 已拒绝非 `NORMAL`(含 `CLOSED`) |
| 后端全量回归 | **650 tests / 0 failures(起点 648,净 +2)** |
| 报告 | `docs/Phase-21-V11-Recovery-Completion-Report-2026-09-18.md` |
| 遗留(未静默扩权) | ① 红娘服务进行中拦截:数据模型无 `matchmaker_services` 表,仍硬编码 0(TODO);② 数据保留"配置+人工审核"删除流程属产品决策未实现;③ 隐私设置接口仍为 TODO 桩 |
### Phase 22 — 部署运维配置扩展(Feature Flag)✅(KEEP-VERIFY 复验关闭,2026-09-18)
| 项 | 复验结论 |
|------|------|
| 范围 | STATUS 遗留区「Phase 22 部署运维配置扩展」= 7 个 V1.1 Feature Flag + `FeatureFlagController` + 默认值(计划文件 Phase 22 实为 Deployment/Ops 基础设施,另属一块任务,未纳入本 Phase) |
| D-22-A(High) | `updateFlag` 仅支持布尔 flag(反射 `getMethod("set"+cap, boolean.class)`)→ 7 个非布尔 flag 经 API 更新必失败;已改为按字段类型分派 boolean/int/String |
| D-22-B(Medium) | `body.getOrDefault("value", false)` 缺 value 静默置 false + 非布尔转型崩;已改为缺 value/类型错→400 且不改原值 |
| T01–T05 模块开关 | 复验发现 `isCounselingEnabled` / `isPremaritalEnabled` / `isContentEnabled` / `isServiceLocationEnabled` / `isLocalEligibilityEnabled`(模块级)全仓无业务调用点 → **死配置**(暴露但未 gate);不静默扩权,留交各模块 Phase 接线 |
| T06 上传策略 | 实测已在 `LocalEligibilityService`(启用开关 + 数量上限)+ `PhotoService`(大小 + 类型)**真强制** ✅ |
| T07 私有存储桶 | `counselingAttachmentsPrivate` / `Bucket` 全仓零引用 → **死配置**(存储本就走 `object-storage.bucket-private`);可选增强,遗留 |
| yml 声明夸大 | STATUS 称「application.yml 默认配置(15 flag)」,实际 yml 无 `features:` 块,默认值来自 Java 字段默认值;功能不受影响,文档纠正 |
| 守卫测试 | 新增 `FeatureFlagControllerTest`(7 用例:21 键全暴露 / 布尔·字符串·整数更新生效 / 未知 flag·缺 value·类型错→400);负向验证(仅布尔缺陷版)恰 2 用例精准变红,还原全绿 |
| 全量回归 | **657 tests / 0 failures / 0 errors / 3 skipped(起点 650,净 +7)** |
| 报告 | `docs/Phase-22-V11-Recovery-Completion-Report-2026-09-18.md` |
| 遗留(未静默扩权) | ① T01–T05 模块开关死配置;② T07 私有桶死配置;③ PUT 仅内存生效(不持久化,计划未要求);④ 计划 Phase 22 Deployment/Ops 基础设施尚未复验 |
**Phase 20(Analytics数据统计扩展)— 已完成** ✅
### Phase 22 — 部署运维配置扩展(历史声明,已被上方 2026-09-18 权威结论取代)
> ⚠️ 下表为历史进度声明,**经 KEEP-VERIFY 实测部分不成立**,以本节上方「Phase 22 — 部署运维配置扩展(Feature Flag)✅(KEEP-VERIFY 复验关闭,2026-09-18)」为准。
| 任务 | 历史声明 | 实测结论 |
|------|---------|---------|
| P22-T01 counselingEnabled flag | ✅ | ⚠️ 死配置:全仓无业务调用点,不 gate 任何功能 |
| P22-T02 premaritalEnabled flag | ✅ | ⚠️ 死配置:同上 |
| P22-T03 contentEnabled flag | ✅ | ⚠️ 死配置:同上 |
| P22-T04 serviceLocationEnabled flag | ✅ | ⚠️ 死配置:同上 |
| P22-T05 localEligibilityEnabled flag | ✅ | ⚠️ 死配置:同上 |
| P22-T06 local evidence upload policy | ✅ | ✅ 属实:`LocalEligibilityService` 强制启用开关+数量上限,`PhotoService` 强制 size+类型 |
| P22-T07 private storage for counseling attachments | ✅ | ⚠️ 死配置:`counselingAttachmentsPrivate/Bucket` 零引用,存储实走 `object-storage.bucket-private` |
| FeatureFlagController API | ✅ | ⚠️ 曾含 D-22-A(仅布尔,7 个非布尔 flag 更新必失败)与 D-22-B(缺 value 静默置 false);已修复并补 7 例守卫 |
| application.yml 默认配置(15个 flag) | ✅ | ❌ 不成立:yml 无 `features:` 块,实际为 Java 字段默认值 |
**Phase 21(账户生命周期增量)— 已完成** ✅
### Phase 22 — 部署运维配置扩展(重复的历史声明块,已作废)
> ⚠️ 与上一条为同一 Phase 的重复历史声明,同样已被上方 2026-09-18 权威结论取代,不再逐项重复。
| 任务 | 实测结论 |
|------|---------|
| P22-T01~T05 五个模块开关 flag | ⚠️ 死配置(无业务调用点) |
| P22-T06 local evidence upload policy | ✅ 属实(真实强制) |
| P22-T07 private storage for counseling attachments | ⚠️ 死配置(零引用) |
| FeatureFlagController API | ✅ 已修复 D-22-A/D-22-B 并补守卫 |
| application-dev.yml + application-docker.yml 配置 | ❌ 不成立:两份 yml 均无 `features:` 块 |
**Phase 21(账户生命周期增量)— 已完成** ✅
### Phase 23 — 可信系统测试重建(REFACTOR)⚠️ 部分关闭(KEEP-VERIFY 复验,2026-09-18)
> 下方「Phase 23 — V1.1专项测试 ✅ 已完成」为**历史声明,经实测部分不成立**,以本节为准。
| 项 | 结论 |
|---|---|
| 报告 | `docs/Phase-23-V11-Recovery-Completion-Report-2026-09-18.md` |
| 回归 | **655 tests / 通过 652 / 失败 0 / 错误 0 / 跳过 3**(起点 657,净 −2:原 14 个空转用例合并为 12 个) |
| 跳过原因 | `ConcurrentTests` ×2(`@EnabledIfEnvironmentVariable(CI=true)`,「本地并发测试跳过」);`CoreE2ETest` ×1(`@Disabled`「需要完整数据库连接」)—— 均有显式声明,非空壳 |
| D-23-A(Critical) | `V11InvariantsTest` 原 14 个用例全为常量断言:INV-016 断言**文章状态**常量(跑错域)、INV-017 是**自造字面量的重言式**(从未调用首页服务)、INV-018/019/020 用无关状态常量冒充权限验证 → 已重写,新增 4 个真实行为守卫(INV-013 脱敏、INV-016 白名单禁外链、INV-017 首页 8 入口顺序、INV-019 内容编辑员零数据)+ `assertBehaviorTestExists` 指针契约 |
| D-23-B(High) | `tests/e2e/` **44 个 `pass` 空壳**(4 个文件 100% 为空壳)→ 已移除,改为诚实占位并保留场景清单 |
| D-23-C(High) | pytest E2E 套件**整体不可执行**:全仓无 `conftest.py`,约 15 个 fixture 不存在;唯一可执行的 `run_v11_tests.py`(16 用例)需活栈 |
| D-23-D(High,遗留) | **CI 未串联 E2E**(计划明确要求)→ 需先决定 CI 活栈供给方式,未在本轮实施 |
| D-23-E(Medium) | CI `migration` job 注释称「验证 SQL 语法」但只查文件非空 → 改为真实序列校验(命名/非空/版本号唯一/无缺号),已本地实跑通过 |
| 新增闸门 | `scripts/check-no-empty-tests.py`(AST 扫描,阻断 `pass` 空壳与无条件 `skip`)+ CI `test-shell-guard` job |
| 遗留 | ① E2E 进入 CI 待基础设施决策;② pytest fixture 体系缺失;③ INV-011 无显式守卫(结构性满足);④ E2E 场景清单待实现(已保留在占位文件头) |
| 结论 | **部分关闭**:假覆盖已归零,但 UAT 前 Gate 要求的端到端链路仍未真实执行,**不宜据此宣布可进入 UAT** |
---
### Phase 23 — V1.1专项测试 ✅ 已完成(历史声明,已被上方权威结论取代)
> ⚠️ 下表为历史进度声明,**经 Phase 23 KEEP-VERIFY 实测部分不成立**,以上方「Phase 23 — 可信系统测试重建(REFACTOR)」为准。
| 任务 | 历史声明 | 实测结论 |
|------|---------|---------|
| P23-T01 Home V1.1 E2E | ✅ (home_v11_test.py) | ❌ 该文件 7/9 为空壳且依赖不存在的 fixture,从未执行;首页聚合实由 `run_v11_tests.py::test_02_home` 覆盖 |
| P23-T02 Banner timing filter | ✅ (home_v11_test.py) | ❌ 空壳 `pass`,未实现 |
| P23-T03 Banner audience filter | ✅ (home_v11_test.py) | ❌ 空壳 `pass`,未实现 |
| P23-T04 Quick Entry order | ✅ (home_v11_test.py) | ⚠️ 原为自造字面量重言式;**现由真实用例 `V11InvariantsTest#inv017QuickEntriesFixedOrder` + `run_v11_tests.py::test_03` 覆盖** |
| P23-T05 Local Eligibility E2E | ✅ (local_eligibility_test.py) | ❌ 该文件 11/11 全为空壳,从未执行 |
| P23-T06 Counseling E2E | ✅ (counseling_v11_test.py) | ⚠️ 该文件真实可执行;其中 INV-013 一项为空壳,已移除,**改由 `V11InvariantsTest#inv013` 真实覆盖** |
| P23-T07 Counseling permission | ✅ (counseling_permission_test.py) | ❌ 该文件 10/10 全为空壳,从未执行 |
| P23-T08 Service Appointment E2E | ✅ (service_appointment_test.py) | ❌ 该文件 7/7 全为空壳,从未执行 |
| P23-T09 Content E2E | ✅ (content_e2e_test.py) | ✅ 属实(自包含 requests 用例,真实可执行) |
| P23-T10 Multi-type Activity E2E | ✅ (multi_type_activity_test.py) | ✅ 属实(自包含 requests 用例) |
| P23-T11 Activity Mutual Consent E2E | ✅ (activity_mutual_consent_test.py) | ❌ 该文件 8/8 全为空壳;不变量实由后端 `ActivityMutualConsentServiceTest` 真实覆盖 |
| P23-T12 Service Station permission | ✅ (service_station_permission_test.py) | ✅ 属实(自包含 requests 用例) |
| P23-T13 Organization relation isolation | ✅ (organization_isolation_test.py) | ✅ 属实(自包含 requests 用例) |
| P23-T14 INV-011~INV-020 | ✅ (V11InvariantsTest.java) | ❌ 原 14 个用例全为常量字符串断言(INV-016 断言文章状态、INV-017 重言式);**已重写为 12 个,含 4 个真实行为守卫** |
E2E测试文件:10个(~80+测试用例)→ **实测:6 个含 44 个 `pass` 空壳,其中 4 个 100% 为空壳;pytest 侧因无 `conftest.py` 整体不可执行**
Invariant测试:10个(INV-011~020)→ **实测:原 14 个用例无任何服务行为断言;现 12 个,其中 4 个为真实行为(已过负向注入验证)**
**Phase 22(部署运维配置扩展)— 已完成** ✅
### Phase 23B — E2E 测试基建重建(2026-09-18)✅ 已关闭
> 本轮补齐的是 Phase 23 的两条遗留(D-23-C「E2E 整体不可执行」、D-23-D「CI 未串联 E2E」),
> 与下方 **「Phase 24 — UAT增量」是不同工作**,不要混为一谈。
| 交付 | 说明 |
|---|---|
| `tests/e2e/conftest.py` | fixture 体系:ApiClient、`operator_token(username)`、`new_user`、栈探活 |
| `pytest.ini` / `tests/e2e/requirements.txt` | 收集范围与依赖 |
| `tests/e2e/sql/seed_e2e_operators.sql` | 运营账号自举(**迁移里没有任何 operator 种子**,全新库无账号可登录) |
| CI job `e2e` | 起真实栈 → 等就绪 → seed → pytest → 失败阻断 → 清理 |
| 8 个 E2E 文件改造 | 消除 import 期 `KeyError`;替换恒真 / 名不副实的断言 |
**核心设计**:栈不可达时 `pytest.exit(4)`,**不是 skip** —— skip 会把"未执行"伪装成"通过"。
**验证**:本机真实活栈 **33 passed**;后端全量回归见本节末。
**本轮暴露并修复的真实生产缺陷**(H2 测试库全部零覆盖,只有真 PostgreSQL 才现形):
| 编号 | 真相 |
|---|---|
| D-23B-A | 构建产物残留重复迁移版本号 042 → Flyway 报错 → **应用起不来** |
| D-23B-B | 非 UUID path 参数 → 500 且泄漏数据库异常 |
| D-23B-C | 6 个 E2E 文件 import 期崩溃 → **从未被执行过** |
| D-23B-E | 权限 seed 缺口:`super_admin` 仅 18/48 条、`matchmaker` **0** 条(matchmaker 部分列为遗留) |
| D-23B-I | 非法枚举参数 `IllegalArgumentException` 未映射 → 500(应 BAD_REQUEST) |
| D-23B-J | `operator does not exist: uuid = character varying` → JDBC 增加 `stringtype=unspecified` |
详见 `docs/Phase-23B-V11-E2E-Infrastructure-Completion-Report-2026-09-18.md`。
### HTTP 语义检修 — 失败响应携带真实 HTTP 状态码(2026-09-18)✅ 已关闭
起因:Phase 23B 收尾时质疑「HTTP 200 + body.code 这套约定,开放第三方还守得住吗」。
审计后确认**当时就已经是断的**,不是未来风险。
| 发现 | 说明 |
|---|---|
| 105 处 / 30 个 Controller | `return ApiResponse.error(...)` 不抛异常、不带 `@ResponseStatus` → HTTP 恒为 200 |
| 前后端契约已断 | 小程序 `api.js` 的 401/403/429 分支**永远走不到**;token 过期回 403 → 不触发 `onSessionExpired` → **用户卡死** |
| 未认证回 403 | `SecurityConfig` 未配 `authenticationEntryPoint`,body 连 `code` 都没有 |
| CORS 默认 `*` + `allowCredentials(true)` | 注释却写「默认只允许 localhost」——注释与代码不符 |
| 测试覆盖 | 全量测试仅 4 文件 / 15 处断言触及状态码 |
修法:**一处定义、两处应用、业务代码零改动** —— 响应码枚举新增 `httpStatus`(单一真相源)、
异常处理器从枚举读状态、新增 `ResponseBodyAdvice` 覆盖全部直返路径。
验证:E2E **37 passed**(+4 契约用例);后端回归 **662 / 0 / 0 / 3**;
活栈实测 404 / 400 / 401 正确。回归首轮 3 处失败经判定均为**测试断言了旧的错误行为**,
改断言而非改回实现。
遗留(第三方开放,属范围扩张,需产品决策):第三方凭据机制、限流是否真实生效、
OpenAPI 对外发布、调用审计与配额、分页幂等覆盖、脱敏边界。
**同日续做:身份类型与路径规则收敛**
| 发现 | 说明 |
|---|---|
| 运营身份可打进用户端 | 兜底规则是 `authenticated()`,运营 token 完全满足;而 `@AuthenticationPrincipal UserPrincipal` 遇 `OperatorPrincipal` 类型不匹配返回 **null**(Spring 默认 `errorOnInvalidType=false`),全仓 **244 处**使用、**仅 48 处**做 null 检查 → 其余 **NPE → 500** |
| PathPattern 陷阱 | 嵌套运营端点(`/counseling/services/operator/**` 等)不能用 `/**/operator/**` 覆盖——`**` 只允许在末尾,写了会抛 `PatternParseException` 且**整个过滤器链 500**(实测 E2E 由 37 passed 直落 33 failed) |
| 修法 | 兜底收紧为 `hasRole("USER")`(196 处潜在 NPE 在认证层消解,不补 null 检查)+ 显式枚举 9 个运营前缀 + 新增 `SecurityPathCoverageTest` 机械守卫(防将来新增端点漏配) |
验证:E2E **40 passed**(+3 身份隔离用例);后端回归 **664 / 0 / 0 / 3**。
守卫经负向验证(摘掉 `/content/operator/**` → 恰好 1 用例变红并列出受影响的 6 个端点)。
详见 `docs/HTTP语义检修报告-2026-09-18.md`。
### 幂等键检修 — `Idempotency-Key` 从「声明」到「兑现」(2026-09-18)✅ 已关闭
起因:HTTP 语义检修收尾时我写下「`Idempotency-Key` 已支持」,随后核对**推翻了自己的结论**——
后端当时**零处**读取该头。
| 发现 | 说明 |
|---|---|
| 声明与实现彻底失联 | 规范第八章要求 7 类端点支持幂等键;前端 25 处调用点(8 service + 2 TS 页面)发送该头,**后端 0 处读取** |
| **前端那一侧也是坏的** | 原写法 `idempotencyKey: \`like:${Date.now()}\`` —— `Date.now()` 每次调用都变,**就算后端实现了也永远命中不了**。互补的两半,谁也不起作用 |
| 唯一真幂等的端点走的不是 header | 只有 counseling 申请靠 body 字段 `idempotencyKey`(V039 `uk_counseling_idem`) |
| 两道兜底双双落 500 | `DuplicateKeyException`(并发重复提交的最后防线)与 30 处 `IllegalStateException`(业务状态冲突)均无映射 → 500;而 500 语义是"可重试",**调用方于是重试,制造更多重复** |
| **一个错误的安全假设** | 上轮 `D-23B-J` 判定 `stringtype=unspecified` 是"一处解决全局"。本轮 V045 的 `actor_id VARCHAR` 在**同样开着该参数**的 docker profile 下依然抛 `character varying = uuid` → 该参数覆盖不到经类型处理器显式指定类型的参数。**真正的不变量是"列类型必须是 uuid"** |
修法:**一处实现、零业务代码改动、逐端点声明** —— `V045` 建表(`idempotency_records` + 唯一索引
`uk_idempotency_scope`)、`V046` 修正列类型、`IdempotencyInterceptor`(先占位后执行/重放/409)、
`IdempotencyResponseCacheFilter`(缓存响应体供逐字节重放)、`@Idempotent` 声明 30 处、
异常处理器两处新映射(`IllegalStateException` / `DuplicateKeyException` → 409,
且**刻意不映射**其父类 `DataIntegrityViolationException`,因后者含 CHECK 违反应由 500 暴露)。
四个关键设计:**先占位后执行**(靠唯一索引让并发只有一个赢家,不用 SELECT-then-INSERT)、
**失败释放占位**(否则一次瞬时故障把用户永久卡在 409)、**孤儿占位可接管**(进程中断不留死键)、
**作用域含 `actor_id`**(同键不同用户互不干扰)。
前端键改为"**一次未成功的逻辑操作内复用同一把键,成功才释放**",25 处 `Date.now()` 写法全部替换(残留 0)。
验证:E2E **49 passed**(含 `tests/e2e/idempotency_test.py` 7 用例:重放逐字节相同、同键只产生一条记录、
作用域隔离、**5 线程并发同键业务恰好落库一次**、无键重复 Like 不得 500);
后端全量 **669 / 0 / 0 / 3**(首轮 664/1 failure 为有意设计的迁移基线守卫,已按流程抬基线至 46);
小程序 `tsc --noEmit` EXIT=0;UI 契约门控 **14/14**。
**列类型不变量全库扫描**:所有 `*_id VARCHAR` 列中,`actor_id` 是唯一违规(已修);
`client_message_id` / `provider_request_id` 为外部 id、`resource_id` / `source_id` 在 Java 侧**零处作查询条件**
(已 grep 确认)→ 不存在第二处同类隐患。
**新增机械守卫** `IdempotencyDeclarationGuardTest`(2 用例,经注入变异负向验证,各自精确报出行号):
规范第八章 7 类端点族 + Phase 16 互选链路必须声明 `@Idempotent`;`@Idempotent` 后必须紧跟 `@PostMapping`。
同时**修正一处假绿**:`GlobalExceptionHandlerTest` 原 3 条断言只测 DTO、**一次都没进过处理器**。
**同轮清掉三处同形状问题**(均属"一处声明、另一处不兑现"的复发):
1. **补 `CheckinController` 手工签到的 `@Idempotent`** —— 第 146 章"扫码两次"场景的同类漏标;
2. **CI 上的 E2E 从未真正通过过**(本轮活栈复跑暴露):迁移里**没有任何 operator 种子**、
`DemoDataSeeder` 也不建运营账号,`conftest.admin_token` 却写死 `username="admin"` ——
那是某台开发机手工创建的遗留账号,本机有它所以本地一直绿,CI 全新库没有 → fixture 必然 401。
已改用 seed 创建的 `e2e_admin`(绑 super_admin),并新增 `tests/e2e/fixture_account_guard_test.py`
机械拦住"fixture 只准用 seed 账号"(含"解析失败即失败"断言,防守卫自身静默失效);
3. **`POST /activities/{id}/interests` 契约漂移**:`API_INVENTORY` 记载该端点、前端按此实现,
但后端**从未实现**(Phase 16 已把表达意向合并进 `/activities/{id}/feedback` 的 `interestTargetUserIds`)
→ 调用必然 404。已更正 `API_INVENTORY` 并按真实端点重列,删除前端死代码链
(`activityService.submitInterests` + `activityStore.submitInterests`,全仓确认无页面调用方),
各留注释说明删除原因与恢复条件。**若产品确认需要独立端点,应先定义语义并补后端实现。**
详见 `docs/幂等键检修报告-2026-09-18.md`。
### Phase 24 — UAT增量 ✅ 已就绪(测试数据支持)
| 任务 | 状态 |
|------|------|
| P24-T01 Service Station Operator UAT | ✅ 测试数据已就位(stationop账号) |
| P24-T02 Counselor UAT | ✅ 测试数据已就位(counselor01账号) |
| P24-T03 Counseling Manager UAT | ✅ 角色权限已配置 |
| P24-T04 Content Editor UAT | ✅ 角色权限已配置 |
| P24-T05 服务站扫码→预约→到场 | ✅ API链路完整 |
| P24-T06 咨询申请→服务完成 | ✅ API链路完整 |
| P24-T07 婚前辅导申请 | ✅ Miniapp页面U58/U59完整 |
| P24-T08 活动双方互选→双方确认→Chat | ✅ API+Miniapp完整 |
**备注**:UAT需要人工操作验证,后端API和数据模型已全部就绪。
**Phase 23(V1.1专项测试)— 已完成** ✅
### Phase 25 — RC内容检查 ✅ 可执行
| 任务 | 状态 |
|------|------|
| P25-T01~T09 真实素材填充 | ⏳ 待运营提供内容 |
| Banner真实素材 | ⏳ 等待运营 |
| 服务站真实地址/开放时间 | ✅ 已初始化万善公园站 |
| 咨询服务介绍 | ✅ API已就绪 |
| 婚前辅导介绍 | ✅ API已就绪 |
| 婚恋反诈首批内容 | ⏳ 待运营提供 |
| 婚恋课堂首批内容 | ⏳ 待运营提供 |
| 关于善缘丹阳 | ⏳ 待运营提供 |
| 主办/执行信息 | ⏳ 待运营提供 |
### Phase 26 — Production初始化 ✅ 已完成
| 任务 | 状态 |
|------|------|
| P26-T01 Seed Content Categories | ✅ (V027) |
| P26-T02 Seed Activity Types | ✅ (CHECK约束已定义) |
| P26-T03 Seed Service Types | ✅ (CHECK约束已定义) |
| P26-T04 创建万善公园服务站 | ✅ (V027) |
| P26-T05 初始化Banner | ✅ (V027) |
| P26-T06 初始化Feature Flags | ✅ (application.yml配置) |
| P26-T07 初始化新增Roles/Permissions | ✅ (V015已覆盖) |
| P26-T08~T13 Smoke tests | ⏳ 上线前手动验证 |
**V027 生产种子数据迁移**已创建,包含:
- 4个内容分类(婚恋课堂/反诈/婚前辅导/婚俗新风)
- 万善公园服务站基础数据
- 3条首页Banner
**Phase 24(UAT增量)— 已就绪** ✅
---
## 整体进度总结
| Phase范围 | 状态 |
|-----------|------|
| Phase 01~12 (V1.0基线) | ✅ 已完成 |
| Phase 13~22 (V1.1核心增量) | ✅ 已完成 |
| Phase 23 (V1.1专项测试) | ⚠️ 部分关闭(2026-09-18):假覆盖已清除 + 4 个真实守卫;E2E 入 CI 待决策 |
| Phase 24~26 (UAT/RC/Production) | ⏳ 运营/上线阶段 |
### Phase 24 — UAT增量 ✅ 已就绪
| 任务 | 状态 |
|------|------|
| P24-T01~T04 各角色UAT | ✅ 权限模型已配置 |
| P24-T05~T08 业务场景验收 | ✅ API链路完整 |
### Phase 25 — RC内容检查 ⏳ 待运营
| 任务 | 状态 |
|------|------|
| P25-T01~T09 真实素材 | ⏳ 需运营提供 |
### Phase 26 — Production初始化 ✅ 已完成
| 任务 | 状态 |
|------|------|
| P26-T01~T07 种子数据 | ✅ (V027) |
| P26-T08~T13 Smoke测试 | ⏳ 上线前手动验证 |
### Admin Web V1.1 模块扩展 ✅ 已完成
| 模块 | 文件 | 说明 |
|------|------|------|
| Banner管理 | BannerManagementView.vue | CRUD + 上架/下架 |
| 内容管理 | ContentManagementView.vue | 分类+文章CRUD + 发布/下架 |
| 善缘服务站 | ServiceStationView.vue | 站点信息编辑 |
| 服务预约 | ServiceAppointmentView.vue | 确认/完成/取消 |
| 专项项目 | ServiceProgramView.vue | CRUD + 成员审批 |
| 婚恋咨询 | CounselingView.vue | 分配/排期/跟进/完成 |
| 转介记录 | ReferralManagementView.vue | 转介历史查询 |
| 路由扩展 | router/index.ts | 7个新菜单+路由 |
---
## V1.1 整体进度总结
| 类别 | 状态 |
|------|------|
| 数据库迁移 (V001~V027) | ✅ 27个文件 |
| 后端 Java API | ✅ 100% 完成 |
| Miniapp 页面 (U55~U61) | ✅ 7个新页面 |
| E2E 测试 (12个文件) | ✅ 80+用例 |
| Invariant 测试 (INV-011~020) | ✅ 10个用例 |
| Feature Flag 配置 | ✅ 15个V1.1开关 |
| Admin Web V1.1 模块 | ✅ 7个新页面 |
| Admin Web 前端开发 | ⏳ 需完善样式和联调 |
**V1.1 核心功能 100% 完成,可进入 UAT 验收和上线准备阶段**
---
## 已知限制
| 限制 | 说明 |
|------|------|
| 人脸核验 | Feature Flag 预留,Provider 未确认 |
| 本地资格佐证触发规则 | 待运营确认 |
| 微信公众号审核 | 需人工操作 |
| SSL证书 | 需人工申请 |
| 有效交友匹配报送口径 | 待运营确认 |
---
*版本基线: 1.1.0-dev(2026-09-08)— V1.0 核心 100% 就绪,V1.1 增量开发中*
---
## V1.1 本地部署完成(2026-09-09,历史记录)
> ⚠️ **历史记录边界**:本节为 2026-09-09 的部署时点记录,其中的测试声明(11/11、25/25、16/16)
> **已在后续重新审查中被推翻**,不作为验收证据。当前有效状态见文首「当前有效结论」。
> 本区块在原文件中重复出现三次(内容高度雷同),2026-09-18 文档治理合并为一处。
### 修复的关键问题
- **CounselingServiceApp 通知 FK 约束** — operator 用户不在 `users` 表,改为检查后再发送通知
- **HomeController 路径重复** — `@RequestMapping("/api/v1/home")` → `"/home"`
- **LocalEligibilityController 路径重复** — 同上修复
- **数据库 `updated_at` 列缺失** — 为 18 个 V1.1 表补充 `ALTER COLUMN`
- **前端** — `CounselingView` / `ContentManagementView` 截断、路由缺失、侧边栏菜单缺失
### 为什么这些声明被推翻(保留为治理证据)
- E2E 的「16/16」记录**不可复现**,测试文件存在大量空 `pass` —— 这是 Phase 23「可信系统测试重建」的直接起因。
- API 人工测试未证明 Permission、DataScope 和业务闭环,不能作为上线依据。
- 「25/25 PASS」「11/11 PASS」均为当时自报,未附可复现命令与失败处理。
### 运营阶段遗留(至今不变)
- Phase 24: UAT — 需真实用户参与并确认启动
- Phase 25: RC 内容检查 — 需运营团队填充真实内容
- Phase 26: Production Smoke Tests — 13 项手动验证