Files
danyang-match/docs/V1.1_RECOVERY_DEVELOPMENT_PLAN_2026-09-09.md
T

18 KiB
Raw Blame History

善缘丹阳 V1.1 Recovery Implementation Plan

已被取代: 本计划使用 R0~R8 恢复阶段,与客户 V1.1 增量基线不一致。当前唯一修复计划为 善缘丹阳 V1.1 客户需求基线增量开发与修复计划.md。本文件仅保留为审计历史,不再作为执行依据。

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.1 恢复为满足业务不变量、可构建、可回归、可人工验收的发布候选版本。

Architecture: 保持 Java 21 + Spring Boot 模块化单体、PostgreSQL、Redis、私有对象存储、Vue 3 管理后台和微信原生小程序。按“安全底座 → 测试底座 → 业务纵切 → 前端闭环 → UAT → RC”恢复,不引入微服务和新基础设施。

Tech Stack: Java 21、Spring Boot 3.x、MyBatis-Plus、Flyway、PostgreSQL、Vue 3、TypeScript、Vite、微信小程序原生、Docker Compose。

Spec: AGENTS.md、docs/善缘丹阳 V1.1 页面级功能清单与交互流程修订版.md、docs/善缘丹阳 V1.1 数据库与API增量设计.md、docs/superpowers/specs/2026-09-13-reference-driven-dual-client-ui-redesign-design.md、docs/善缘丹阳 V1.1 Codex-Jira 最终开发任务增量清单.md。

Global Constraints

  • 用户永久免费,禁止 VIP、会员、金币和用户付费功能。
  • Required 条件是 Hard Constraint,任何推荐路径不得自动放宽。
  • Mutual Match 后才能聊天;Block 优先级最高。
  • 活动互选必须经过双方分别确认后才创建或复用 Match/Conversation。
  • Counselor 只能访问 Assigned Service;Content Editor 零用户婚恋数据权限。
  • PostgreSQL 是 Source of Truth;前端 Store 和 Redis 不得覆盖数据库事实。
  • 首页结构与 8 个核心入口顺序固定;Banner 仅允许内部目标类型。
  • 默认简体中文、Asia/Shanghai、日期 YYYY-MM-DD、金额人民币元。
  • 每个阶段结束必须产生真实测试输出和 Completion Report,并暂停等待审核。

执行策略

推荐采用“恢复式纵向切片”:先建立不可绕过的权限与测试门禁,再按首页、咨询/预约、活动互选、内容/服务站逐条打通后端—小程序—后台—测试。不要继续按原 Phase 编号批量补文件,也不要先重做视觉稿。

估算以 1 名全栈工程师持续投入为前提,仅用于排序:恢复到可进入正式 UAT 约需 20~30 个工程日;真实内容、第三方认证、微信审核和生产证书不计入。

Phase R0:冻结错误基线并恢复可追溯性

Files:

  • Modify: docs/STATUS.md
  • Modify: docs/JIRA_BACKLOG.md
  • Create: docs/RECOVERY_ISSUE_TRACKER.md
  • Verify: .git/ 或新的正式 Git 工作区

Produces: 单一版本号、真实状态矩阵、P0/P1 缺陷清单、可审计提交历史。

  • 确认正式代码仓库位置;若当前目录是拷贝,迁回正式仓库后再修改源码。
  • 对当前目录做不可变备份或建立恢复分支,记录当前 V027 数据库版本。
  • 将 V1.1 状态改为 RECOVERY,撤销“100% 完成、可上线”的结论。
  • 把旧 Completion Report 标为“历史记录,需按恢复门禁复验”。
  • 统一 Backend、Admin、Miniapp、VERSION 和文档中的版本号为同一个 1.1.0-recovery。
  • 建立缺陷编号:安全 P0、功能 P1、体验 P2;每项写清复现步骤、影响不变量、验收测试。

