2026-09-09 22:05:00 +08:00
# 善缘丹阳 V1.1 客户需求基线增量开发与修复 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在保留已经验证正确的 V1.0 婚恋核心和 V1.1 数据资产的前提下,依据客户最新修订文档修复当前伪完成、权限越界、前端不可用和业务闭环缺失问题,交付可测试、可运营、可回滚的善缘丹阳 V1.1。
**Architecture:** 继续使用 Java 21 + Spring Boot 模块化单体、PostgreSQL、Redis、私有对象存储、Vue 3 统一运营后台和微信原生 TypeScript 小程序。V1.1 是 V1.0 的增量升级,不新建第二套系统;正确模块 KEEP,缺少能力 EXTEND/ADD,错误首页和活动互选逻辑 REPLACE/REFACTOR。
**Tech Stack:** Java 21、Spring Boot 3.x、Spring Security、MyBatis-Plus、Flyway、PostgreSQL、Redis、WebSocket、S3-Compatible Private Object Storage、Vue 3、TypeScript、Vite、Pinia、Element Plus、微信原生小程序、Docker Compose、Nginx。
2026-09-16 14:37:44 +08:00
**Spec:** `docs/善缘丹阳 V1.1 WorkBuddy最终主启动提示词(整合版).md` 、`docs/superpowers/specs/2026-09-13-reference-driven-dual-client-ui-redesign-design.md` 、`docs/善缘丹阳 V1.1 数据库与API增量设计.md` 、`docs/善缘丹阳 V1.1 页面级功能清单与交互流程修订版.md` 、`docs/善缘丹阳 V1.1 WorkBuddy 开发执行计划修订版.md` 、`docs/善缘丹阳 V1.1 WorkBuddy-Jira 最终开发任务增量清单.md` 。
2026-09-09 22:05:00 +08:00
## Global Constraints
- 这六份客户修订文档共同构成 V1.1 需求基线,不能以其中一份覆盖其余文档的专业域要求。
2026-09-13 21:12:50 +08:00
- 主启动提示词负责执行纪律和不变量;页面清单负责功能与交互;2026-09-13 参考图重设计规格是唯一视觉和状态基线;数据库/API 文档负责数据契约;执行计划和 Jira 增量清单负责 Phase、任务与依赖。
2026-09-09 22:05:00 +08:00
- 文档中的“✅、已完成、已部署、MVP完成”属于历史进度声明,不属于客户需求;必须由当前代码、自动化测试和人工流程重新证明。
- V1.0 正确核心按 KEEP 处理,不重新开发;但每个受影响 Phase 必须执行回归门禁。
- V001~V027 已应用迁移不得改写;数据结构修复只能新增向前迁移。
- 用户基础婚恋服务永久免费;不增加支付、会员、金币、礼物、付费曝光或商业广告。
- Required 不自动放宽;普通婚恋 Mutual 后才能聊天;Block 优先级最高;红娘不得替用户 Like 或确认。
- 活动互选必须经过双方分别确认开启沟通,再复用或创建 Match Episode 和 Conversation。
- 本地资格独立于实名认证;咨询独立于红娘;所有新业务复用统一 User、Operator、RBAC、DataScope、Audit、Notification、Risk 和 Object Storage。
- 首页结构、8 个核心入口及其顺序固定;底部导航固定为首页、找对象、消息、活动、我的。
- 用户端采用 `#E96B6B` 品牌 Token、`#FAFAF8` 暖白背景、16px 水平边距、44×44px 最小点击区;禁止页面散落硬编码颜色。
- 所有未确认参数配置化;Feature Flag 仅用于灰度和故障关闭,不能把已确认的 V1.1 正式范围降为“以后再做”。
- 单智能体执行时按 Phase 01、02、03……13、13A、14……26 顺序;每个 Phase 输出 Completion Report 后停止。
---
## 一、对上一版计划的纠正
上一版计划的主要错误不是发现的问题失实,而是处理策略失实:
1. 错误地把主启动提示词当成单一产品规格;正确做法是六份客户修订文档共同约束。
2. 错误地把 V1.0 Phase 01~26 当成全部需要重建;客户文档明确要求“保留主结构、增量修订、不重建全部 Backlog”。
3. 错误地把“未重新验证”统一判成“未完成”;正确做法是 KEEP 项快速回归,只有失败项才进入修复。
4. 错误地声称 U49~U64 全部缺失;实际 U55~U59、U62~U63 已有页面文件,但类型检查和运行链路尚未通过;明确缺失的是 U49~U54、U60、U61、U64。
5. 没有充分区分“数据库已建表”“后端有骨架”“前端可操作”“业务闭环可验收”四种进度。
6. 没有把 Jira/STATUS/PENDING_DECISIONS 中未经验证的 ✅ 当作待清理的项目治理问题。
本计划因此采用:**增量恢复 + 纵向闭环 + 证据驱动状态**,而不是全项目推倒重来。
## 二、当前真实进度基线
### 2.1 已有资产
- V001~ V027 迁移文件及对应的 V1.1 表、字段、角色和种子数据已经存在。
- Backend 已有 home、local_eligibility、service_appointment、counseling、content、service_program、activity_mutual 等模块骨架。
- Miniapp 已有 U55~ U59、U62~U63 及活动互选结果/等待页面文件。
- Admin Web 已有 Banner、Content、Service Station、Appointment、Program、Counseling、Referral 等 Vue 文件。
- V1.0 Auth、Profile、Review、Match、Like/Block、Messaging、Relationship、Matchmaker、Activity、Risk、Appeal 模块可作为 KEEP 候选。
### 2.2 不能算作完成的证据
- Admin Web `npm run type-check` 当前失败:`CounselingView.vue` 存在语法错误;路由文件未注册 counseling 页面。
- Miniapp TypeScript 当前有 20 余个错误,且 `.ts` /`.js` 双轨并存,不能证明运行的是客户修订版本。
- U49 公益服务中心、U50 服务站、U51 预约、U52 我的预约、U53 课堂、U54 内容详情、U60 反诈、U61 专项服务、U64 服务记录没有注册为可访问页面。
- `/api/v1/operator/**` 当前只统一检查 `operator_login` ,不能满足 Permission + DataScope + Sensitive Permission。
- 用户预约创建仍可从请求体接受 `userId` ,存在替他人创建/越权风险。
- Counseling 的 operator 接口位于 `/counseling/services/operator/**` ,不受现有 `/operator/**` 过滤规则覆盖。
- Activity Mutual 代码只检测 active Match,没有形成“双方确认后复用/新建 Match Episode + Conversation”的完整事务。
- E2E 文件大量使用 `pass` ,不能证明功能通过;Jira 中相应 ✅ 必须回退为待验证。
- `docs/PENDING_DECISIONS.md` 同时存在“待确认”与“已部署”矛盾,且包含测试默认账号和密码描述,需清理。
### 2.3 分层进度估算
| 层级 | 当前估算 | 说明 |
|---|---:|---|
| V1.0 核心资产 | 70%~85% | 代码较完整,但需受影响回归 |
| V1.1 数据模型/迁移 | 80%~90% | 迁移齐全,仍需约束、权限和回滚验证 |
| V1.1 后端业务闭环 | 35%~50% | 多数有骨架,主体、权限、事务和真实聚合不足 |
| V1.1 小程序页面闭环 | 25%~35% | 部分页面存在,缺页、未注册、TS/JS 漂移明显 |
| V1.1 运营后台闭环 | 20%~30% | 文件存在但类型检查失败、路由/权限/交互不完整 |
| 自动化测试可信度 | 10%~ 20% | 大量空壳、fixture 缺失,无法支撑完成声明 |
| 发布就绪度 | 10%~15% | 无可信系统测试、UAT、备份恢复和回滚证据 |
综合开发资产约 45%~55%,可验收业务闭环约 30%~35%。后续进度只按“验收项通过数”计算,不再按文件数量计算。
## 三、修复策略与执行门禁
### 3.1 Phase 状态定义
- `KEEP-VERIFY` :不改业务设计,只跑回归;通过即可关闭。
- `EXTEND` :保留现有实现,补客户新增能力和测试。
- `REFACTOR` :保留数据资产,替换错误业务流程或权限边界。
- `REPLACE` :删除旧运行入口,只保留客户定稿实现。
- `ADD` :补齐不存在的页面、接口或运营闭环。
### 3.2 每 Phase 的统一完成证据
- 关联 Jira 任务状态与实际代码一致,禁止仅凭文件存在勾选 ✅。
- Backend 单元/集成测试通过;Admin type-check/build 通过;涉及 Miniapp 时 TypeScript 检查和开发者工具构建通过。
- 新增/修改 POST 的身份主体、幂等、并发和状态机测试通过。
- Permission、DataScope、Sensitive Access 负向用例返回 401/403/404,不能返回脱敏后的 200 冒充拒绝。
- 受影响业务至少完成一条真实 happy path 和一条失败路径人工验证。
- 更新 STATUS、JIRA_BACKLOG、API/数据库/UI 文档以及对应 Completion Report。
- 输出报告并停止,不自动进入下一 Phase。
## 四、按客户正式 Phase 的增量开发与修复计划
### Phase 01:项目治理与可重复构建基线 — EXTEND
**Files:** `AGENTS.md` 、`docs/STATUS.md` 、`docs/PENDING_DECISIONS.md` 、`docs/JIRA_BACKLOG.md` 、`docs/V1_0_TO_V1_1_GAP_ANALYSIS.md` 、`docs/ARCHITECTURE_BASELINE_V1.1.md` 、`README.md` 、`backend/pom.xml` 、`admin-web/package.json` 、`miniapp/project.config.json` 。
- [x] 将六份客户修订文档登记为共同需求基线,并按专业域定义冲突裁决规则。
- [x] 把未经验证的“已完成/已部署”改为 `待验证` 、`部分完成` 或 `失败` ;保留历史说明,不伪造完成记录。
- [x] 清除文档中的默认账号密码;测试账号改由本地 seed/环境变量生成且不进入交付文档。
- [x] 建立 Windows PowerShell 与 Bash 两套一键检查入口,覆盖 backend test、admin type-check/build、miniapp type-check、E2E。
- [x] 修复或重新初始化 Git 元数据问题;若无法恢复,记录仓库来源、当前文件清单和后续提交策略,不擅自覆盖用户文件。(当前无法恢复,已记录并等待用户决定)
- [x] 生成 Phase 01 Completion Report 后停止。
**Gate:** 三端检查命令可重复启动并给出真实成功/失败;项目状态文件不再互相矛盾。
### Phase 02:统一认证、RBAC、DataScope 与敏感访问 — REFACTOR
**Files:** `backend/src/main/java/com/danyang/match/platform/shared/filter/PermissionFilter.java` 、`permission/**` 、`security/**` 、`audit/**` 、V015 后续新迁移、`admin-web/src/stores/auth.ts` 、`admin-web/src/router/index.ts` 。
2026-09-10 10:58:43 +08:00
- [x] 先写角色×资源×动作×数据范围矩阵测试,覆盖 counselor、counseling_manager、content_editor、service_station_operator。
- [x] 用明确的用户 Principal 和 Operator Principal 替代各 Controller 自行解析 token/userId。
- [x] 移除 `/operator/** → operator_login` 粗粒度授权,改为接口 Permission + Service DataScope 双重校验。
- [x] 把当前不在 `/operator/**` 下的运营接口统一迁移或施加同等级方法权限。
- [x] 验证 ContentEditor 无用户婚恋数据权限、Counselor 仅 Assigned、ServiceStationOperator 仅站点/任务范围、Organization 关系不继承权限。
2026-09-09 22:05:00 +08:00
**Gate:** 权限正向用例通过,四类越权负向用例全部被服务端拒绝并写审计;前端菜单隐藏仅作为体验,不作为安全控制。
### Phase 03:实名认证增量预留 — EXTEND
**Files:** verification 模块、`miniapp/pages/verification/**` 、FeatureFlag 配置。
2026-09-13 21:12:50 +08:00
- [x] 验证 V1.0 实名、年龄、加密/hash 和状态流转回归。
- [x] 保留 liveness/provider/verification_level 预留;人脸首发未确认前不实现自研识别、不保存 face embedding。
- [x] 删除任何“官方婚姻状态认证、100%真实”的前端文案。
2026-09-09 22:05:00 +08:00
**Gate:** 实名状态来自数据库而非首页硬编码;人脸 Flag 关闭时流程可正常完成。
### Phase 04: Profile、Preference 与本地资格 — EXTEND
**Files:** `local_eligibility/**` 、profile/status/capability 服务、`miniapp/pages/local-eligibility/**` 、`miniapp/pages/local-eligibility-supplement/**` 。
2026-09-13 21:12:50 +08:00
- [x] 保留 V1.0 Profile/Preference,补齐本地资格声明、按需补证、提交、状态查询和 `/me/status` 。
- [x] 用户 API 的 userId 只能来自认证主体;佐证文件进入私有存储,先鉴权再签名。
- [x] 将本地资格佐证触发规则、数量、大小、类型和保留期限全部配置化。
- [x] 把 U62/U63 接入首次准入与“我的”,并覆盖未提交、声明完成、待补充、审核中、已核验、未通过状态。
2026-09-09 22:05:00 +08:00
**Gate:** 本地资格与身份表独立;非本人和无特殊权限人员不能读取佐证。
2026-09-13 21:12:50 +08:00
### Phase 05:统一审核扩展 — EXTEND( 2026-09-12 已完成)
2026-09-09 22:05:00 +08:00
**Files:** review 模块、local eligibility service、`admin-web/src/modules/review/ReviewView.vue` 。
2026-09-13 21:12:50 +08:00
- [x] 复用现有 ReviewTask,增加 local_eligibility 类型,不建第二套审核引擎。
- [x] 验证 Claim 原子性、Need Evidence、Approve、Reject 与本地资格状态联动。
- [x] 每次查看敏感佐证记录 purpose、operator、target、timestamp、result。
2026-09-09 22:05:00 +08:00
**Gate:** 两名审核员不能同时 claim;审核通过/拒绝与前台状态一致。
2026-09-13 21:12:50 +08:00
### Phase 06: Match Eligibility 增量 — KEEP/EXTEND( 2026-09-12 已完成)
2026-09-09 22:05:00 +08:00
**Files:** `match/service/MatchEligibilityService.java` 、`RecommendationEngineService.java` 、对应测试。
2026-09-13 21:12:50 +08:00
- [x] 先跑 V1.0 双向 Required、Block、Paused、Successful 和隐私回归,不重写正确算法。
- [x] 仅在配置要求时把本地资格接入 eligibility;不得自动放宽 Required。
- [x] 确认首页推荐仍调用正式 Match Engine,推荐数量、阈值、冷却均配置化。
2026-09-09 22:05:00 +08:00
**Gate:** 双方任一 Required 不满足时永不入选;前台不显示数字匹配率。
2026-09-13 21:12:50 +08:00
### Phase 07: V1.1 首页唯一实现 + 找对象 — 业务证据保留,UI REOPENED( 2026-09-13)
> 后端聚合、Capability、8 入口及推荐规则的专项证据保留;旧页面视觉已被用户否决。当前 UI 实施入口仅为 `docs/superpowers/plans/2026-09-13-reference-driven-dual-client-ui-redesign.md`,不得按本节历史完成标记恢复旧设计。
2026-09-09 22:05:00 +08:00
**Files:** `home/**` 、banner 读取服务、`miniapp/pages/index/**` 、`miniapp/pages/discover/**` 、首页组件、`miniapp/app.json` 、Design Token。
2026-09-13 21:12:50 +08:00
- [x] 为 HomeApplicationService 写聚合契约测试,确保它调用正式 status、match、activity、location、content、capability 服务,不复制规则。
- [x] 修复硬编码 verified、空 recommendations/articles、固定服务站和错误入口路由。
- [x] 固定首页顺序:品牌、状态、Banner、8 入口、推荐、公益服务、活动、服务站、课堂、安全提醒。
- [x] 固定 8 入口顺序并分别路由到真实页面;未开放时展示服务端 Capability 返回的 Disabled 原因。
- [x] 统一 TypeScript 为唯一源,配置小程序 TypeScript 编译;移除同页手写 `.ts` /`.js` 逻辑漂移。
- [x] 落实未登录、未实名、审核中、Searching、Paused、Successful、空数据、网络错误、Skeleton 状态矩阵。
- [x] 迁移完成后删除旧首页运行逻辑,不保留 `/home-old` 。
2026-09-09 22:05:00 +08:00
**Gate:** 首页 5 秒识别品牌和主要入口;Banner 仅内部目标;首页真实聚合数据可用;小程序 TS 检查和开发者工具构建通过。
2026-09-16 15:11:38 +08:00
### Phase 08: Like / Match / Block — KEEP-VERIFY/EXTEND( 2026-09-16 已完成)
> 复验中发现并修复 3 处真实缺陷:搜索完全绕过 Block(INV-004「搜索不可见」整体失效)、
> 详情页对双向拉黑者仍可见、`matches.source` 取值越界(实测 Mapper 传 `"liked"`,违反 `V003` 的 `chk_match_source`,
> 仅在 H2 测试库无该约束时才静默通过)。详见 `docs/Phase-08-V11-Recovery-Completion-Report-2026-09-16.md`。
2026-09-09 22:05:00 +08:00
**Files:** relationship 模块、discover/relationship 页面和对应测试。
2026-09-16 15:11:38 +08:00
- [x] 验证 Like、Pass、普通 Mutual、Unmatch、Block 全链路。
- [x] 增加 Activity Match Episode 兼容,不改变普通 Match 的双向 Like 规则。
- [x] 验证 Block 后推荐排除、搜索不可见、聊天停止且无法由缓存绕过。
2026-09-09 22:05:00 +08:00
**Gate:** V1.0 核心回归通过;活动来源兼容不会创建第二套 Match 逻辑。
2026-09-16 16:42:48 +08:00
### Phase 09: Text Chat — KEEP-VERIFY/EXTEND( 2026-09-16 已完成)
> 复验中发现并修复 4 处真实缺陷:① WebSocket 下行整条链路是死代码(无握手鉴权、无 userId 写入、
> `sendToUser` 零调用点);② Unmatch 只改 Match 不联动会话,且发消息只校验会话状态 → 解除匹配后仍可发消息;
> ③ `RelationService.block` 调用静态 `MatchService.unmatch`(只改内存态)→ Block 后 Match 未落库;
> ④ 聊天四个读/写接口无会话成员校验 → 任意登录用户可读他人私聊(IDOR)。
> 详见 `docs/Phase-09-V11-Recovery-Completion-Report-2026-09-16.md`。
2026-09-09 22:05:00 +08:00
**Files:** `messaging/**` 、WebSocket 配置、Miniapp messages/chat 页面。
2026-09-16 16:42:48 +08:00
- [x] 验证 REST send + WebSocket receive、消息幂等、重连和未读计数。
- [x] 验证非 active Match 禁聊,Unmatch/Block 后即时禁聊。
- [x] 让活动双确认产生的 Conversation 复用同一消息体系。
2026-09-09 22:05:00 +08:00
**Gate:** 未 Mutual 或活动未双确认时不能发消息;正常会话不重复投递。
### Phase 10: Image & Chat Safety — KEEP-VERIFY
**Files:** photo 模块、message safety、对象存储配置和聊天页面。
2026-09-16 21:00:52 +08:00
- [x] 验证图片私有访问、类型/大小校验、审核和水印。
- [x] 验证风险识别、举报入口和违规内容处理。
- [x] 检查日志不记录聊天正文、身份证、手机号或签名 URL。
2026-09-09 22:05:00 +08:00
**Gate:** 越权图片访问被拒绝,敏感内容不进入普通日志。
2026-09-16 21:00:52 +08:00
( 2026-09-16 复验通过:修复 D1 图片上传魔数校验死代码——本地资格佐证上传曾 100% 失败;D2 高风险词写入普通日志。水印未实现,登记 gap。)
2026-09-09 22:05:00 +08:00
### Phase 11: Notification — EXTEND
**Files:** `notification/**` 、预约/咨询/资格/活动服务及通知页面。
2026-09-16 21:50:56 +08:00
- [x] 新增预约、咨询、辅导、本地资格和活动双确认通知。
- [x] 统一在业务事务提交后发送,发送失败不回滚核心事实。
- [x] 锁屏和通知摘要使用隐私安全文案,不泄露咨询主题或单向意向。
2026-09-09 22:05:00 +08:00
**Gate:** 回滚事务不发通知;已提交事务通知失败可重试且不产生重复业务记录。
2026-09-16 21:50:56 +08:00
( 2026-09-16 复验:修复 D3——10 种通知 type 违反生产 CHECK 约束致全部落库失败;D1——补通知幂等唯一索引
V036;D2——接线婚前辅导及管理端排期通知。`sendExternal` 在事务内执行的缺口已登记,接入真实微信 API 前须
改为提交后发送。真机文案 INV-010 达标。)
2026-09-09 22:05:00 +08:00
### Phase 12: Relationship Progress — KEEP-VERIFY/EXTEND
**Files:** relationship 状态服务、Match Episode、relationship-status 页面。
2026-09-16 23:01:13 +08:00
- [x] 验证成功关系双确认、恢复/退出、历史 Episode 和并发确认。
- [x] 补充 getting_to_know 阶段的婚前辅导入口引导。
- [x] 验证工作人员不能替用户确认成功关系。
2026-09-09 22:05:00 +08:00
**Gate:** 单方确认不改变最终关系;历史 Episode 可追踪但不会恢复旧聊天权限。
2026-09-16 23:01:13 +08:00
( 2026-09-16 复验:修复 D1——实体与生产迁移系统性漂移,23 表 50 列缺失,其中 `matches.episode`
等 11 张表属"INSERT 必崩"级生产故障,真实 PG 上 Match 创建 / 偏好保存 / 权限写入等全部失败;
D2——`RelationshipService.createMatch` 不写 episode/lastActivityAt,与 `MatchService` 双路径字段不一致,
且 `episode` 为 null 时 `getEpisode() + 1` 自动拆箱 NPE; D3——测试库缺 `user_identities` 等 7 张表,
致 `GET /home` 在测试环境直接 BadSqlGrammar,首页零回归覆盖;D4——Phase 12 计划项 2 实际未实现
( getting_to_know 只给 counseling,无婚前辅导入口)。新增 `EntityMigrationParityTest` 把
「实体字段 ⊆ 生产迁移列」「测试库覆盖关键表」固化为自动守卫,并经负向验证证明会变红。
真机行为:双确认/并发确认/历史 Episode 不恢复旧聊天/非成员不可代确认 —— 14 项全绿。)
2026-09-09 22:05:00 +08:00
### Phase 13:公益红娘转介 — EXTEND
**Files:** `matchmaker/**` 、`referral/**` 、Miniapp 红娘页面、Admin referral 页面。
2026-09-17 00:01:53 +08:00
- [x] 保留红娘服务和人工推荐;验证任何工作人员不能替用户 Like。
- [x] 补齐转介咨询、活动、服务站的用户同意、来源追踪和状态记录。
- [x] 红娘只能看转介状态和必要摘要,不能读取 counseling followup 正文。
2026-09-09 22:05:00 +08:00
**Gate:** 转介形成可追踪记录但不越权;用户决定权测试通过。
2026-09-17 00:01:53 +08:00
> **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`
2026-09-09 22:05:00 +08:00
### Phase 13A:婚恋咨询与婚前辅导 — REFACTOR/EXTEND
**Files:** `counseling/**` 、`miniapp/pages/counseling-*` 、`miniapp/pages/my-counseling/**` 、`miniapp/pages/premarital-*` 、`admin-web/src/modules/counseling/CounselingView.vue` 、router。
2026-09-17 01:25:12 +08:00
- [x] 修复 Admin Vue 语法错误并注册 `/counseling` 路由,先使 type-check 失败转为通过。
- [x] 用户申请接口从认证主体取 userId;补幂等、取消、详情 owner 校验和合法状态迁移。
- [x] 分配操作使用条件更新/版本号解决并发;Counselor 只能读取和操作 Assigned Service。
- [x] Counseling Manager 可分配和查看必要摘要;普通管理员、红娘、内容编辑不得读取咨询正文。
- [x] 婚前辅导复用 counseling service type;邀请平台内伴侣必须由对方自主确认。
- [x] U55~U59 修复类型错误、API 契约、Loading/Empty/Error/Permission 状态和非医疗化文案。
2026-09-09 22:05:00 +08:00
**Gate:** 申请→分配→预约→服务→完成→反馈真实闭环通过;所有隐私负向用例通过。
2026-09-17 01:25:12 +08:00
> **复验完成(2026-09-17) ** — Tag: `phase13a-recovery-2026-09-17`
>
> 复验发现 counseling 模块存在**双实现**:线上权威 `CounselingService`( 167 行)
> **零测试**,唯一被测的 `CounselingServiceApp`( 280 行)是**孤儿类**
> (无注入点、无端点可达,生产永不执行)。已合并并删除孤儿类。
>
> **9 处缺陷(D1~D9) **:
> - 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 /services/intro` 后端不存在,小程序 intro 页 100% 无数据
> (且被 `/services/{id}` 吞掉)→ 已补端点并置于变量路径之前。
> - D7 Medium: Admin 调用 5 条不存在的运营端端点(404)+ 缺四态。
> - D8 Medium:小程序字段名不匹配 + 无幂等 + 未检查 `success`(403 静默空列表)+ 跳转不存在的页。
> - D9 Medium 测试保真度:测试库 counseling 两表**零 CHECK 约束**, `counseling_services` 零覆盖。
>
> **另修 4 处测试基建缺陷(T1~T4) **:守卫因 surefire `workingDirectory` 指向仓库根而
> **找不到 DDL**(恒真假绿);全限定 `@TableField(exist=false)` 漏解析(假警报);
> 权限守卫扫到私有辅助方法(假阳性);两处测试自身逻辑缺陷。
>
> **负向验证两轮**:① DDL 常量守卫 —— 从 V039 移除 `scheduled` → 守卫精准变红
> (证明解析的是**真实 DDL** 而非副本);② 行为守卫 —— 注入并发/INV-013/状态机
> 三个缺陷 → 三个用例精准变红。均已还原。
>
> **全量回归实测**: `[WARNING] Tests run: 420, Failures: 0, Errors: 0, Skipped: 3` /
> `BUILD SUCCESS`( 4 分 49 秒)。Phase 13 基线 391 → 420(净 +29)。
> **Phase 13A 已关闭。Phase 14 未自动进入,等待用户确认。**
> 报告:`docs/Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md`
2026-09-09 22:05:00 +08:00
### Phase 14:多类型公益活动 — REFACTOR/EXTEND
**Files:** activity 模块、Miniapp activity 页面、Admin activity 页面。
2026-09-17 14:02:00 +08:00
- [x] 保留活动基础,完成 ActivityType 分类、按类型报名策略、capacity groups 和多组织关系。
- [x] 完成小程序分类 Tabs、类型化卡片、动态资格提示和后台动态表单。
- [x] 验证主办组织关系不自动授予用户库访问权限。
2026-09-09 22:05:00 +08:00
**Gate:** matchmaking 与课堂/反诈类活动显示和资格策略不同;容量按配置正确扣减。
2026-09-17 14:02:00 +08:00
> **复验完成(2026-09-17) ** — Tag: `phase14-recovery-2026-09-17`
>
> **11 处后端缺陷(D1~D11) **:
> - D1 **Critical 生产故障**: `ActivityMapper.countRemainingCapacity` 无 `@Select` 无 XML
> → 活动详情/报名/审核三条路径必抛 `Invalid bound statement`。
> - D2 **Critical 并发**:报名与审核均为「先读后写」→ 并发超卖;改
> `insertIfCapacityAvailable` / `approveIfCapacityAvailable` 单条原子 SQL。
> - D3 High 生产故障:`activityType` / `orgRole` 未校验生产 `chk_activity_type` /
> `chk_org_role` 白名单("只在 PG 上炸")。
> - D4 High 契约:`ActivityListItemDTO` 无 `activityType` → 小程序分类 Tabs 恒无数据。
> - D5 Medium:男女人数为 `approvedCount/2` 编造 → 改按 `user_profiles.gender` 真实统计。
> - D6 Medium:年龄门槛为 TODO 空壳,完全不生效。
> - D7 Medium: `registration_policy` 只写不读,按类型资格策略为空(Gate 未落地)。
> - D8 Medium: `POST /operator/activities` 丢弃类型/多组织/容量分组,且把
> `organizer_org_id` 错设为操作者 userId → 后台动态表单无法创建带类型活动。
> - D9 Medium:三个运营写入端点错挂在**用户端** `ActivityController`(双实现、零调用方)。
> - D10 Medium NPE:软删活动致 `getMyActivities` NPE;后台漏填字段致创建活动 500。
> - D11 Medium 契约:DTO 缺 `registeredCount`/`status`/`coverFileId`/`description`
> → 卡片报名人数恒 0、按钮恒"查看详情"、封面与摘要恒不显示。
>
> **3 处前端契约缺陷(F1~F3) **:小程序分类 code `classroom` 不在生产白名单
> (应为 `relationship_education`)且缺三类入口;卡片读取 7 个后端根本不存在的字段;
> admin-web 完全没有活动管理页(已新增 `ActivityManagementView.vue` 类型驱动动态表单)。
>
> **2 处测试保真度缺陷(T1~T2) **: `testNoOverbooking` /
> `testNoDuplicateRegistration` 为 `assertTrue(true)` 占位假绿(已删除);
> 测试库缺 V023 列与三张表,且 activity 五表在 `EntityMigrationParityTest`
> 只属"可选白名单"(零覆盖)→ 已补齐并移入必选集合。
>
> **负向验证两轮**:① 后端 —— 从 V023 删 `anti_fraud` + 报名退化为无容量检查
> → 3 条用例精准变红;② 前端契约 —— 分类 code 改回 `classroom` + 卡片加回
> `activity.suitableFor` → 3 条守卫精准变红。均已还原。
>
> **全量回归实测**: `[WARNING] Tests run: 450, Failures: 0, Errors: 0, Skipped: 3` /
> `BUILD SUCCESS`( 4 分 52 秒)。Phase 13A 基线 420 → 450(净 +30)。
> admin-web `vue-tsc --noEmit` 0 error、`vite build` 通过。
> **Phase 14 已关闭。Phase 15 未自动进入,等待用户确认。**
> 报告:`docs/Phase-14-V11-Recovery-Completion-Report-2026-09-17.md`
2026-09-09 22:05:00 +08:00
### Phase 15:活动报名、审核与签到 — KEEP-VERIFY/EXTEND
**Files:** activity registration、checkin 服务和 U29~ U32 页面。
2026-09-17 15:07:52 +08:00
- [x] 回归报名、审核、取消、签到码、重复签到和名额并发。
- [x] 增加非 matchmaking 活动和 capacity group 场景测试。
- [x] 服务站操作员只能操作指定活动或站点任务。
2026-09-09 22:05:00 +08:00
**Gate:** 重复请求和并发报名不超额;签到不可跨活动复用。
2026-09-17 15:07:52 +08:00
> **2026-09-17 复验关闭**:修复 16 处缺陷(8 处签到 + 5 处报名/审核/取消 + 1 处容量分组 + 2 处前端契约)
> + 3 处测试保真度缺陷。两处必崩:**D1 签到码一生成即作废**( `generateCheckinToken` 写 `"used"`,
> 扫码 100% 失败)、**D9 取消后永远无法再报名**(撞生产 `UNIQUE(activity_id,user_id)`,
> 测试库缺该约束故零覆盖)。新增 V040 `activity_staff_assignments` 落实签到数据范围(INV-020)。
> 一轮负向验证:3 处注入 → 8 条用例精准变红并还原。全量回归 **474 tests 全绿**(基线 450)。
> 报告:`docs/Phase-15-V11-Recovery-Completion-Report-2026-09-17.md`
> **Phase 16 未自动进入,等待用户确认。**
2026-09-17 16:47:10 +08:00
### Phase 16:活动互选与双方开启沟通确认 — REFACTOR ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验关闭)
2026-09-09 22:05:00 +08:00
**Files:** activity_mutual、relationship、messaging 模块及 activity-mutual 页面。
2026-09-17 16:47:10 +08:00
- [x] 以 activity_mutual_connection_consents 为唯一逻辑,双实现统一到 `RelationshipService.confirmActivityInterest` 。
- [x] 双方确认事务中:已有 active Match 则复用已有会话;历史 Unmatch 则复用同一行(episode 递增 + reopen);无历史则创建 Match 和 Conversation。
- [x] 补 decline、expires_at 超时、重复确认幂等、并发确认(exactly-once)和单向意向保密(INV-006)测试。
2026-09-09 22:05:00 +08:00
**Gate:** A 单选 B 时 B 无感知;Mutual 但未双确认时无新 Chat;双确认后 exactly-once 形成正确 Match/Conversation。
2026-09-17 16:47:10 +08:00
> **2026-09-17 复验结论(KEEP-VERIFY/EXTEND):** 历史 ✅ 不可信,逐条核对运行时路径后发现**活动互选核心 Gate 缺陷**——
> 新路径 `ActivityMutualConsentController.confirmConnection` 双确认后**根本不建 Match/会话**(违反 INV-014/015),而旧路径
> `ActivityInterest.confirmInterest`→`confirmActivityInterest` 建 Match 却**缺会话**;两条路径分裂。已统一到
> `RelationshipService.confirmActivityInterest` 单实现。修复 **7 处缺陷 + 1 处隐藏编译缺陷 + 1 处测试保真度缺陷**:
> - **D1( Critical, Gate 缺陷 · INV-014/015) ** 双确认后不建 Match/会话 → 重写为 `confirmConnection` 走
> `confirmActivityInterest`,由原子 `confirmSideIfPending` 保证 exactly-once( `both_confirmed_at` NULL→非NULL 仅一方赢家建 Match+会话并 `bindMatch` 溯源);单方确认不建 Match。
> - **D2(High,双实现分裂)** 旧/新路径各自为政 → 统一到 `RelationshipService.confirmActivityInterest`(返回 `matchId` + `priorUnmatch`)。
> - **D3(High,隐藏编译缺陷 · 必崩级)** Phase 15 提交态引用 `matchMapper.reopenEpisode` 但该方法**从未定义** → 整个
> activity_mutual / relationship 模块**根本不编译**, **"474 绿"基线从未真实存在**。修复:在 `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` 现在**显式**调用
> `chatService.getOrCreateConversation` 并返回 `conversationAutoCreated=true`。
> - **D6( Medium,测试库零覆盖)** `schema-h2.sql` 缺 `activity_mutual_connection_consents` 表 → 补表
> (含 `deleted_at`/`expires_at`/`match_id` 与 `chk_consent_status` CHECK、UNIQUE(activity_id,user_a_id,user_b_id)),与 V024+V037+V041 对齐;
> `EntityMigrationParityTest` 将其从 `TEST_SCHEMA_OPTIONAL_TABLES` 移入 `REQUIRED_IN_TEST_SCHEMA`; `MigrationValidationTest` 基线 40 → 41。
> - **D7( Medium,无互选测试)** 新建 `ActivityMutualConsentServiceTest`( 7 用例:双确认建 Match+会话+溯源、INV-006 单向不暴露、
> decline 阻止、幂等重确认不重复建、expires_at 超时拒绝、软删过滤、复用 active Match),`@SpringBootTest` 走真实方法路径。
> - **D8( Medium,断言与 #20 冲突)** `ChatPhase09IntegrationTest:344` 假设"每次活动互选新建独立会话",与 AGENTS.md #20
> "同对用户 Unmatch 后重连复用同一 Match 行、会话随之复用"冲突 → 改为 `assertEquals`(认可复用),保留 sendText/WebSocket/未读主断言以验证"复用同一消息管线"。
> - **负向验证**:临时注释 `createMatchAndConversation(consent)` 调用 → `ActivityMutualConsentServiceTest` 中 doubleConfirm + idempotent
> 两条依赖 Match 的用例**精准变红**( `Tests run: 7, Failures: 2`)→ 证明守卫有牙 → 已还原(`grep -c "NEG-VAL"` = 0)。
> - 新增迁移 `V041__extend_mutual_consent_expiry.sql`( `expires_at` + `match_id` + 索引)。
> - 全量回归 **481 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS**(约 5 分)。基线 474 → 481(净 +7)。
> - 报告:`docs/Phase-16-V11-Recovery-Completion-Report-2026-09-17.md`。**Phase 17 需用户确认后启动。**
2026-09-17 20:42:09 +08:00
### Phase 17:举报与风控 — EXTEND ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
2026-09-09 22:05:00 +08:00
**Files:** risk、report、referral 模块和后台风险页面。
2026-09-17 20:42:09 +08:00
- [x] 将 counseling、service_station、offline_activity 作为风险来源接入统一 RiskEvent(运行时已真实调用,本轮确认非假绿)。
- [x] 后台显示必要来源上下文但不暴露无关咨询正文(INV-006 同族最小可见约束延续)。
- [x] 禁止公开黑名单;举报、处置、Block 与敏感访问继续审计(补 D2 人工标记审计、D3 敏感访问审计、D4 审计 ip/ua)。
2026-09-09 22:05:00 +08:00
2026-09-17 20:42:09 +08:00
**Gate:** 风险来源可追踪 ✅、正文最小可见 ✅、低权限人员不能扩大读取范围 ✅。
**复验结论:** 修复 6 处真实缺陷(D1 测试库缺三表必崩级盲区、D2 人工标记无审计、D3 敏感访问无审计、D4 审计缺 ip/ua、D5 findByUserId 未过滤软删、D6 jakarta 编译缺陷+risk_events 漏 updated_at);新增集成测试 7 例;全量回归 488 全绿。
**报告:** `docs/Phase-17-V11-Recovery-Completion-Report-2026-09-17.md` 。**Phase 18 需用户确认后启动。**
2026-09-09 22:05:00 +08:00
2026-09-17 21:07:25 +08:00
### Phase 18:申诉 — KEEP-VERIFY ✅ 已完成(2026-09-17 KEEP-VERIFY 复验通过)
2026-09-09 22:05:00 +08:00
**Files:** appeal 模块、Miniapp appeal 页面和后台 AppealCenter。
2026-09-17 21:07:25 +08:00
- [x] 回归 ban/suspend 申诉、幂等处理、审批和解除动作。
- [x] 验证申诉不能绕过仍有效的其他风险处置(负向验证已证守卫有牙)。
- [x] 是否首发继续由已确认 Feature Flag 控制(`features.appeal-enabled` , dev/docker 均 false)。
2026-09-09 22:05:00 +08:00
2026-09-17 21:07:25 +08:00
**Gate:** 申诉通过只解除目标处置 ✅;拒绝后原处置保持有效 ✅。
**复验结论:** 修复 8 处真实缺陷(D1 测试库缺 `appeals` 表 + `AppealServiceTest` 6 处假绿 → 零覆盖;**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);新增 `AppealPhase18IntegrationTest` ( 15 例),删除假绿 `AppealServiceTest` ( 9 例);全量回归 494 全绿。
**报告:** `docs/Phase-18-V11-Recovery-Completion-Report-2026-09-17.md` 。**Phase 19 需用户确认后启动。**
2026-09-09 22:05:00 +08:00
### Phase 19:统一运营后台 + 用户端公益服务页面 — ADD/REFACTOR
**Files:** Admin banner/content/service-station/service-appointment/service-program/counseling/referral 模块、MainLayout/router; Miniapp 新增 U49~ U54、U60、U61、U64 页面;service API 文件。
2026-09-17 22:21:31 +08:00
- [x] 先修复 Admin 全量 type-check 和角色路由,再实现“角色第一屏知道今天做什么”的待办型工作台。
- [x] Banner 完成 CRUD、排期、排序、Audience、内部 target 校验和预览;禁止外链。
- [x] Content 完成分类、文章编辑、发布/下架;用户端只做文章列表/详情,不做 Feed、评论和点赞。
- [x] Service Station 完成万善公园站信息、开放时间、公告、服务项目和预约管理。
- [x] 修复预约 IDOR:普通用户创建、详情、列表、取消只能操作本人;代登记使用独立 operator 接口和权限。
- [x] Service Program 完成项目、申请、审批、退出和必要统计,禁止把项目成员身份变成用户价值标签。
- [x] 新增并注册 U49 公益服务中心、U50 服务站、U51 预约、U52 我的预约、U53 课堂、U54 内容详情、U60 反诈、U61 专项服务、U64 公益服务记录。
- [x] 重构 U37“我的”四组结构,接入上述新增页面;U64 只显示用户自己的服务时间线,不显示内部备注。
- [x] 所有页面复用统一 Token 和组件,覆盖 Loading、Skeleton、Empty、Error、Permission、Disabled、Responsive。
2026-09-09 22:05:00 +08:00
2026-09-17 22:21:31 +08:00
**Gate:** 小程序 U01~U64 页面清单无缺页且路由可达 ✅(`ui-tests/ui-contracts.mjs` : `app.json` 63 页);七类后台角色只看到自己的工作 ✅(`admin-role-navigation-contracts` + `V11PermissionMatrixContractTest` 扫全部迁移 + `OperatorEndpointPermissionCoverageTest` );后台 type-check/build 通过 ✅(`vue-tsc --noEmit` EXIT=0、`vite build` EXIT=0)。
**复验结论:** 修复 **25 处真实缺陷** 。高价值项:**Service Station 公告能力整条不可达**( Service 与 V042 表都已存在但全仓零端点,后台与小程序都拿不到)→ 补运营端五端点 + 用户端只读端点 + 后台公告 UI + 小程序 U50 公告区块;
**服务站 `create/update` 越权写** (类级 `service_location.view` 兜底,V015 的 `service_location.manage` 是从未被使用的死权限)→ 权限下沉方法级,并把该控制器纳入权限覆盖守卫(此前未纳入,正是缺陷长期隐形的原因);
**Banner 校验失败落 500** (裸 `RuntimeException` )→ 统一 `VALIDATION_ERROR` ,并补软删过滤(软删 Banner 曾仍上首页);
**Content「发布」是死路** (后台复用只返回 `published` 的公开接口,草稿永不出现)→ 运营端接口分离;**Service Program 审批死路 / 草稿项目泄露 / 成员数恒 0 / 「退出」未实现 / 重复申请撞唯一键**;
**测试库缺 `content_categories` 与 `service_location_announcements`** → 对应路径零覆盖(约束漂移盲区),已补表并移入必选集合。
新增守卫:`ServiceLocationAnnouncementPhase19IntegrationTest` (24) / `ServiceLocationControllerPermissionContractTest` (5) / `ServiceLocationAnnouncementConstraintParityTest` (5,**生产 DDL ↔ 测试库 ↔ 后端白名单 ↔ 后台标签** 四方一致);`V11PermissionMatrixContractTest` 由硬编码 V015+V029 改为扫描全部迁移,消除「后续迁移权限变更隐形」。
负向验证:注入 3 处缺陷(移除软删过滤 / 移除测试库 CHECK / 写端点降级为 `view` )→ **4 个用例精准变红且无无关失败** ,还原后 `NEG-VAL` 残留 0。
全量回归 **602 tests 全绿** (起点 420);admin-web `vue-tsc` EXIT=0 + `vite build` EXIT=0;小程序 `tsc --noEmit` EXIT=0; ui-tests 14/14。
**报告:** `docs/Phase-19-V11-Recovery-Completion-Report-2026-09-17.md` 。**Phase 20 需用户确认后启动。**
2026-09-09 22:05:00 +08:00
### Phase 20:公益服务 Analytics — EXTEND
**Files:** analytics 模块、统计查询/事实表后续迁移、Admin Analytics 页面、`docs/ANALYTICS_METRICS.md` 。
- [ ] 为每个指标登记名称、定义、分子分母、去重键、时间字段、时区、版本和负责人。
- [ ] 分离服务用户数与服务人次、活动 mutual/confirmed/match/chat/success、Banner impression/click。
- [ ] 有效交友匹配在口径未确认前标为 provisional,不能当正式成功或对外宣传。
- [ ] 所有统计接口应用 `analytics.view` 和组织/站点 DataScope,低权限账号返回 403。
**Gate:** 用固定测试数据人工复算一致;相同用户多次服务不会污染去重人数。
### Phase 21:账户生命周期 — EXTEND
**Files:** `account/service/AccountLifecycleService.java` 、预约/咨询/项目/资格服务、数据保留文档。
- [ ] 注销前检查进行中的预约、咨询、项目和本地资格审核。
- [ ] 注销事务关闭未来服务、退出项目、失效本地资格并匿名化允许保留的服务历史。
- [ ] 数据保留期限未确认的敏感材料采用配置和人工审核,不擅自永久保存或删除。
**Gate:** 注销后不能登录/推荐/聊天;统计留痕不反向暴露个人和咨询正文。
### Phase 22: Deployment / Ops — EXTEND
**Files:** Dockerfiles、`infrastructure/docker-compose*.yml` 、Nginx、backup/restore/deploy/gray-release scripts、OPS/DEPENDENCIES 文档。
- [ ] 删除 Backend 镜像跳过测试的发布路径;CI 构建必须先测试再打包。
- [ ] 生产关闭 Mock WeChat、默认密码、Debug、Swagger 和演示 Seed; Secret 全部由环境变量/Secret 文件注入。
- [ ] 建立 `/api/v1` 、WebSocket、私有对象、6688 端口检测及国内依赖镜像说明。
- [ ] 备份加密并存放独立位置,执行一次 PostgreSQL + 对象存储实际恢复演练。
- [ ] Rollback 明确回到哪个稳定镜像/版本;Flyway 只向前修复,不破坏 V001~ V027。
**Gate:** staging 部署、健康检查、恢复演练和版本回滚都有命令、日志与结果证据。
### Phase 23:可信系统测试重建 — REFACTOR
**Files:** `backend/src/test/**` 、`tests/e2e/**` 、`tests/invariants/**` 、测试 fixture/seed、CI scripts。
- [ ] 删除测试体中的空 `pass` ,建立可隔离的用户、角色、组织、活动、咨询和预约 fixture。
- [ ] INV-001~020 必须测试真实服务行为,不能只断言常量字符串存在。
- [ ] E2E 覆盖首页聚合、Banner、资格、咨询、预约、内容、多类型活动、二阶段同意、组织隔离。
- [ ] 增加 appointment owner、Counselor Assigned、ContentEditor zero-user-data、station scope 等负向安全测试。
- [ ] CI 串联迁移、backend test、admin type-check/build、miniapp type-check 和 E2E,任何失败阻断发布。
**Gate:** 不允许 skip/pass 空壳;报告列出总数、通过、失败、跳过及原因,失败为零才进入 UAT。
### Phase 24: UAT — EXTEND
- [ ] 按用户、Reviewer、Matchmaker、Counselor、Counseling Manager、Service Station Operator、Content Editor、Activity Manager、Risk Operator 分角色验收。
- [ ] 验收线上主路径、线下扫码路径、咨询路径、辅导路径、服务站路径、活动二阶段确认和反诈举报路径。
- [ ] UI 按 375px 小程序基准和 1440px 后台基准检查,并覆盖弱网、空态、错误态、权限态。
**Gate:** 所有 P0/P1 客户场景有签字结果;阻断缺陷为零。
### Phase 25: RC — EXTEND
- [ ] 只使用客户确认的真实 Banner、站点、咨询、课堂、反诈、关于我们和组织信息;不 Seed 假用户/假 Match。
- [ ] 完成隐私政策、用户协议、敏感文案和“非官方婚姻状态核验”提示审核。
- [ ] 冻结 RC 镜像、数据库版本、配置清单、第三方依赖和回滚目标。
**Gate:** Go/No-Go 清单通过;所有未决事项有明确 Flag/配置行为和责任人。
### Phase 26: Production — EXTEND
- [ ] 上线前备份,执行 V027 及后续向前迁移,验证角色权限和真实基础内容。
- [ ] 依次执行 Home、Quick Entries、Service Station、Counseling、Content、Activity Mutual、Chat、Block smoke。
- [ ] 首日监控错误率、延迟、登录、推荐、消息、预约、咨询和权限拒绝;异常按已验证 Rollback 操作。
**Gate:** 生产 smoke 全部通过且无数据泄露/权限越界;否则立即 NO-GO 或回滚。
## 五、第一轮执行范围
收到“开始修复”后,只执行 Phase 01:
1. 纠正文档状态与共同基线;
2. 建立三端可重复检查命令;
3. 明确 Git/版本基线;
4. 输出 Phase 01 Completion Report;
5. 停止并等待用户确认 Phase 02。
不得借 Phase 01 提前修改首页、咨询、活动或后台业务代码。
## 六、计划自检
- 客户修订范围:品牌、首页、Banner、8 入口、本地资格、服务站、预约、咨询、辅导、课堂、反诈、多类型活动、二阶段同意、专项服务、多组织、来源和 Analytics 均已映射。
- 页面范围:U01~ U48 KEEP;U49~U64 按“已有修复/缺失新增”分别处理。
- 数据范围:V001~V027 保留,后续只向前迁移;身份、资格、咨询、预约和活动边界独立。
- 权限范围:RBAC、DataScope、Sensitive Permission、Audit 和客户端 Capability 分层明确。
- 发布范围:测试、UAT、真实内容、Secret、备份恢复、Rollback、Production Smoke 均有 Gate。
- 禁止范围:未加入微服务、独立 CMS/咨询服务、社区 Feed、支付、AI 代聊或其他 V1.1 外功能。