Exit Gate: git status 可用;版本唯一;状态文档不存在同一模块既完成又未完成的冲突。

Phase R1:建立不可伪造的质量门禁

Files:

  • Modify: .github/workflows/ci.yml
  • Modify: backend/Dockerfile
  • Modify: admin-web/package.json
  • Modify: miniapp/package.json
  • Modify: miniapp/tsconfig.json
  • Create: pytest.ini
  • Create: tests/e2e/conftest.py
  • Replace: tests/e2e/*_test.py 中的空壳测试

Produces: 一条失败即阻断的 CI;后端、后台、小程序、迁移、E2E 均有真实门禁。

  • 先写一个 CI 自检用例,证明空 pass、未知 pytest mark 和缺失 fixture 会使流水线失败。
  • 为 E2E 建立隔离测试数据、用户令牌与操作员令牌 fixture,不再用管理员令牌代替用户。
  • 把 run_v11_tests.py 拆成可独立运行、可清理数据、每个结果都有断言的测试。
  • 将 INV-011~020 改为调用真实 Service/Controller/Database 的行为测试,删除“常量存在即不变量成立”的判定方式。
  • 后端镜像构建执行 mvn verify -B,移除 maven.test.skip=true。
  • Admin CI 顺序固定为 npm ci、npm run type-check、无修复模式 lint、npm run build。
  • Miniapp CI 执行 npm ci、npm run type-check,并校验页面注册、WXML 事件处理器和目标路径存在。
  • Migration Job 使用临时 PostgreSQL 真正执行 Flyway,不再只检查 SQL 文件非空。

Exit Gate: 全新环境可一次运行全部门禁;故意破坏任一不变量时相应测试会失败。

Phase R2:修复认证、RBAC、DataScope 与敏感数据边界

Files:

  • Modify: backend/src/main/java/com/danyang/match/platform/shared/filter/JwtAuthFilter.java
  • Replace: backend/src/main/java/com/danyang/match/platform/shared/filter/PermissionFilter.java
  • Modify: backend/src/main/java/com/danyang/match/platform/shared/config/SecurityConfig.java
  • Modify: backend/src/main/java/com/danyang/match/platform/counseling/controller/CounselingController.java
  • Modify: backend/src/main/java/com/danyang/match/platform/counseling/service/CounselingServiceApp.java
  • Modify: backend/src/main/java/com/danyang/match/platform/service_appointment/controller/ServiceAppointmentController.java
  • Modify: backend/src/main/java/com/danyang/match/platform/service_appointment/service/ServiceAppointmentService.java
  • Test: backend/src/test/java/com/danyang/match/platform/invariants/PermissionMatrixTest.java
  • Test: tests/e2e/counseling_permission_test.py
  • Test: tests/e2e/service_station_permission_test.py
  • Test: tests/e2e/organization_isolation_test.py

Produces: 用户主体与操作员主体分离;接口级 Permission + DataScope;敏感字段按角色裁剪。

  • 写失败测试:用户令牌调用后台咨询接口返回 403。
  • 写失败测试:服务站人员访问全局用户、咨询队列、全局统计返回 403。
  • 写失败测试:Counselor A 访问 Counselor B 的咨询详情、跟进和状态变更返回 403。
  • 写失败测试:Matchmaker 与普通管理员无法读取咨询正文和 followup 内容。
  • 写失败测试:用户 A 读取用户 B 的预约详情返回 404 或 403,且不泄露记录存在性。
  • 将 operator API 统一迁到 /api/v1/operator/...,为每组接口映射明确权限码。
  • 控制器只从已验证 Principal 取主体,不再各自解析 Authorization Header。
  • 只有具备代办权限的操作员可指定 userId,普通用户请求体中的 userId 被拒绝。
  • 在 Service 层实现 Assigned Counselor、Service Station、Organization DataScope,避免只依赖路由过滤。
  • 对咨询 DTO 做角色视图裁剪;日志仅记录咨询 ID、风险级别和脱敏标识。

Exit Gate: INV-011、012、013、018、019、020 行为测试全部通过;无低权限角色能通过直接 API 绕过前端菜单。

Phase R3:首页聚合与 Capability 单一事实源

Files:

  • Create: backend/src/main/java/com/danyang/match/platform/capability/service/CapabilityService.java
  • Modify: backend/src/main/java/com/danyang/match/platform/home/service/HomeApplicationService.java
  • Modify: backend/src/main/java/com/danyang/match/platform/home/dto/HomeDTO.java
  • Modify: backend/src/main/java/com/danyang/match/platform/banner/service/HomeBannerService.java
  • Test: backend/src/test/java/com/danyang/match/platform/home/HomeApplicationServiceTest.java
  • Test: tests/e2e/home_v11_test.py

Produces: GET /api/v1/home 从真实模块聚合数据,入口顺序固定,所有入口由服务端能力控制。

  • 写失败测试,精确断言 8 个入口 code、顺序、目标页面和 enabled 状态。
  • 写失败测试,Banner 外链目标、过期 Banner、受众不匹配 Banner 均不会返回。
  • 写失败测试,未实名、审核中、暂停寻找、成功牵手五类首页状态分别符合文档。
  • CapabilityService 统一读取账户、实名、资料审核、本地资格、关系状态和 Feature Flag。
  • 用真实身份记录替换 verified=true,用推荐服务替换空列表。
  • 从 service_locations、content_articles 读取服务站和婚恋课堂内容,移除硬编码业务对象。
  • 修正 8 个入口和全部 CTA 到真实、已注册的内部页面。
  • 严格输出固定首页顺序:品牌/状态由前端壳展示,数据区依次为 Banner、8 入口、推荐、公益服务、活动、服务站、婚恋课堂、安全提醒。

Exit Gate: 首页 E2E 覆盖 5 种用户状态、Banner 规则、精确入口顺序和所有目标页面;返回数据无阶段占位值。

Phase R4:活动互选二阶段确认闭环

Files:

  • Modify: backend/src/main/java/com/danyang/match/platform/activity_mutual/service/ActivityMutualConsentService.java
  • Modify: backend/src/main/java/com/danyang/match/platform/activity_mutual/controller/ActivityMutualConsentController.java
  • Modify: backend/src/main/java/com/danyang/match/platform/relationship/service/RelationshipService.java
  • Modify: backend/src/main/resources/db/migration/V024__add_activity_mutual_connection_consents.sql 的约束策略通过新增迁移实现,禁止改写已应用迁移
  • Create: backend/src/main/resources/db/migration/V028__harden_activity_mutual_consents.sql
  • Test: tests/e2e/activity_mutual_consent_test.py
  • Test: backend/src/test/java/com/danyang/match/platform/activity_mutual/ActivityMutualConsentServiceTest.java

Produces: Mutual Interest → 双方分别确认 → 原子创建/复用 Match → 创建/复用 Conversation。

  • 写失败测试:单向 Interest 对另一方不可见。
  • 写失败测试:Mutual Interest 和单方 Confirm 都不会创建 Match/Conversation。
  • 写失败测试:双方并发 Confirm 只生成一个结果。
  • 写失败测试:已有 active Match 时复用;曾 Unmatch 时创建新 Match Episode。
  • 在单事务内锁定 consent pair、重读双方状态、处理幂等键、创建或复用 Match/Conversation。
  • 增加规范化 pair 唯一约束和重复请求冲突处理。
  • 返回前端所需的 bothConfirmed、matchId、conversationId、reusedExistingMatch。

Exit Gate: INV-014、015 及“已有 Match 复用/曾 Unmatch 新建”全部在并发测试中通过。

Phase R5:小程序改为单一 TypeScript 运行源并补齐页面闭环

Files:

  • Modify: project.config.json
  • Modify: miniapp/project.config.json
  • Modify: miniapp/tsconfig.json
  • Replace: miniapp/pages/index/index.ts
  • Remove after verified migration: 与 13 个 TypeScript 页面重复且漂移的手写 .js
  • Create/complete: miniapp/pages/service-center/**
  • Create/complete: miniapp/pages/service-station/**
  • Create/complete: miniapp/pages/service-appointment/**
  • Create/complete: miniapp/pages/my-appointments/**
  • Create/complete: miniapp/pages/classroom/**
  • Create/complete: miniapp/pages/article-detail/**
  • Create/complete: miniapp/pages/anti-fraud/**
  • Create/complete: miniapp/pages/service-program/**
  • Create/complete: miniapp/pages/service-history/**
  • Modify: miniapp/app.json

Produces: 一套可编译的 TypeScript 源码;U49~U64 与活动互选页可真实导航和操作。

  • 先建立页面注册、handler 存在、内部目标可达的静态失败测试。
  • 明确 .ts 为唯一手写源;生成 .js 不纳入人工维护,CI 检测同名双轨漂移。
  • 修复请求 Promise 类型、页面级模块作用域、全局类型和 uploadBase 定义。
  • 重建首页,让 WXML、TS 和 /home DTO 字段完全一致,并补上婚恋课堂区块。
  • 接通 8 个核心入口与 Banner 内部跳转,不再借用本地资格页承载无关业务。
  • 补齐服务预约、我的预约、内容列表/详情、反诈、专项服务、服务记录页面。
  • 活动互选页覆盖“结果、本人确认、等待对方、双方确认、已有聊天、拒绝/超时”状态。
  • 所有提交、取消、拉黑、退出等重要操作提供进度、结果与二次确认。

Exit Gate: npm run type-check 无错误;微信开发者工具编译无错误;首页固定顺序和 U49~U64 核心流程完成真机/模拟器截图验收。

Phase R6:管理后台按角色形成可运营工作台

Files:

  • Modify: admin-web/src/router/index.ts
  • Modify: admin-web/src/layouts/MainLayout.vue
  • Replace: admin-web/src/modules/counseling/CounselingView.vue
  • Complete: admin-web/src/modules/banner/BannerManagementView.vue
  • Complete: admin-web/src/modules/content/ContentManagementView.vue
  • Complete: admin-web/src/modules/service-station/ServiceStationView.vue
  • Complete: admin-web/src/modules/service-appointment/ServiceAppointmentView.vue
  • Complete: admin-web/src/modules/service-program/ServiceProgramView.vue
  • Create: admin-web/src/modules/counseling/CounselingDetailView.vue
  • Test: admin-web/src/**/*.spec.ts

Produces: Platform Admin、Counseling Manager、Counselor、Content Editor、Service Station Operator 各自只看到可执行任务。

  • 先写路由与权限测试,证明菜单可见性、直接 URL 访问和 API 403 三层一致。
  • 注册 /counseling 路由,修复语法和接口路径,拆分队列、我的咨询、详情/跟进职责。
  • 将长侧栏按“用户与审核、婚恋服务、公益服务、内容运营、系统治理”分组。
  • 工作台优先展示待办、超时、风险和今日服务,不以全零累计数字作为主视觉。
  • Banner 编辑器校验内部目标类型、排期、受众和预览。
  • 服务站人员只能处理本站预约;Content Editor 页面完全不请求用户婚恋数据。
  • 为列表补齐加载、空状态、错误恢复、分页、筛选和操作结果反馈。

Exit Gate: type-check、lint、unit test、build 全通过;五种角色逐一完成登录—待办—详情—处理—审计留痕流程。

Phase R7:业务纵切回归与隐私安全复验

Files:

  • Modify: tests/invariant_integration_test.py
  • Modify: tests/uat/UAT-Test-Cases.md
  • Modify: tests/README.md
  • Create: docs/security/V1.1_SECURITY_RETEST.md
  • Create: docs/Phase-R7-Completion-Report.md

Produces: V1.0 核心不变量 + V1.1 新增不变量的完整回归证据。

  • 回归 Auth、Profile、Review、Required、Match、Mutual、Block、Chat、RBAC。
  • 执行 INV-001~020 的 API + DB 双层断言。
  • 对本地资格佐证、咨询附件、聊天图片执行对象存储私有访问和过期 URL 测试。
  • 执行 IDOR、水平越权、垂直越权、组织隔离、日志脱敏测试。
  • 对注销流程验证预约取消、咨询生命周期、专项项目退出和本地资格失效。
  • 生成覆盖实际命令、版本、通过数、失败数和已知限制的完成报告。

Exit Gate: 无 P0/P1 缺陷;20 条不变量全部有失败前例和通过证据;安全复验无发布阻断项。

Phase R8:正式 UAT、内容验收与发布候选

Files:

  • Modify: docs/Go-NoGo-Checklist.md
  • Modify: docs/STATUS.md
  • Modify: docs/PENDING_DECISIONS.md
  • Create: docs/Phase-R8-UAT-Completion-Report.md
  • Create: releases/v1.1.0-RC.1/RELEASE_NOTES.md
  • Create: releases/v1.1.0-RC.1/FILE_MANIFEST.md

Produces: 有真实运营人员和测试用户签字的 RC,而不是 API 可返回 200 的演示版本。

  • 使用独立 UAT 数据库和对象存储,禁止复用开发脏数据。
  • 完成服务站扫码→预约→到场、咨询申请→完成、婚前辅导、活动互选→双方确认→聊天四条端到端场景。
  • 按角色确认无需 Excel、个人微信和纸质临时台账即可留痕。
  • 完成真实 Banner、服务站信息、咨询介绍、婚前辅导、反诈、课堂、关于与主办信息审核。
  • 执行移动端、常见 Windows 浏览器、弱网、空数据、错误恢复和无障碍抽查。
  • 生产 Smoke 覆盖首页、入口、服务站、咨询、内容、活动互选、Block 与权限矩阵。
  • 只有 Go/No-Go 清单全部通过后,才将状态改为 1.1.0-RC.1。

Exit Gate: UAT 签字、真实内容审核、安全复验、备份恢复演练和生产 Smoke 全部有证据。

每阶段统一验收命令

# Backend(本机需 JDK 21 + Maven)
Set-Location backend
mvn verify -B

# Admin Web
Set-Location ..\admin-web
npm ci
npm run type-check
npm run build

# Miniapp
Set-Location ..\miniapp
npm ci
npm run type-check

# E2E
Set-Location ..
python -m pytest -q tests/e2e
# Backend
cd backend && mvn verify -B

# Admin Web
cd ../admin-web && npm ci && npm run type-check && npm run build

# Miniapp
cd ../miniapp && npm ci && npm run type-check

# E2E
cd .. && python3 -m pytest -q tests/e2e

计划自检

  • Spec coverage:覆盖首页、8 入口、本地资格、咨询、婚前辅导、多类型活动互选、服务站/预约、内容、专项服务、Analytics、账户生命周期、权限与发布。
  • Placeholder scan:计划没有以空任务代替实现;每阶段均有明确文件、失败测试、实现动作和 Exit Gate。
  • Type consistency:统一以服务端 Principal、Permission + DataScope、CapabilityService 和 /api/v1/operator/** 作为跨模块接口约束。
  • Scope control:不引入微服务、Kubernetes、Kafka、新 CMS Server 或新咨询 Server。

执行顺序

严格执行 R0 → R1 → R2 → R3 → R4 → R5 → R6 → R7 → R8。R2 未通过前不得处理视觉美化;R7 未通过前不得进入正式 UAT;R8 未通过前不得恢复“可上线”表述。