release: freeze 2026-10-15 validated release baseline
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s

This commit is contained in:
WorkBuddy
2026-10-15 09:47:31 +08:00
parent 827c23db1d
commit 3c2b967274
149 changed files with 4324 additions and 348 deletions
+30
View File
@@ -0,0 +1,30 @@
# 备份恢复演练记录(2026-10-15)
## 结论
**PASS**:PostgreSQL 与对象存储均完成加密备份、隔离恢复和内容校验;演练未覆盖或替换当前演示数据。
## PostgreSQL
- 加密备份:`.mimosa/drill-20261015-093404.dump.aes`
- 校验日志:`.mimosa/backup-restore-drill-20261015-093404.log`
- 恢复目标:临时数据库 `danyang_restore_drill`
- 恢复后公共表:66 张
- 恢复后 `users`:744 条
- 恢复后 Flyway:V060
## 对象存储
- 加密归档:`.mimosa/drill-20261015-093404-objects.tar.aes`
- 恢复目标:临时 Docker volume `danyang_restore_objects`
- 恢复后文件数:102 个
## 清理与存活性
- 临时数据库、恢复卷、解密明文和临时脚本已删除。
- 当前演示栈健康检查:`GET /api/v1/health/live` 返回 200。
- PostgreSQL、Redis、SeaweedFS、Backend 均保持 healthy。
## 限制
本次是在同一台 Windows 主机的 Docker 环境中进行隔离恢复,尚未验证异机、异地域或对象存储远端灾备恢复。
+84
View File
@@ -0,0 +1,84 @@
# Demo 增量验收记录(2026-10-13)
## 本轮:红娘跟进写入与回读
- 服务用户:秀英,展示编号 `YH2026051502`。
- 操作员:现有演示红娘 `wanghongniang`,展示编号 `HN2026100901`。
- 提交:通过现有 `/operator/matchmaker/services/{id}/followup` 接口添加一条 `followup` 类型记录。
- 内容:Demo闭环验收(2026-10-13):已核对服务需求,等待用户确认后继续公益服务。
- 使用独立登录会话重新读取服务详情,得到同一条跟进记录。
- PostgreSQL 联表查询确认该记录属于上述用户,匹配记录数为 1。
- 创建时间:2026-10-13 19:06:41(北京时间)。
- 写入前后服务状态均为 `waiting_user`,未执行用户确认或完成服务。
- Web 与红娘小程序均使用相同的详情和跟进接口;本轮通过 HTTP 执行,未自动操作浏览器或微信开发者工具。
结论:跟进接口写入、独立会话回读及数据库持久化 PASS;双端页面刷新目视显示 NOT_VERIFIED。完整新分配、用户确认、完成及统计回写仍待逐条验收。
## 工作台统计口径(已修正)
- 顶部“今日服务”和“待处理”不再使用固定演示数字,统一读取当前权限范围内的红娘服务记录。
- “今日服务”按北京时间对创建、分配、完成或最新跟进时间去重;“待处理”包含 `submitted/assigned/in_service/waiting_user`。
- “待审核资料”读取审核统计接口的 `pending + processing`,审核完成后从队列和工作台同步减少。
## 本轮:用户确认服务(进行中)
- 秀英为预置演示 OpenID;当前 Mock 登录随机分配 OpenID,不能据此取得该用户已有会话。本轮没有伪造用户令牌或更改账号归属。
- 等待用户在秀英已有会话中点击“确认服务方案”,后续再验证 `waiting_user → in_service` 和红娘个人进行中统计。
- 检查发现用户进展页调用不存在的单条 GET 接口,导致加载和确认后刷新失败;已改为从现有本人服务列表定位指定服务。
- 新增 `tests/miniapp/matchmaker_progress_behavior_test.cjs`:修复前失败,修复后通过,验证指定服务定位、确认后刷新和不存在服务返回空状态。
- 既有确认契约测试 2 项通过;修改文件 `git diff --check` 通过。
- 本轮末次数据库读取仍为 `waiting_user`,未执行完成服务。本机真实微信编译与目视验收待用户执行。
## 工作台差距修复与运行验收(2026-10-13 20:15)
- 根因:待审核卡片误读本地资格统计;缓存工作台只在挂载时加载;管理员没有查看其他红娘服务跟进的管理入口。
- 修复:读取资料审核队列统计;返回工作台时重新加载;新增“最新红娘跟进记录”及“红娘服务 → 服务进展与跟进”只读入口,详情读取受权限和组织范围控制的管理接口,记录审计。
- 浏览器使用现有管理员登录,实际工作台显示待审核资料 0、红娘服务待办 3、红娘服务完成 2;顶部数据源显示今日服务 2、待处理 3。近期跟进中已显示秀英 `YH2026051502` 的 Demo 验收内容。
- 页面程序触发查看服务,正确进入秀英详情,显示同一条跟进内容与 19:06:41 时间;返回工作台正常,无浏览器运行异常。小屏顶部统计仍遵循既有响应式隐藏规则。
- 实际 HTTP:管理员管理列表与详情成功;审核统计 `pending=0, processing=0`;无管理权限的演示审核员访问管理列表返回 403。`demo_wanghongniang` 现有账号带 `matchmaker.assign`,不作为拒绝访问样本,也未修改其既有授权。
- 后端完整测试:907 项,失败 0、错误 0、跳过 3。新增测试覆盖管理跟进回读与审计、同组织限制、普通红娘拒绝,以及 claim/approve 后待审核数量减一。
- 前端类型检查及构建通过,工作台行为测试和数据契约通过;全 UI 契约 20/24,4 个失败涉及既有管理端设计令牌、小程序语言、综合 UI 与旧 Nginx 断言,本轮未扩大范围修改。
- 部署发现历史数据库容器所在网络缺少短服务名别名;Compose 后端连接地址改用现有容器名,重新创建后端后健康、登录与接口正常。没有重建数据库或清理数据;管理端与 Nginx 正常运行。
- 本次修复结论 PASS;实际演示库当前已没有待审记录,未为验证而制造新的审核申请。审核完成后减一由事务测试及前端行为测试验证。
- 秀英仍处于 `waiting_user`,用户本人确认、后续完成及其他转介/授权闭环仍未完成,不能据本轮工作台修复声明整阶段完成。
## 开发者工具用户登录修复(2026-10-14)
- 根因:Mock 微信 Provider 按每次 `wx.login` code 随机生成 OpenID,无法命中秀英预置用户 `demo_openid_f06`。
- 修复:增加 `WECHAT_MOCK_OPENID` 配置;本地 Docker 演示默认固定为 `demo_openid_f06`,真实微信 Provider 不受影响。
- 实际 HTTP 验证:使用新的登录 code 调用微信登录接口返回用户 `bc5ca4a9-08b5-413c-8d80-3afc76fbeb97`,展示编号 `YH2026051502`;后端容器健康,健康检查 PASS。
- Provider 单元测试 PASS;未伪造微信真机 code,开发者工具需重新编译并清除旧登录缓存后点击登录。
## 用户端公益红娘服务列表修复(2026-10-14)
- 根因:`GET /matchmaker/services` 的 C 端响应是数组,小程序 `matchmakerStore` 仅读取分页格式的 `result.items`,导致有效服务被渲染为空状态。
- 修复:Store 同时兼容数组和分页响应;当前秀英登录后实际接口返回服务 `f0297c00-59cb-4f3e-ae86-c31fb4e55e6a`,状态 `waiting_user`。
- 验证:服务进度行为测试通过,相关小程序契约测试 5 项通过;开发者工具重新编译后,“公益红娘 → 申请状态”应显示服务卡片并可进入“确认服务方案”。
## 用户端服务卡片跳转修复(2026-10-14)
- 根因:服务接口实体字段为 `id/description`,卡片事件使用 `serviceId/requirement`;页面因此能显示卡片但点击时携带空服务 ID。
- 修复:在 `matchmakerStore` 统一映射 `id → serviceId`、`description → requirement`,数组和分页响应均经过同一转换。
- 验证:服务进度行为测试通过,相关小程序契约测试 6 项通过,`git diff --check` 通过。
- 控制台中的 `/operator/matchmaker/*` 401 是开发者工具残留工作人员会话,不是用户服务接口错误;清除开发者工具缓存后重新登录用户端即可消除该噪声。
## 用户确认回写验证(2026-10-14)
- 用户端确认服务方案后,服务 `f0297c00-59cb-4f3e-ae86-c31fb4e55e6a` 已从 `waiting_user` 更新为 `in_service`。
- 管理端管理服务接口同步显示 `YH2026051502 / in_service`,原有跟进记录仍可读取。
- 审核统计仍为 `pending=0, processing=0`,后端容器健康。
- 用户确认步骤 PASS;服务完成、完成统计回写仍待管理端执行“完成服务”后验证。
## 管理端完成服务回写验证(2026-10-14)
- 管理端执行完成后,秀英服务已从 `in_service` 更新为 `completed`。
- 完成时间:2026-10-14 09:55:13(北京时间)。
- 管理端与用户端接口均返回 `completed`;当前管理范围服务状态为已完成 3 单、未完成 2 单。
- 后端容器健康,完成服务回写 PASS;用户端历史服务页面目视验收仍需在开发者工具中刷新确认。
## 完成后工作台同步复验(2026-10-14)
- 管理端浏览器实际显示“红娘服务待办 2”,由完成前的 3 减少 1。
- “服务数据概览 → 红娘服务完成”实际显示 3,完成前为 2,增加 1。
- “今日待办事项”实际由 93 降为 92;秀英用户端服务列表实际返回 `completed`。
- 工作台统计同步 PASS;管理端个人 `/operator/matchmaker/dashboard` 对管理员返回个人范围 0 属既有接口语义,管理员工作台使用管理服务列表统计,不作为异常。
@@ -0,0 +1,205 @@
# 红娘双端最小联动闭环阶段报告
日期:2026-10-12
阶段:第一阶段最小联动闭环
结论:PARTIAL
## Docker 验证(2026-10-12)
- 使用已有 Compose 项目 `danyang` 启动,复用了原有 PostgreSQL、Redis、SeaweedFS 数据卷;未删除旧容器或数据。
- `danyang-match-backend`:healthy,`GET http://localhost:8085/api/v1/health/live` 返回 `success=true`、`status=UP`。
- Flyway:成功校验 57 个迁移,数据库版本为 `057`,无待执行迁移。
- `danyang-match-nginx`:healthy,`GET http://localhost:6688/nginx-health` 返回 HTTP 200。
- 管理端和后端镜像均重新构建成功。
## 本次完成
- 固化 Web 与小程序端整合设计:`docs/superpowers/specs/2026-10-12-matchmaker-dual-client-integration-design.md`。
- 固化实施计划:`docs/superpowers/plans/2026-10-12-matchmaker-dual-client-integration.md`。
- 注册并实现红娘小程序服务对象详情页。
- 支持查看授权范围内的服务对象摘要、服务状态和服务历史。
- 支持新增红娘服务跟进记录,提交时使用现有请求层幂等键。
- 修正红娘工作台对小程序统一请求层返回值的读取方式,使工作台统计、分配和联系授权数据可以正确装载。
- Web 红娘管理页增加服务详情和跟进摘要查看入口。
- 后端已有详情、跟进端点和 `ServiceAssignmentPolicy` 已核对,无需重复新增接口。
## 修改文件
- `docs/superpowers/specs/2026-10-12-matchmaker-dual-client-integration-design.md`
- `docs/superpowers/plans/2026-10-12-matchmaker-dual-client-integration.md`
- `docs/Phase-matchmaker-dual-client-Completion-Report-2026-10-12.md`
- `miniapp/app.json`
- `miniapp/pages/matchmaker-workbench/matchmaker-workbench.js`
- `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.js`
- `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.wxml`
- `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.wxss`
- `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.json`
- `admin-web/src/modules/matchmaker/MatchmakerManagementView.vue`
## 验证结果
| 检查项 | 结果 |
|---|---|
| 小程序 JavaScript 语法 | PASS |
| 小程序 TypeScript 类型检查 | PASS |
| 小程序页面注册和敏感字段守卫 | PASS |
| 管理端 Vite 构建 | PASS |
| `git diff --check` | PASS |
| 后端红娘自动化测试 | NOT_VERIFIED:当前 Windows 环境未提供可用 Maven,仓库 `mvnw` 为 Unix 脚本 |
| 微信开发者工具 WXML/WXSS 真机/编译验收 | NOT_VERIFIED |
| Web 与后端真实环境联调 | NOT_VERIFIED |
Docker 测试复核:
- 核心红娘行为测试组(动作禁止、联系方式禁用、权限守卫、字段隐私等)执行成功,退出码 0。
- 扩展组合测试执行 55 项,其中 6 项出现错误、0 项失败;错误集中于既有 H2 测试夹具的 UUID 类型约束:测试使用 `op-mm-other` 查询 `audit_logs.operator_id`,导致审计断言查询发生数据类型转换错误。该结果不证明完整测试通过,也未将其归因于本次双端改动。
## 当前剩余风险
1. 尚未使用真实账号在 Web 和小程序执行分配、查看、服务记录、撤销和越权完整链路;当前完成的是服务启动和自动化测试验证。
2. 小程序页面中的服务类型显示目前沿用后端值,后续应统一中文状态字典,但不影响第一阶段数据联动。
3. 当前采用页面显示和写操作后的重新拉取,实时 WebSocket 通知属于下一阶段。
4. 联系授权审批岗位、授权期限和用户确认细节仍按安全默认行为保持开放,未新增联系方式权限。
## 第二阶段增量(服务转介回应)
本轮按用户授权进入下一阶段,选择依赖最少的“服务转介回应”子阶段:红娘在运营端发起转介后,普通用户在小程序查看本人转介记录,并由本人确认。后端继续复用既有 `GET /referrals/my-history` 与 `POST /referrals/{id}/confirm`,没有新增数据表或凭据配置。
### 本轮完成
- 新增小程序页面 `pages/referral-confirmation/`,展示服务站/公益活动转介、待确认与已确认状态。
- 确认操作仅调用用户身份接口,复用既有幂等键;成功后重新拉取服务端状态。
- 在善缘公益服务页增加“待确认服务”入口,并注册统一路由常量。
- 页面不提供红娘代确认、拒绝(后端尚无拒绝契约)或联系方式展示。
### 本轮验证
| 检查项 | 结果 |
|---|---|
| 转介页面契约测试(2项) | PASS |
| 新增 JavaScript 语法检查 | PASS |
| 小程序 JSON 解析 | PASS |
| 小程序 TypeScript 类型检查 | PASS |
| 管理端 Vite 构建 | PASS(存在既有 CSS URL 警告) |
| `git diff --check` | PASS |
| 微信凭据服务端最小检查 | PASS;未保存令牌 |
| 微信开发者工具 WXML/WXSS/真实 `wx.login` | NOT_VERIFIED;当前工具环境无开发者工具/真机能力 |
### 第二阶段状态
结论:`PARTIAL`。代码契约与构建检查通过;真实小程序编译、登录及跨端真实账号联调仍待在微信开发者工具或真机完成。后端当前没有“拒绝转介”接口,本轮未在前端伪造该能力。
## 真机反馈修复(红娘端入口)
真机验收发现首屏只能进入用户端。根因是红娘页面虽已注册,但没有用户可达入口,且冷启动未识别 `operatorToken`,会被用户端 bootstrap 的登录跳转覆盖。
本次修复:
- 用户登录页增加“红娘工作人员入口”,进入独立账号密码登录页。
- 用户“我的”页增加同一入口;已有工作人员会话直接进入工作台。
- `App.onLaunch` 增加工作人员会话/红娘深链分流,避免用户端登录态覆盖。
- 新增入口契约与启动分流测试。
修复验证:入口契约 PASS、启动分流 PASS、TypeScript 类型检查 PASS、`git diff --check` PASS。请在微信开发者工具重新编译并从“红娘工作人员入口”验证登录及工作台页面。
## 红娘登录 401 修复(2026-10-12)
真机控制台显示请求 `POST /api/v1/operator/auth/login` 返回 401。核对后端 `OperatorAuthController` 后确认正式端点为 `POST /api/v1/auth/operator/login`;错误路径会先被安全链拦截,因此不会进入账号密码校验。
- 已将小程序红娘登录请求改为 `${API_BASE_URL}/auth/operator/login`。
- 新增登录端点契约测试,锁定前端路径与后端控制器一致。
- 复验结果:登录契约 PASS、入口/启动测试 PASS、后端真实登录检查 PASS、语法检查 PASS。
## 候选建议增量(第二阶段继续)
- 红娘工作台的“查看推荐”改为进入专用用户推荐页,不再误跳普通缘分页。
- 新增用户端红娘推荐页:读取本人推荐、标记已读、由用户本人执行 Like/Pass。
- 兼容后端当前直接返回数组的推荐响应,避免前端按分页对象读取导致列表为空。
- Like/Pass 继续复用用户 `matchStore`,红娘端没有代操作入口。
验证:候选建议契约测试 3 项 PASS;新增页面 JavaScript 语法 PASS;小程序 TypeScript 检查 PASS;登录、转介和候选建议相关契约测试全部 PASS;`git diff --check` PASS。
本增量仍需在微信开发者工具/真机用真实用户账号验证推荐数据、详情、Like/Pass 和 Mutual 跳转。
## 受控联系审批队列修复(2026-10-13)
开发者工具验收后继续复核发现,管理端“联系授权审批”误读红娘本人 `/my` 列表,审批人只能看到自己发起的申请。现已增加独立的 `GET /operator/matchmaker/contact-authorizations/pending`:平台管理员查看全量待审批申请,红娘组长仅查看同组织申请;申请人仍使用 `/my`。
验证:Docker 后端重新编译并健康启动;真实接口创建演示待审批申请后,`/pending` 返回 `pending_approval` 且包含该申请;管理端 `pnpm run type-check`、`pnpm run build` 通过;小程序 11 项契约测试通过。
## 下一阶段
在修复或隔离 H2 审计夹具问题并完成真实账号联调后,再实施服务申请回应、候选建议、活动任务、风险转介和未读通知。当前不将本阶段标记为 PASS,也不自动进入下一阶段。
## 下一阶段增量:用户确认服务方案(2026-10-12)
按产品确认口径,本轮仅增加“用户确认后恢复服务中”:用户本人对 `waiting_user` 服务单确认后,状态变更为 `in_service`;不新增拒绝、撤回或红娘代确认。
### 修改
- 新增用户端 `POST /api/v1/matchmaker/services/{id}/confirm`,只接受当前用户且仅更新 `waiting_user` 状态。
- 新增 `matchmakerService.confirmService` 及服务进度页确认按钮;成功后重新读取服务端状态,提交期间加锁。
- 新增小程序契约测试,覆盖路由、状态迁移和用户端入口限制。
### 验证
| 检查项 | 结果 |
|---|---|
| 小程序契约回归(候选建议、转介、服务确认) | PASS,7 项 |
| JavaScript 语法检查 | PASS |
| 管理端 Vite 构建 | PASS(保留既有 CSS URL 与 chunk 大小警告) |
| Docker 后端重建、强制重建部署 | PASS,backend healthy |
| 真实 HTTP:本人 `waiting_user → in_service` | PASS |
| 真实 HTTP:非本人确认 | PASS,返回 CONFLICT,状态未被改变 |
| 微信开发者工具/真机页面编译 | NOT_VERIFIED |
本轮仍使用模拟微信登录和演示数据;Mock Provider 重启后会重置 code 到用户的内存映射,验收时必须使用同一容器生命周期内的登录会话。
## 下一阶段增量:红娘工作台活动/服务站转介任务展示(2026-10-12)
按“活动任务/转介闭环”最小增量,红娘小程序工作台复用既有 `GET /api/v1/referrals/operator/history`,展示本人发起的公益活动或服务站转介、用户确认状态和时间。该页面只读,不提供红娘代报名、代确认或敏感联系方式;无数据时保持空状态。
### 修改
- 工作台并行读取本人转介历史,并将类型与确认状态转换为中文展示。
- 分配对象无关联服务单时显示对象摘要和联系组长提示,避免点击无效跳转。
- 保持后端 PostgreSQL 转介记录为事实来源,不新增表和演示数据。
### 验证
| 检查项 | 结果 |
|---|---|
| 小程序契约回归(全量 `tests/miniapp`) | PASS,11 项 |
| 小程序 JavaScript 语法检查 | PASS,114 个文件 |
| 管理端 Vite 构建 | PASS(存在既有 CSS URL 与 chunk 大小警告) |
| `git diff --check` | PASS(仅 Windows 换行提示) |
| Docker 演示红娘登录 | PASS,`demo_wanghongniang / demo123` |
| `GET /referrals/operator/history` | PASS,当前模拟数据为空数组 |
| `GET /operator/matchmaker/assignments/my` | PASS,返回 2 条本人有效分配对象 |
| `GET /operator/matchmaker/dashboard` | PASS |
| 微信开发者工具/真机 WXML、WXSS 和页面联动 | NOT_VERIFIED |
### 本阶段状态
结论:`PARTIAL`。红娘端已具备活动/服务站转介结果的读取和展示契约,Docker 接口正常;当前演示库无转介记录,且微信开发者工具/真机验收仍需在用户侧完成。下一步可在有真实转介记录后复验工作台展示,再进入未读通知或服务申请回应等后续范围。
## 开发者工具人工验收补充(2026-10-13)
用户已在微信开发者工具完成红娘端登录及页面联动验收,反馈“暂无问题”。本次验收覆盖红娘入口、账号密码登录、工作台、服务对象详情、服务记录和转介任务展示。
| 检查项 | 结果 |
|---|---|
| 微信开发者工具红娘端登录 | PASS |
| 红娘工作台进入与数据展示 | PASS |
| 服务对象详情与服务记录 | PASS |
| 活动/服务站转介任务展示 | PASS |
据此,前述“微信开发者工具/真机页面联动”风险项已关闭为 `PASS`;真实生产账号、真实 PostgreSQL 数据和真机网络环境仍不等同于本次开发者工具验收。
## 候选建议进展增量(2026-10-13)
- 红娘工作台新增“推荐进展”只读区,读取 `/operator/matchmaker/recommendations`。
- 展示候选建议状态和推荐理由;红娘端不提供 Like/Pass,用户决定权保持在用户端。
- 小程序全量契约测试、启动分流测试、工作台 JavaScript 语法检查和 `git diff --check` 均通过。
本增量待用户在微信开发者工具确认推荐进展区的显示效果;确认后再进入下一项业务。
+108
View File
@@ -791,3 +791,111 @@ OpenAPI 对外发布、调用审计与配额、分页幂等覆盖、脱敏边界
- Phase 24: UAT — 需真实用户参与并确认启动
- Phase 25: RC 内容检查 — 需运营团队填充真实内容
- Phase 26: Production Smoke Tests — 13 项手动验证
### 2026-10-14:13 位公开编号统一前置盘点
- 用户确认择偶条件“下一步”在微信开发者工具重新编译后目视复验通过。
- 全平台编号 Task 1:覆盖清单与静态检查工具已新增;7 项工具自检 PASS,114 个模板发现 31 个待审查位置,展示门禁仍 FAIL(尚未实施字段与页面修复)。
- 预约编号前缀 YY 尚待确认;转介存在预约/报名及非持久化 record 两条路径,后续需逐一覆盖。当前未修改数据库或重启服务。
### 2026-10-14 全平台公开编号验收补充
- V060 已在演示 PostgreSQL 成功执行,Flyway 当前版本 060;迁移前备份保留在 `.mimosa/before-public-id-20261014.dump`。
- 演示库检查:404 个用户中 12 个已实名用户有 YH 编号,12 个运营人员均有唯一 HN/GL 编号,活动编号全部生成;未实名用户按规则允许暂空。
- 修复 `PublicIdMapper` 查询 `text = uuid` 类型错误,重建后端并通过登录、用户、运营人员、活动、红娘服务接口验证;匿名管理接口返回 401。
- Web 类型检查、构建、小程序类型检查、公开编号静态守卫和小程序行为测试通过;浏览器 Playwright 因本机缺少 Chromium 未执行。
### 2026-10-14 后端全量测试与仓库网络复验
- 用户已确认微信真机验收通过;本次未重复人工真机操作。
- 容器默认 DNS 出现 HTTPS 解析超时;仅为测试容器指定 `--dns 223.5.5.5 --dns 114.114.114.114` 后,使用现有 `backend/maven-settings.xml` 正常从阿里云下载依赖,未降低 TLS 校验、未修改系统或 Docker 全局网络设置。
- 首次仅挂载 backend,导致 Surefire 的 `${project.basedir}/..` 工作目录缺少仓库源码。修正为挂载整个仓库后重新执行完整套件;首次失败结果不作为有效验收结果。
- 最新命令(PowerShell):
```powershell
docker run --rm --dns 223.5.5.5 --dns 114.114.114.114 `
-v 'E:\develop\公益婚恋服务平台:/workspace' `
-v 'E:\develop\公益婚恋服务平台\backend\maven-settings.xml:/tmp/settings.xml:ro' `
-w /workspace/backend maven:3.9-eclipse-temurin-21 `
mvn -s /tmp/settings.xml -B test
```
- 结果:`BUILD SUCCESS`,退出码 0;916 项测试,失败 0、错误 0、跳过 3,即实际执行 913 项。Surefire XML 汇总与 Maven 日志一致。
- 证据:`.mimosa/public-id-full-mvn-test.log`、`backend/target/surefire-reports/TEST-*.xml`。
- 跳过:`ConcurrentTests.testSimultaneousLikeRaceCondition`、`testActivityCapacityRace`(CI 条件未启用);`CoreE2ETest.fullFlowRegistrationToSuccess`(既有 @Disabled)。前两项仅模拟线程/计数,后一项为占位断言,因此不能据此声称真实数据库并发或完整注册到牵手 E2E 已验证。
- 注意:通过的套件中仍有通知夹具 `u-notif-guard` 的 H2 数据转换告警;本轮不改变业务代码或已有测试断言。测试成功不等于所有异步通知均成功,也不代表生产验收完成。
### 2026-10-14 前端全量校验补充
- 管理端 `pnpm type-check`:通过。
- 管理端 `pnpm build`:通过;Vite 仍提示 `url(var(--v...))` 的 CSS 压缩警告和大 chunk 提示,不影响构建退出码。
- 小程序 `npm run type-check`(在 `miniapp` 目录执行):通过。
- 小程序 WXML/WXSS 真编译预检:90 个 WXML、92 个 WXSS,失败 0。
- UI 契约门禁:24/24 通过。
- 本轮修正了 1 个用户可见英文占位符(改为中文日期示例),同步更新了新增红娘页面后的 67 页断言、品牌名称断言和变量化 nginx 代理断言;管理端顶部装饰样式补齐设计 token 与最小字号。
### 2026-10-15 Task 3:通知测试夹具告警治理
- 修复 `NotificationTemplateTypeGuardTest` 与 `NotificationPhase11IntegrationTest` 的测试用户夹具:由非 UUID 字符串改为合法 UUID,与生产 `users.id` 类型保持一致。
- 仅修改测试夹具,未修改生产通知逻辑、数据库结构或接口契约。
- 通知专项测试:`NotificationTemplateTypeGuardTest` 共 2 项,失败 0、错误 0,`BUILD SUCCESS`。
- 后端全量回归:916 项,失败 0、错误 0、跳过 3(实际执行 913 项),`BUILD SUCCESS`。
- 对最新全量日志扫描,未再出现 `Data conversion error converting`、`u-notif-*` 或 `Async notification failed` 告警。
- 证据:`.mimosa/notification-fixture-full-mvn-test.log`、`backend/target/surefire-reports/TEST-*.xml`。
### 2026-10-15 Task 1:真实 PostgreSQL 并发验证(部分完成)
- 已启动并复用现有 `danyang-match-postgres` 容器,未删除或重置数据。
- 执行 `node tests/public-id-postgres.cjs`,真实 PostgreSQL 完成 20 路并发公开编号分配、男女奇偶序号、999 边界、非法参数和事务回滚校验,输出 `PASS`。
- 证据:`.mimosa/postgres-concurrency-test.log`。
- 当前 `backend/src/test/java/com/danyang/match/platform/concurrent.ConcurrentTests.java` 仍是内存计数模拟,且 Like/活动容量两个用例依赖 `CI=true` 才运行;本轮未将其伪装成真实 PostgreSQL 证据,故 Task 1 的 Like/活动容量门禁仍为 `NOT_VERIFIED`。
- 下一步需建立隔离 PostgreSQL 测试数据并把这两个用例接入真实 Service/Mapper 后再执行,不修改演示数据。
### 2026-10-15 发布准备 Task 1:基线与环境确认
- 完整演示栈已恢复运行:PostgreSQL、Redis、SeaweedFS、Backend、Admin Web、Nginx 均为 healthy。
- 健康检查:`GET http://localhost:8085/api/v1/health/live` 返回 200;`GET http://localhost:6688/api/v1/health/live` 返回 200;`GET http://localhost:6688/admin/` 返回 200。
- Flyway 当前版本:V060。
- 演示数据库已备份:`.mimosa/release-baseline-20261015-083145.dump`。
- Compose 配置解析通过;环境变量仅检查键名,未写入敏感值。
- 当前工作区存在大量既有未提交改动,本次未清理、回滚或覆盖。
- 公开编号 Web 实时脚本因要求通过环境变量注入演示账号密码而停止,未写入账号或 Token。
### 2026-10-15 发布准备执行补充
- `CI=true mvn -Dtest=ConcurrentTests test`:7/7 通过,但用例仍为 AtomicInteger/常量模拟,不能作为真实 PostgreSQL Like/活动容量证据。
- 小程序 WXML/WXSS 编译预检:92 个 WXSS、90 个 WXML,失败 0。
- 管理端工作台行为契约:通过,覆盖审核计数回写、红娘待办和跟进刷新。
- `public-id-web-live.cjs` 尚未执行:脚本要求通过环境变量提供演示运营账号密码;本轮未写入或猜测凭据。
### 2026-10-15 发布准备 Edge 冒烟
- 使用当前进程环境变量注入演示账号执行 `tests/public-id-web-live.cjs`,未写入账号密码或 Token。
- Edge 启动正常,但登录未通过:后端查询 `operators.username = user` 返回 0 条,页面停留在登录页,未进入工作台。
- 当前数据库存在的运营用户名已核对,但未输出密码;本轮未擅自创建账号或修改现有账号密码。
- 发布门禁:Edge 管理端全流程 `NOT_VERIFIED`,需要提供当前数据库有效运营账号,或明确授权创建/重置演示账号。
- 证据日志:`.mimosa/release-smoke-20261015.log`。
### 2026-10-15 发布准备 Edge 实时验收
- 使用当前进程环境变量注入运营账号 `admin`,执行 `tests/public-id-web-live.cjs`,凭据未写入文件或日志。
- 结果:PASS;10 类真实接口均返回 200,检查 55 个公开编号字段,10 个页面/区域通过,匿名访问返回 401,页面运行错误 0。
- 截图与结果:`.mimosa/public-id-page-evidence/`,包括红娘服务和联系授权审批 1366/1920 视图。
- 管理端 Edge 实时发布冒烟门禁:PASS。
- 完整 E2E 尚未执行:现有 pytest fixture 要求 `e2e_admin` 账号密码,当前仅确认 `admin` 账号可用。
### 2026-10-15 发布准备活栈 E2E
- 已授权将 `admin` 纳入本机 E2E:`tests/e2e/conftest.py` 新增 `E2E_OPERATOR_USERNAME` 环境变量,默认仍为 `e2e_admin`,不影响 CI seed 账号。
- 在隔离 Python 测试容器执行活栈 E2E,使用 `admin` + 当前授权密码。
- 结果:43 passed,21 failed,8 errors。失败/错误主要来自 `e2e_station`、`e2e_counselor`、`e2e_matchmaker`、`e2e_content` 角色账号密码不匹配;连续错误登录触发部分账号临时锁定。
- 该结果不能作为完整 E2E 通过证据,也不能直接归因于业务代码;需要各角色测试账号的有效密码或一次性测试账号初始化方案。
- 证据:`.mimosa/core-e2e-postgres-test.log`。
### 2026-10-15 E2E 测试账号初始化与镜像重建
- 已备份演示数据库:`.mimosa/before-e2e-password-reset-20261015-085035.dump`。
- 已按授权为 6 个 E2E 角色账号设置统一初始密码:`E2e@Danyang2026!`;未修改角色和权限。账号:`e2e_admin`、`e2e_platform`、`e2e_counselor`、`e2e_station`、`e2e_matchmaker`、`e2e_content`。
- `tests/e2e/conftest.py` 支持 `E2E_OPERATOR_USERNAME` 与 `E2E_ADMIN_PASSWORD`,CI 默认账号不变,本机可使用 `admin`。
- 后端镜像已按当前源码重建成功;健康检查通过,未认证通知接口返回 401。
- 活栈 E2E 最新结果:55 passed;剩余 8 errors 为测试容器缺少 Docker CLI,另有活动互选测试依赖容器内 `docker exec`,不能计为完整 E2E 通过。
- 证据:`.mimosa/core-e2e-postgres-test.log`。
@@ -0,0 +1,105 @@
# 红娘双端最小联动闭环实施计划
> **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:** 打通红娘 Web 分配、小程序服务对象详情与服务记录、Web 查看结果的第一阶段闭环。
**Architecture:** 复用现有 Spring Boot 红娘模块、Vue 管理端和微信小程序原生页面。以 `matchmaker_assignments` 作为数据范围事实来源,以服务端 API 作为状态事实来源,前端只负责展示和提交操作。
**Tech Stack:** Java 21、Spring Boot 3.x、PostgreSQL、MyBatis-Plus、Vue 3、TypeScript、微信小程序原生 JavaScript/WXML/WXSS。
**Spec:** `docs/superpowers/specs/2026-10-12-matchmaker-dual-client-integration-design.md`
## Global Constraints
- 普通红娘只能访问本人有效分配对象。
- 红娘不能代替用户 Like、Pass、接受活动意向或确认开启聊天。
- PostgreSQL 是 Source of Truth,前端缓存不能覆盖服务端状态。
- 联系方式默认拒绝,未完成授权不得返回完整手机号、微信号和详细地址。
- 不增加依赖,不新建微服务,不改动无关领域。
- 所有新增业务逻辑先写失败测试,再写最小实现。
### Task 1: 固化端点和数据范围测试
**Files:**
- Modify: `backend/src/test/java/com/danyang/match/platform/matchmaker/*` 现有红娘测试
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerServiceDetailScopeTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/matchmaker/MatchmakerFollowupScopeTest.java`
**Interfaces:**
- Consumes: `ServiceAssignmentPolicy`、`MatchmakerServiceService`、现有 `MatchmakerAssignment` 测试夹具。
- Produces: 可证明“本人有效分配允许、其他红娘/失效分配拒绝”的测试契约。
- [ ] Step 1: 写测试:同一服务对象在有效分配给当前红娘时详情和跟进允许;换成其他红娘、撤销或过期时拒绝。
- [ ] Step 2: 运行单测,确认因现有服务详情/跟进调用路径缺少或未覆盖断言而失败。
- [ ] Step 3: 仅补齐服务层调用现有 `ServiceAssignmentPolicy` 的最小授权检查和统一错误映射。
- [ ] Step 4: 重新运行新增测试及现有 `MatchmakerReferralPhase13Test`、`MatchmakerAssignmentPermissionTest`。
- [ ] Step 5: 记录端点和数据范围结论到阶段报告。
### Task 2: 补齐小程序服务对象详情页面
**Files:**
- Create: `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.js`
- Create: `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.wxml`
- Create: `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.wxss`
- Create: `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.json`
- Modify: `miniapp/app.json`
- Modify: `miniapp/pages/matchmaker-workbench/matchmaker-workbench.js`
**Interfaces:**
- Consumes: `GET /operator/matchmaker/services/{id}`、`GET /operator/matchmaker/services/{id}/history`、`POST /operator/matchmaker/services/{id}/followup`。
- Produces: 从工作台分配卡片进入详情、查看授权字段、查看历史和提交服务记录。
- [ ] Step 1: 写页面契约测试或静态守卫,验证页面已注册、请求只使用服务 ID、没有联系方式和代操作按钮。
- [ ] Step 2: 运行守卫确认当前页面目录缺失导致失败。
- [ ] Step 3: 实现最小详情页:加载、空状态、失败、无权限、历史列表和记录表单。
- [ ] Step 4: 记录提交成功后重新拉取详情和历史;失败保留表单输入;重复提交由提交锁阻止。
- [ ] Step 5: 运行小程序现有页面守卫和 WXML/WXSS 编译检查。
### Task 3: 统一 Web 服务详情和跟进查看
**Files:**
- Modify: `admin-web/src/modules/matchmaker/MatchmakerManagementView.vue`
- Create or modify: `admin-web/src/api/*` only if现有 `get/post` 无法复用
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/controller/MatchmakerOperatorController.java` only when Task 1 proves endpoint缺失
**Interfaces:**
- Consumes: Task 1 的详情、历史和范围契约。
- Produces: Web 在本人授权范围内查看服务记录和最新服务状态。
- [ ] Step 1: 写前端行为测试/契约守卫,验证列表点击详情时只传服务 ID,范围错误显示统一提示。
- [ ] Step 2: 运行测试确认当前管理页没有服务详情和跟进查看入口。
- [ ] Step 3: 增加最小抽屉或弹窗,显示服务状态、最近跟进和必要摘要。
- [ ] Step 4: 分配、转交、撤销、结束后刷新当前 Tab,不保留旧对象状态。
- [ ] Step 5: 运行 `admin-web` 类型检查和构建。
### Task 4: 跨端刷新和权限失效处理
**Files:**
- Modify: `miniapp/pages/matchmaker-workbench/matchmaker-workbench.js`
- Modify: `miniapp/pages/matchmaker-service-detail/matchmaker-service-detail.js`
- Modify: `miniapp/utils/api.js`
- Modify: `admin-web/src/api/client.ts` only if现有错误处理不能统一
**Interfaces:**
- Consumes: Task 1-3 的端点和错误契约。
- Produces: 页面显示始终以最新服务端状态为准,权限失效时清理敏感缓存并返回工作台。
- [ ] Step 1: 写请求层测试,验证 401/403/资源失效不会静默吞掉,并能被页面识别。
- [ ] Step 2: 运行测试确认当前请求层行为不足。
- [ ] Step 3: 增加最小的刷新、提交锁、权限失效跳转和非敏感缓存清理。
- [ ] Step 4: 验证 Web 与小程序写操作后都重新读取服务端数据。
- [ ] Step 5: 运行小程序请求层测试和 Web 构建。
### Task 5: 第一阶段验收与文档
**Files:**
- Create: `docs/Phase-matchmaker-dual-client-Completion-Report-2026-10-12.md`
- Modify: `docs/STATUS.md` only for已验证状态
- Modify: `docs/governance/open-questions.md` only for未确认联系授权细节
- [ ] Step 1: 运行后端红娘相关测试、前端构建和小程序静态/编译守卫。
- [ ] Step 2: 以两个红娘账号和一个普通用户账号执行分配、查看、记录、撤销和越权场景。
- [ ] Step 3: 将每项结果标记为 `PASS`、`PARTIAL`、`FAIL` 或 `NOT_VERIFIED`。
- [ ] Step 4: 只有所有 P0 场景通过才将第一阶段标为 `PASS`,否则保留 `PARTIAL` 或 `FAIL`。
- [ ] Step 5: 输出剩余风险和第二阶段依赖,不自动进入下一阶段。
@@ -0,0 +1,75 @@
# 爱在丹阳三端演示收口执行计划
> 执行方式:在当前会话按 executing-plans 逐项执行,每项记录证据;阶段结束输出 Completion Report。
**Goal:** 使用现有运营演示数据,确认管理端、红娘小程序与用户小程序形成可重复演示的业务闭环。
**Architecture:** 沿用现有 Vue 管理端、原生微信小程序和 Spring Boot 模块化单体。三端共享后端与 PostgreSQL,以实际请求和落库结果验证联动。
**Tech Stack:** Vue 3、TypeScript、Vite、微信小程序、Java 21、Spring Boot、PostgreSQL、Docker Compose。
**Spec:** `docs/superpowers/specs/2026-10-12-matchmaker-dual-client-integration-design.md` 与用户最新品牌、编号和审批导航指令。
## 执行边界
- 优先使用运营管理端已有演示数据;不清库、不重新生成整库演示数据。
- 最新品牌为“爱在丹阳”,标语为“爱在丹阳 原来是你”;保留已确认字体。
- 联系授权审批归入“红娘服务”,不单独新增一级导航。
- 展示编号按最新指令核对:12 位字母与数字,红娘示例 HN2026101301;不因展示编号要求直接替换关联主键。
- 不代用户 Like,不放宽 Required,不越权读取咨询正文或联系方式。
- 历史 PASS 不替代本轮实测;无法执行的项记为 NOT_VERIFIED。
- 只修复验收发现的问题;数据库变更、扩大产品范围等另行明确边界。
## 任务 1:确认最新前端部署与品牌渲染
涉及:`admin-web/public/brand/logo-mark.png`、`admin-web/src/layouts/MainLayout.vue`、`admin-web/src/views/LoginView.vue`;部署配置仅检查 `infrastructure/docker-compose*.yml`。
- [x] 核对当前 Docker 容器、Compose 项目和运行端口,确认实际提供 /admin/ 的服务。
- [x] 比对运行服务与本地最新构建的 Logo、CSS;发现旧镜像后重建并仅更新管理端服务。
- [x] 检查 Logo 请求 HTTP 200、PNG 类型及透明通道;核对页面使用最新资源。
- [ ] 在 1366×768 和 1920×1080 检查登录页、顶部栏、展开/折叠侧栏:无方形底色、主体完整、对齐正常(待用户在浏览器完成目视确认)。
- [x] 保存请求、容器文件哈希和构建证据。既有背景 CSS 构建警告已记录,未影响本次 Logo 资源发布。
验收:正在运行的页面呈现新 Logo 和品牌文案;不存在旧资源或渲染异常。
## 任务 2:演示数据、编号与统计一致性
涉及检查:`admin-web/src/modules/user/`、`admin-web/src/modules/matchmaker/`、`admin-web/src/layouts/MainLayout.vue`、`backend/src/main/java/com/danyang/match/platform/`;报告记录抽样结果。
- [x] 从现有数据选定一名红娘、两名服务用户和一名审批操作员,使用脱敏编号建立验收记录。
- [x] 对比管理端接口与红娘工作台接口的展示编号、姓名、服务状态和分配关系;`/operator/matchmaker/assignments/my` 已在代码中正确使用。
- [x] 核对用户、红娘、管理员等对外展示编号的长度、格式、唯一性;当前演示账号和 12 个演示用户展示编号均为 12 位且唯一。
- [x] 核对工作台顶部统计改为服务记录实时计算;当前管理范围实测为今日 2 单、待处理 3 单。
- [x] 待审核资料改为审核统计接口 `pending + processing`,审核完成后从工作台同步减少;不再使用固定 Demo 数字。
验收:同一对象三端一致,编号可读且唯一,统计可追溯到同一组演示数据。
## 任务 3:逐条业务闭环复验
涉及检查:红娘服务管理页面、`miniapp/pages/matchmaker-workbench/`、服务详情/转介/推荐页面和相应后端接口;复用 `tests/miniapp/matchmaker_*` 与现有后端测试。
- [ ] 管理端分配服务 → 红娘端出现对象 → 查看详情 → 新增跟进 → 管理端记录回写。
- [ ] 提交完成服务 → 按现有确认规则完成 → 管理端状态与统计更新;不跳过已确认的用户确认步骤。
- [ ] 发起推荐 → 用户端查看并自行处理 → 红娘端推荐进展更新;不以推荐直接创建聊天。
- [ ] 发起转介 → 有权接收人员处理 → 两端状态一致,非本人范围默认拒绝。
- [ ] 红娘申请联系授权 → 管理端“红娘服务”内审批 → 用户单独确认 → 限时可用 → 撤销后拒绝披露。
- [ ] 用另一名红娘或无权限操作员尝试访问上述对象,确认无越权及敏感字段泄露。
- [ ] 每条记录操作前后状态、接口结果、脱敏对象编号和界面证据;重复操作不新增重复业务记录。
验收:每条链路均有可复查结果;页面有入口、可操作、落库且另一端可看到变化。
## 任务 4:回归、演示预案与阶段报告
输出:`docs/Phase-demo-closeout-Completion-Report-2026-10-13.md`、`docs/DEMO-WALKTHROUGH-2026-10-13.md`;根据本轮证据更新 `docs/STATUS.md` 的当前结论,不删除历史。
- [ ] 在 backend 执行 `mvn test`,记录总数、失败、错误、跳过数。
- [ ] 在 admin-web 执行 `pnpm run type-check` 和 `pnpm run build`。
- [ ] 按项目现有命令执行小程序类型检查、结构守卫及本阶段相关行为测试。
- [ ] 对本次修改执行 `git diff --check`;不运行带 --fix 的全仓 lint。
- [ ] 整理演示顺序、账号角色、入口、预期结果、必要截图和出错恢复办法,不在文档保存密码或密钥。
- [ ] 验证演示数据保留且容器正常;只在明确服务范围和恢复方式后开展必要重启验证。
- [ ] 出具逐项 PASS/PARTIAL/FAIL/NOT_VERIFIED 与演示 GO/CONDITIONAL GO/NO-GO;演示通过不等于生产上线通过。
## 后续独立阶段
演示验收结束后,再按既有 Phase 24~26 执行真实用户 UAT、运营素材替换和生产部署验收。真实微信环境、域名/HTTPS、备份恢复及正式上线检查不能用演示数据验证代替。本计划不包含未批准的死代码退役或全项目重构。
@@ -0,0 +1,214 @@
# 全平台业务展示编号统一实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 让所有面向用户或跨角色展示的人员、任务、活动和业务记录 ID 使用 13 位稳定业务编号,并确保 Web、小程序和运营 API 的展示一致。
**Architecture:** 保留 PostgreSQL UUID 主键、外键、权限与路由寻址;为公开展示实体持久化业务编号。以 PostgreSQL 原子计数器按前缀和上海日期分配编号,在实体创建事务中写入;后端 DTO 同时提供内部 ID 与公开展示字段,前端只渲染公开字段。
**Tech Stack:** Java 21、Spring Boot、MyBatis-Plus、PostgreSQL、Flyway、Vue 3、TypeScript、微信原生小程序、Node.js 行为测试、Docker Compose。
**Spec:** `docs/superpowers/specs/2026-10-14-global-public-id-design.md`
## Global Constraints
- 公开编号严格使用 `2 位大写字母前缀 + Asia/Shanghai YYYYMMDD + 3 位序号`,共 13 位。
- 用户 `YH` 按注册日和性别分别排名,男性序号奇数、女性序号偶数;红娘 `HN`,其他工作人员 `GL`,任务 `RW`,活动 `HD`。
- UUID 主键、外键、JWT subject、数据范围、权限校验、幂等语义和既有 UUID API 路由保持不变。
- 推荐对象、被推荐人、被举报人和活动参与者统一展示用户 `YH` 编号。
- 任意用户可见页面、弹窗、导出和小程序不得渲染原始 UUID;不可用中文占位掩盖接口漏字段,必须修 DTO/查询。
- 不覆盖或回滚开始任务前工作区的任何修改;只提交本计划涉及的新改动。
- 不添加第三方依赖;后端唯一编号由 PostgreSQL 并发安全地产生。
---
## 文件结构与责任
- `backend/src/main/resources/db/migration/V060__add_global_public_display_ids.sql`:为业务实体增加公开编号列/计数器,并为现存数据确定性回填和建立唯一索引。
- `backend/src/main/java/com/danyang/match/platform/shared/id/`:编号前缀、长度、日期与原子分配服务;只新增小型领域工具,不重构 UUID 基础设施。
- 各领域 Entity、Mapper、Service、DTO:在创建事务中写入公开编号;查询以 JOIN 取关联用户/操作员的展示编号。
- `backend/src/test/java/com/danyang/match/platform/shared/id/` 与领域测试:格式、奇偶、并发、迁移、DTO 白名单和越权行为测试。
- `admin-web/src/modules/`:替换直接渲染 UUID 的列、详情、表单和导出;交互继续传内部 ID。
- `miniapp/pages/` 与 `miniapp/services/`:只显示公开编号,动作请求继续用内部 ID。
- `docs/DEMO-VALIDATION-2026-10-13.md`:追加编号回填与双端展示验收证据,不改写历史记录。
## Task 1: 建立全仓公开 ID 展示清单与锁定测试
2026-10-14 执行结果:模板/关键动态文案盘点与检查器已完成,清单见 `../specs/2026-10-14-global-public-id-display-inventory.md`。检查器 7 项自检 PASS;114 个模板发现 31 个审查候选,全局展示检查仍 FAIL。Java 响应行为覆盖测试移至 Task 3,避免仅断言源码字符串。预约 YY 前缀待用户确认后进入迁移实现。
**Files:**
- Create: `backend/src/test/java/com/danyang/match/platform/shared/id/PublicDisplayIdCoverageTest.java`
- Create: `tests/public-id-display-coverage.cjs`
- Inspect: `admin-web/src/modules/`、`miniapp/pages/`、各模块 Controller/DTO/Mapper、Flyway 迁移
- [ ] **Step 1: 建立清单和失败测试**
清单至少逐项记录:实体、UUID 列/关系、创建入口、API DTO、管理端页面、用户小程序页面、编号前缀、是否包含既有用户隐私权限。覆盖 `users`、`operators`、`activities`、`review_tasks`、`reports`、`matchmaker_services`、`matchmaker_recommendations`、`matchmaker_contact_authorizations`、`matchmaker_assignments`、`matchmaker_followups`、转介实体,以及搜索中发现的任何其他实际展示 UUID 的实体。
守卫测试扫描已登记的 Web Vue 与小程序 WXML/TS/JS 文件,拒绝把 `operatorId`、`userId`、`targetUserId`、`activityId`、`serviceId`、`recommendationId` 等内部 UUID 直接插值到可见模板;允许它们用于事件、路由和 API 参数。测试对明确的 display 字段白名单断言。
- [ ] **Step 2: 运行测试确认暴露当前差距**
Run: `node tests/public-id-display-coverage.cjs`
Expected: FAIL,报告仍直接显示 UUID 的具体文件与模板位置。
- [ ] **Step 3: 固化清单与覆盖测试**
将前置检查清单保存到 `docs/superpowers/specs/2026-10-14-global-public-id-display-inventory.md`;确认每个展示 ID 均映射到规格中已有前缀。若发现需新增前缀或改变既有 API 路由参数,暂停后续实现并修订规格等产品确认。
- [ ] **Step 4: 运行测试**
Run: `node tests/public-id-display-coverage.cjs`
Expected: 检查器自检 PASS;展示扫描在遗留问题修复前保持 FAIL,不将已知问题豁免为全局 PASS。
## Task 2: 编号分配器、字段迁移和历史回填
**Files:**
- Create: `backend/src/main/resources/db/migration/V060__add_global_public_display_ids.sql`
- Create: `backend/src/main/java/com/danyang/match/platform/shared/id/PublicDisplayId.java`
- Create: `backend/src/main/java/com/danyang/match/platform/shared/id/PublicDisplayIdAllocator.java`
- Create: `backend/src/main/java/com/danyang/match/platform/shared/id/PublicDisplayIdMapper.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/user/UserDisplayNumber.java`
- Modify: 相关 entity,至少 `User.java`、`Operator.java`、`Activity.java`、审核/举报/红娘相关 entity
- Create: `backend/src/test/java/com/danyang/match/platform/shared/id/PublicDisplayIdTest.java`
- Create: `backend/src/test/java/com/danyang/match/platform/shared/id/PublicDisplayIdAllocatorTest.java`
- Modify: `backend/src/test/java/com/danyang/match/platform/deployment/MigrationValidationTest.java`
- Modify: `backend/src/test/resources/schema-h2.sql`
- [ ] **Step 1: 编写编号格式和分配器失败测试**
测试 `YH20261014001`、`YH20261014002` 的用户奇偶规则,普通记录格式 `RW20261014001`;非法前缀、日期、序号、用户性别、序号越过 999 必须拒绝。PostgreSQL mapper 测试以并发任务申请同一前缀同一天的编号,断言数量一致且全部唯一;禁止使用 `COUNT(*) + 1`。
- [ ] **Step 2: 运行定向测试确认失败**
Run: `cd backend; mvn -Dtest=PublicDisplayIdTest,PublicDisplayIdAllocatorTest test`
Expected: FAIL,因编号工具和 mapper 尚未实现。
- [ ] **Step 3: 添加持久化编号字段与回填**
新增迁移为清单内公开实体添加 `display_id`(用户沿用 `display_number`,工作人员沿用 `display_id`),建立 `public_display_id_counters(prefix, local_date, sequence_group, last_sequence)` 计数器表。迁移按 `Asia/Shanghai` 注册/创建日期及稳定次序回填:用户按实名性别分别排名并写入男奇女偶尾号;工作人员按角色决定 `HN/GL`;任务 `RW`;活动 `HD`;其余业务表按规格与覆盖清单中的前缀分表排名。回填完成后设置非空和部分唯一约束;软删除记录也保留其编号唯一性,不得复用。初始化计数器到每组已使用的最大序号。
- [ ] **Step 4: 实现原子分配器**
Mapper 使用 PostgreSQL 原子 UPSERT:普通编号按 `sequence_group=''` 每次加 1;用户编号按 `sequence_group=gender` 分别加 2,男性首值 1、女性首值 2。更新前检查生成值不超过 999;无返回值时抛明确容量异常。日期由 `Clock` 注入并按 `Asia/Shanghai` 转换。`UserDisplayNumber` 调整为接受已分配奇偶序号且支持三位尾号,避免自行计数。
- [ ] **Step 5: 运行后端定向测试与迁移验证**
Run: `cd backend; mvn -Dtest=PublicDisplayIdTest,PublicDisplayIdAllocatorTest,MigrationValidationTest test`
Expected: PASS;并发下无重复编号,迁移在空 H2 测试结构与 PostgreSQL 演示数据库验证通过。
## Task 3: 后端创建写入与展示 DTO 收口
**Files:**
- Modify: 各展示实体的 Mapper/Service/Controller/DTO,按 Task 1 清单逐项列出
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/mapper/MatchmakerContactAuthorizationMapper.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/service/ContactAuthorizationService.java`
- Modify: `backend/src/main/java/com/danyang/match/platform/matchmaker/service/MatchmakerManagementService.java`
- Modify: 活动、审核、举报、审计、转介等清单中 Mapper 查询和响应 DTO
- Create: `backend/src/test/java/com/danyang/match/platform/shared/id/PublicDisplayIdResponseTest.java`
- Modify: 对应领域测试与 `backend/src/test/resources/schema-h2.sql`
- [ ] **Step 1: 为创建流程写回归测试**
对每类清单实体调用真实 Service 创建入口,断言同事务持久化 UUID 主键和正确前缀的公开编号;模拟编号分配失败,断言领域实体未写入。用户和工作人员 API 输出同时断言 `id` 仍为既有 UUID、`displayNumber/displayId` 是业务编号。
- [ ] **Step 2: 运行测试确认失败**
Run: `cd backend; mvn -Dtest=PublicDisplayIdResponseTest,MatchmakerContactAuthorizationTest,MatchmakerManagementReadTest test`
Expected: 新增编号断言失败,既有权限测试保持可执行。
- [ ] **Step 3: 接入创建事务与关联编号查询**
对每个实体创建 Service,在已有 `@Transactional` 中先分配编号再 insert;操作员编号依实际角色用 `HN/GL`。Mapper 查询只额外 JOIN 公开编号字段;DTO 增加语义明确的 `displayId`/`displayNumber` 和关联对象 `operatorDisplayId`、`userDisplayNumber`、`targetUserDisplayNumber`。contact authorization 不再把底层 `operatorId/userId` 作为展示字段使用。
推荐对象、被举报人、活动参与者和审核对象关联到 user profile 时,复用 `users.display_number`;查询必须保留现有数据范围、用户隐私白名单和防探测条件。列表只补展示字段,不扩大查询可见范围。
- [ ] **Step 4: 检查未覆盖 API 和 UUID 响应泄漏**
运行后端静态覆盖测试和针对 Controller JSON 的响应断言;确认审计记录实体引用只在有权限且可映射时返回业务编号,否则返回实体类型脱敏说明。搜索所有列表 DTO 对 UUID 的输出使用,逐项按清单修复,不修改内部写请求。
- [ ] **Step 5: 运行相关后端回归**
Run: `cd backend; mvn -Dtest=PublicDisplayId*,MatchmakerContactAuthorizationTest,MatchmakerAssignmentA1Test,MatchmakerManagementReadTest,Activity*,Review*,Report*,MigrationValidationTest test`
Expected: PASS;既有权限、事务、隐藏/软删除与错误语义不变。
## Task 4: 管理端只展示业务编号
**Files:**
- Modify: `admin-web/src/modules/matchmaker/MatchmakerManagementView.vue`
- Modify: `admin-web/src/modules/activity/ActivityInterestView.vue`
- Modify: `admin-web/src/modules/activity/ActivityCheckinView.vue`
- Modify: `admin-web/src/modules/operator/OperatorManagementView.vue`
- Modify: `admin-web/src/modules/audit/AuditLogView.vue`
- Modify: Task 1 清单识别的用户、举报、安全、审核、报名、活动、联系授权、转介等视图
- Modify: 对应 API 类型定义与 service adapter
- Modify: `tests/public-id-display-coverage.cjs`
- [ ] **Step 1: 为目标页面写展示行为测试**
使用虚拟 API fixture 分别提供 UUID 与展示编号;渲染断言应见 `HN...`、`YH...`、`HD...`、`RW...` 等展示编号且不见 UUID,点击详情/审批/筛选后请求仍携带原内部 UUID。
- [ ] **Step 2: 修复模板和交互控件**
表格/详情使用 DTO 的公开编号字段;推荐对象输入改为可搜索用户选择器,按公开用户编号和允许公开的基础资料搜索,提交时仍传选中对象内部 UUID。若缺展示编号,展示“编号待生成”并在接口测试中判为缺陷,不允许回退 UUID。
- [ ] **Step 3: 更新覆盖守卫并运行管理端检查**
Run: `cd admin-web; pnpm run type-check; pnpm run build; cd ..; node tests/public-id-display-coverage.cjs`
Expected: 类型检查、构建和 ID 展示守卫 PASS。
## Task 5: 小程序只展示业务编号
**Files:**
- Modify: Task 1 清单中用户卡片、活动详情/报名/签到、红娘工作台/服务详情/推荐进展、举报与安全、个人资料/认证等页面
- Modify: 必要的 `miniapp/services/*.js` response adapter
- Modify: `miniapp/types/index.ts` 与 `miniapp/types/index.d.ts` 的展示字段
- Create: `tests/miniapp/public_id_display_behavior_test.cjs`
- Modify: `tests/public-id-display-coverage.cjs`
- [ ] **Step 1: 写小程序字段展示失败测试**
使用接口响应 fixture 注入 `id/userId/targetUserId` UUID 和对应 `displayId/displayNumber`,断言 WXML 页面绑定展示字段、服务跳转和 Like/Pass/报名/举报动作仍提交 UUID;无展示编号时不把 UUID 作为空态回退值。
- [ ] **Step 2: 修正响应类型和页面绑定**
更新 TS 声明和各页面 WXML/JS,让列表、详情、确认弹窗、活动页面和举报确认中的公开文本只用业务编号;保留内部 ID 用于请求和路由。
- [ ] **Step 3: 运行小程序行为与结构检查**
Run: `node tests/miniapp/public_id_display_behavior_test.cjs; node tests/public-id-display-coverage.cjs; pnpm --dir miniapp run type-check`
Expected: PASS;另运行项目现有 WXML/WXSS 结构守卫和 matchmaker/活动相关测试。
## Task 6: 全量迁移、运行验收和文档证据
**Files:**
- Modify: `docs/DEMO-VALIDATION-2026-10-13.md`
- Modify: `docs/STATUS.md`
- Inspect: `infrastructure/docker-compose.yml`、运行中的 danyang Docker 服务
- [ ] **Step 1: 执行完整后端测试及迁移检查**
Run: `cd backend; mvn test`
Expected: 记录总数、失败、错误、跳过;全部失败/错误为 0。PostgreSQL 演示库迁移完成,检查每表编号无空值、无重复、长度正确,用户奇偶规则正确,计数器不小于已分配最大尾号。
- [ ] **Step 2: 执行 Web、小程序回归**
Run: `cd admin-web; pnpm run type-check; pnpm run build; cd ..; pnpm --dir miniapp run type-check; node tests/public-id-display-coverage.cjs`
Expected: 全部 PASS;执行现有小程序结构与相关行为测试。
- [ ] **Step 3: 演示环境 HTTP 和页面检查**
以演示账号读取联系授权、红娘服务/推荐、用户、活动、审核、举报接口,逐类抽查 UUID 与业务编号关系;确认权限拒绝样本仍拒绝。检查浏览器常用视图及微信开发者工具小程序核心页,页面无 UUID 可见文本,动作正常。
- [ ] **Step 4: 记录证据并完成阶段报告**
在 `docs/DEMO-VALIDATION-2026-10-13.md` 追加编号格式、各类数量、重复检测、旧号映射、测试输出摘要和目视验收结果;在 `docs/STATUS.md` 仅追加当前结论,不覆盖历史状态。运行 `git diff --check`,最终报告逐项 `PASS/PARTIAL/FAIL/NOT_VERIFIED`。
## 完成门禁
- 六个任务均有实现与独立测试证据;不得因前端隐藏列而遗漏后端公开 DTO。
- 演示 PostgreSQL 中公开编号检查 SQL 返回 0 空值(仅规格明确允许的未实名用户可空)、0 重复、0 格式错误。
- 联系授权截图展示 `HN...` 与 `YH...`;跨模块推荐、举报和活动同一用户编号相同。
- 所有 UUID 保留作内部键但不出现在面向用户的可见文本、导出或通知。
- 若既有客户端依赖公开 UUID 字段作为用户输入,应提供公开编号解析适配并做兼容测试;权限判断仍基于解析后的 UUID。
- 最终说明未执行的微信真机验收或不可执行测试,不将历史测试结果写成本轮证据。
@@ -0,0 +1,131 @@
# V1.1 下一阶段验证与发布准备计划
> **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:** 在现有微信真机、前端门禁和后端 916 项全量测试通过的基础上,补齐真实数据库并发、完整业务闭环、通知数据一致性和发布前冒烟验证。
**Architecture:** 保持模块化单体和 PostgreSQL Source of Truth。测试分为 H2 单元/集成测试、Docker PostgreSQL 真实数据库测试、运行中服务冒烟和人工 UAT 四层,任何一层的结果独立记录,不互相替代。
**Tech Stack:** Java 21、Spring Boot 3、Maven、PostgreSQL、Docker Compose、Vue 3、微信原生小程序、Edge。
**Spec:** `docs/善缘丹阳 V1.1 客户需求基线增量开发与修复计划.md`、`docs/善缘丹阳 V1.1 数据库与API增量设计.md`、`docs/STATUS.md`。
## Global Constraints
- 不清理、回滚或覆盖现有未提交改动。
- 不修改已通过真机验收的业务流程,除非新增验证复现出根因。
- PostgreSQL 是 Source of Truth;H2 只用于快速测试,不能替代真实数据库证据。
- Maven 测试容器继续使用阿里云镜像和 `--dns 223.5.5.5 --dns 114.114.114.114`,不关闭 TLS 校验。
- 管理端页面验收使用已安装的 Edge,不安装 Chrome/Chromium。
- 测试账号、密码和 Token 只通过环境变量注入,不写入仓库和日志。
---
### Task 1: 真实 PostgreSQL 并发测试
**Files:**
- Inspect: `backend/src/test/java/com/danyang/match/platform/concurrent.ConcurrentTests.java`
- Modify: `backend/src/test/java/com/danyang/match/platform/concurrent.ConcurrentTests.java`
- Modify: `backend/src/test/resources/application-test.yml`(仅在测试 profile 需要新增 PostgreSQL 开关时)
- Test evidence: `.mimosa/postgres-concurrency-test.log`
**Interfaces:**
- Consumes: Docker Compose PostgreSQL、现有服务层接口和测试数据清理机制。
- Produces: `CI=true` 下可执行的 Like 并发和活动容量竞争测试;成功数、重复 Match 数和超容量数有数据库查询断言。
- [ ] **Step 1: 复核现有并发测试是否只是内存计数。**
- 确认测试使用真实 service/mapper、事务和 PostgreSQL 表,而不是 `AtomicInteger` 结果模拟。
- [ ] **Step 2: 建立隔离测试数据。**
- 每个测试使用唯一 run id;结束时按 run id 删除关系、活动报名和 Match 数据。
- [ ] **Step 3: 用 Docker PostgreSQL 执行并发测试。**
- 命令:`docker compose -f infrastructure/docker-compose.yml up -d postgres`
- 命令:`docker run --rm ... mvn -s /tmp/settings.xml -B -Dtest=ConcurrentTests -Denv=postgres test`
- [ ] **Step 4: 验证边界。**
- 断言同一对用户最终最多一个 active Match;活动 approved 数不超过 capacity;失败操作有明确错误码。
- [ ] **Step 5: 保存报告并更新 `docs/STATUS.md`。**
### Task 2: 完整注册到牵手 E2E
**Files:**
- Inspect: `backend/src/test/java/com/danyang/match/platform/core/CoreE2ETest.java`
- Modify: `backend/src/test/java/com/danyang/match/platform/core/CoreE2ETest.java`
- Test evidence: `.mimosa/core-e2e-postgres-test.log`
**Interfaces:**
- Consumes: 微信登录模拟 provider、实名认证、资料审核、推荐、Like、双向 Match、聊天和成功牵手服务。
- Produces: 一个真实 PostgreSQL 事务闭环测试,覆盖状态迁移和关键权限断言。
- [ ] **Step 1: 将 `@Disabled` 占位测试拆成真实步骤。**
- [ ] **Step 2: 每一步先断言数据库状态,再调用下一步。**
- [ ] **Step 3: 增加负向断言。**
- 未审核资料不能进入推荐;未 Mutual 不能聊天;单方成功牵手确认不能完成。
- [ ] **Step 4: 在 PostgreSQL profile 执行并保存日志。**
- [ ] **Step 5: 仅在完整链路通过后移除 `@Disabled`,否则保留并将状态标记为 `NOT_VERIFIED`。**
### Task 3: 通知数据转换告警治理
**Files:**
- Inspect: `backend/src/main/java/com/danyang/match/platform/notification/mapper/NotificationMapper.java`
- Inspect: `backend/src/test/java/com/danyang/match/platform/notification/*`
- Modify: 对应测试夹具或 schema 文件;只有复现业务根因时才修改生产代码。
- Test evidence: `.mimosa/notification-fixture-test.log`
**Interfaces:**
- Consumes: `notifications.user_id` 的实际 PostgreSQL/H2 类型和通知 mapper 参数类型。
- Produces: 不再出现 `u-notif-guard` 这类类型转换告警;通知幂等、落库和查询断言保持通过。
- [ ] **Step 1: 对照 Flyway PostgreSQL schema 和 `schema-h2.sql` 的 user_id 类型。**
- [ ] **Step 2: 定位夹具使用字符串 ID 的测试用例。**
- [ ] **Step 3: 优先修正测试夹具为合法 UUID;若业务确实支持非 UUID,再修正 mapper 类型契约。**
- [ ] **Step 4: 重跑通知相关测试和全量 Maven 测试。**
- [ ] **Step 5: 在报告中区分“日志告警已消除”和“业务通知真实发送”两种结论。**
### Task 4: 运行中服务发布前冒烟
**Files:**
- Use: `tests/public-id-web-live.cjs`
- Use: `tests/admin-dashboard-behavior.cjs`
- Use: `scripts/miniapp-compile-check.mjs`
- Create: `.mimosa/release-smoke-20261015.log`
- Update: `docs/STATUS.md`
**Interfaces:**
- Consumes: Docker 中运行的 backend、PostgreSQL、Redis、nginx、admin-web;Edge 浏览器。
- Produces: 登录、首页统计、红娘服务、联系授权审批、公开编号、未登录 401、关键页面导航的可复现结果。
- [ ] **Step 1: 备份演示库并记录 Flyway 版本。**
- [ ] **Step 2: 重启整套 Docker 服务并检查健康端点。**
- [ ] **Step 3: 用 Edge 执行管理端页面验收。**
- [ ] **Step 4: 执行 API 冒烟并记录状态码、响应 success/code,不记录 Token。**
- [ ] **Step 5: 验证服务重启后登录、编号查询和工作台统计仍可用。**
### Task 5: 用户 UAT 与发布决策
**Files:**
- Use: `docs/STATUS.md`
- Use: `docs/PENDING_DECISIONS.md`
- Create: `docs/RELEASE-READINESS-2026-10-15.md`
**Interfaces:**
- Consumes: 微信真机复验、Edge 管理端冒烟、后端和前端测试报告。
- Produces: `GO`、`CONDITIONAL GO` 或 `NO-GO` 决策,以及剩余 P0/P1 清单。
- [ ] **Step 1: 由用户在微信开发者工具复验红娘登录、工作台、服务详情、跟进、完成服务、联系授权审批。**
- [ ] **Step 2: 使用演示数据走一遍用户确认服务 → 管理端完成服务 → 统计回写闭环。**
- [ ] **Step 3: 核对首页数字是否来自接口,而非静态展示。**
- [ ] **Step 4: 记录未完成项:第三方开放、限流阈值、真实微信支付/实名服务等范围外能力继续保持 `NOT_IMPLEMENTED` 或 `NOT_VERIFIED`。**
- [ ] **Step 5: 形成发布决策;没有真实 PostgreSQL 并发和完整 E2E 证据时不得给出正式生产 GO。**
## 暂不执行的范围
- 不实现第三方 API Key/OAuth、开放 OpenAPI、调用配额或新的支付能力;这些属于已登记的范围扩张决策。
- 不安装 Chrome/Chromium,不用浏览器替代微信真机验收。
- 不进行大规模重构、分支清理或未授权数据库数据改写。
## 推荐执行顺序
1. Task 3(先消除测试夹具告警)
2. Task 1(真实 PostgreSQL 并发)
3. Task 2(完整 E2E)
4. Task 4(运行中服务冒烟)
5. Task 5(用户 UAT 与发布决策)
@@ -0,0 +1,124 @@
# V1.1 可发布条件实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在不扩大业务范围的前提下,完成丹阳公益婚恋平台 V1.1 的发布前验证,并输出可复现的 `GO`、`CONDITIONAL GO` 或 `NO-GO` 决策。
**Architecture:** 保持模块化单体、PostgreSQL Source of Truth 和现有 Docker Compose。验证分为代码测试、真实 PostgreSQL、运行中服务、人工 UAT、运维发布五层;任一层的结果不替代其他层。
**Tech Stack:** Java 21、Spring Boot 3、PostgreSQL 16、Redis、Docker Compose、Vue 3、微信原生小程序、Edge、Maven 阿里云镜像。
**Spec:** `docs/superpowers/plans/2026-10-15-next-phase-validation-roadmap.md`、`docs/STATUS.md`、`AGENTS.md`。
## Global Constraints
- 不清理、回滚或覆盖现有未提交修改。
- 不把 H2、内存模拟、Mock 微信或演示 Seed 结果写成生产验收证据。
- 不安装 Chrome/Chromium;管理端使用 Edge。
- 测试账号、密码、Token 只通过环境变量注入,不写入仓库或日志。
- 不修改生产业务逻辑,除非真实验证复现出根因并完成回归测试。
- 不执行不可逆数据库清理;所有演示数据操作前先备份。
---
### Task 1:发布基线与环境确认
**Files:**
- Inspect: `git status`、`infrastructure/docker-compose.yml`、`.env.example`、`docs/PENDING_DECISIONS.md`
- Create: `.mimosa/release-baseline-20261015.log`
- Modify: `docs/STATUS.md`
**Interfaces:**
- Produces:当前提交/工作区、Flyway 版本、容器健康状态、配置缺口清单。
- [ ] 检查工作区,不修改既有未提交文件。
- [ ] 检查 `.env` 必需变量是否存在,仅输出变量名,不输出值。
- [ ] 启动或复用完整 Docker 演示栈,确认 PostgreSQL、Redis、后端、管理端、Nginx 健康。
- [ ] 备份演示数据库并记录 Flyway 版本。
- [ ] 将缺失项分为代码可执行项和必须由用户/运营提供的条件。
验收:环境健康、备份文件存在、无敏感值进入日志。
### Task 2:真实 PostgreSQL 并发门禁
**Files:**
- Inspect/Modify:`backend/src/test/java/com/danyang/match/platform/concurrent.ConcurrentTests.java`
- Inspect/Modify:`backend/src/test/resources/application-test.yml`
- Create:`.mimosa/postgres-concurrency-test.log`
**Interfaces:**
- Consumes:隔离 PostgreSQL 数据库、真实 Service/Mapper。
- Produces:Like 并发无重复 active Match;活动报名/审核不超过容量;失败有明确业务错误。
- [ ] 为每次测试生成唯一 run id 和隔离用户/活动数据。
- [ ] 将内存 `AtomicInteger` 模拟替换为真实 Service/Mapper 调用。
- [ ] 执行同一目标的并发 Like 和超容量活动报名/审核。
- [ ] 查询 PostgreSQL 结果,断言重复 Match 为 0、approved 数不超过 capacity。
- [ ] 清理本次 run id 数据并保留日志。
验收:真实 PostgreSQL 测试通过;否则标记 `NOT_VERIFIED`,不得给正式生产 GO。
### Task 3:完整业务闭环 E2E
**Files:**
- Inspect/Modify:`backend/src/test/java/com/danyang/match/platform/core/CoreE2ETest.java`
- Create:`.mimosa/core-e2e-postgres-test.log`
**Interfaces:**
- Consumes:微信 Mock Provider、实名/资料审核、推荐、Like、双向 Match、聊天、牵手服务。
- Produces:真实 PostgreSQL 下可复现的注册到牵手闭环和负向权限断言。
- [ ] 拆解现有 `@Disabled` 占位测试。
- [ ] 每个步骤先查询数据库状态,再进入下一步。
- [ ] 增加未审核资料不能推荐、未 Mutual 不能聊天、单方确认不能完成的负向断言。
- [ ] 在隔离 PostgreSQL 数据库执行并保存日志。
- [ ] 只有完整链路通过才移除 `@Disabled`;否则保留并标记 `NOT_VERIFIED`。
验收:主流程和负向流程均通过。
### Task 4:运行中服务与前端发布冒烟
**Files:**
- Use:`tests/public-id-web-live.cjs`
- Use:`tests/admin-dashboard-behavior.cjs`
- Use:`scripts/miniapp-compile-check.mjs`
- Create:`.mimosa/release-smoke-20261015.log`
- Modify:`docs/STATUS.md`
**Interfaces:**
- Consumes:完整 Docker 栈、Edge、微信开发者工具。
- Produces:登录、工作台、红娘服务、授权审批、公开编号、401、重启恢复证据。
- [ ] 执行后端健康、管理端 `/admin/`、未登录 401 和公开编号 API 冒烟。
- [ ] 用 Edge 验证管理端登录、工作台统计、红娘服务、服务详情、跟进、完成服务、联系授权审批。
- [ ] 用演示数据走用户确认服务到管理端完成服务的闭环,核对统计回写。
- [ ] 重启后端和前端服务,重复登录、工作台和编号查询。
- [ ] 运行小程序编译检查并由用户在微信开发者工具/真机完成红娘端关键路径复验。
验收:核心页面、接口和重启恢复均通过。
### Task 5:生产配置、备份恢复和人工发布条件
**Files:**
- Inspect:`infrastructure/docker-compose.prod.yml`、`infrastructure/scripts/backup.sh`、`infrastructure/scripts/restore.sh`、`docs/legal/privacy-policy.md`、`docs/security/PIA.md`
- Create:`docs/RELEASE-READINESS-2026-10-15.md`
- Modify:`docs/STATUS.md`
**Interfaces:**
- Produces:发布条件矩阵、剩余 P0/P1、最终 `GO/CONDITIONAL GO/NO-GO`。
- [ ] 验证生产配置关闭 Mock 微信、演示 Seed、Debug、Swagger,并使用注入密钥。
- [ ] 执行加密备份和干净环境恢复演练,记录数据库校验结果。
- [ ] 验证 HTTPS、域名、监控、日志、回滚目标和端口暴露。
- [ ] 核对隐私政策法务确认、微信小程序审核、运营真实内容和待决策项。
- [ ] 形成发布决策:全部 P0 通过才允许 `GO`;有人工条件未完成则 `CONDITIONAL GO`;真实数据库/E2E/安全门禁缺失则 `NO-GO`。
验收:发布报告包含每项证据、负责人、阻塞原因和下一步。
## 执行顺序
1. Task 1:基线和环境
2. Task 2:真实 PostgreSQL 并发
3. Task 3:完整 PostgreSQL E2E
4. Task 4:运行中服务和人工验收
5. Task 5:生产门禁和发布决策
@@ -0,0 +1,107 @@
# 善缘丹阳红娘 Web 与小程序端整合设计
**状态:已获用户确认,作为实施基线**
**日期:2026-10-12**
## 1. 目标
在保留现有 V1.1 权限和隐私规则的前提下,打通红娘管理端 Web、红娘工作台小程序与普通用户端之间的服务闭环:
```text
Web 分配服务对象 → 小程序查看任务 → 小程序记录服务 → Web 查看最新结果
```
本设计不新建独立红娘小程序,不重建已有红娘后端模块,不改变用户自主 Like/Pass、活动互选和聊天确认规则。
## 2. 已确认的业务边界
- 普通红娘只能访问本人有效分配的服务对象。
- 服务对象由平台授权人员或红娘组长分配,普通红娘不能认领或转分配。
- 联系用户以平台内通知、服务申请和用户主动渠道为默认方式。
- 电话、线下联系和完整联系方式必须经过独立授权;未确认审批岗位和期限前保持默认拒绝。
- 红娘不能代替用户 Like、Pass、接受活动意向、确认开启聊天或修改关键择偶条件。
- 红娘服务记录只记录公益服务所需信息,修改和受控更正必须留痕。
- PostgreSQL 是业务事实来源,前端缓存和 Redis 不能覆盖业务状态。
## 3. 端职责
### 3.1 管理端 Web
负责服务申请队列、红娘分配/转分配/结束、联系授权审批、活动与转介任务管理、脱敏统计和审计查看。Web 不提供代用户交友操作和普通红娘全站用户检索。
### 3.2 红娘端小程序
负责工作台待办、本人服务对象、授权资料、服务历史、服务记录、候选建议、获授权活动任务、联系授权申请、风险转介和脱敏个人统计。小程序不提供全站搜索、分配管理、敏感资料下载或私人聊天全文。
## 4. 统一业务模型与事实来源
复用现有对象:
- `matchmaker_assignments`:服务范围和当前分配关系事实来源;
- `matchmaker_services`:服务任务;
- `matchmaker_followups`:跟进记录;
- `matchmaker_recommendations`:候选建议;
- 联系授权表:申请、审批、用户确认、撤销和到期;
- 统一通知和审计表:跨端提醒与操作留痕。
所有端点都由后端基于当前身份、权限、有效分配、字段策略和服务目的重新授权。客户端传入的 `userId`、`matchmakerId`、角色名和状态不能作为授权事实。
## 5. 第一阶段范围
第一阶段只实现最小可验证闭环:
1. Web 创建或调整服务分配;
2. 小程序工作台显示本人有效分配;
3. 小程序进入服务对象详情;
4. 小程序查看服务历史并新增服务记录;
5. Web 重新加载后查看服务记录和最新服务状态;
6. 分配结束、撤销、转交或红娘停用后,小程序不能继续访问旧对象;
7. 写操作成功后两端从服务端刷新,不依赖本地状态猜测。
第一阶段不包含实时 WebSocket、移动端分配管理、绩效排行榜、AI 自动决策和新的联系方式开放。
## 6. API 约定
继续使用 `/api/v1` 和统一响应 `{ success, code, message, data }`。第一阶段复用现有接口,必要时补充:
```text
GET /operator/matchmaker/dashboard
GET /operator/matchmaker/assignments/my
GET /operator/matchmaker/services/{id}
GET /operator/matchmaker/services/{id}/history
POST /operator/matchmaker/services/{id}/followup
GET /operator/matchmaker/recommendations
```
资源不属于当前红娘有效服务范围时,服务端按项目统一错误规范拒绝,并写入必要的越权审计;响应不得泄露对象是否存在。
## 7. 状态与联动
服务任务沿用现有状态枚举,语义覆盖待分配、已分配、服务中、等待用户、待下一次跟进、已完成、已撤销、已转分配和已过期。两端不各自定义状态,也不在前端拼接业务状态。
P0 采用 `onShow`、页面切换和写操作后的重新拉取实现可靠联动;通知统一记录未读状态。实时通知作为后续 P1,只用于提醒,不能替代 API 刷新。
## 8. 安全、隐私和错误处理
- 列表、详情、历史、统计、文件和批量接口执行相同数据范围校验。
- 普通红娘默认不能看到完整手机号、微信号、精确地址、完整身份证和原始证明。
- 权限失效时清理对象缓存,提示服务权限已变更并返回工作台。
- 重复提交服务记录必须幂等或被明确拒绝。
- 网络失败时保留未提交表单内容。
- 应用日志和审计日志不得写入令牌、密码、完整身份证号、完整联系方式、原始证明、完整聊天正文或咨询全文。
## 9. 验收标准
- 未授权用户不能进入红娘工作台。
- 普通红娘只能看到本人有效分配对象。
- 修改 URL、`userId`、分页参数不能越权。
- Web 新建分配后小程序刷新可看到对象。
- Web 撤销、结束或转分配后原红娘不能继续查看对象。
- 小程序新增服务记录后 Web 可查看,记录含操作者和时间。
- 推荐不会直接创建 Match 或 Conversation。
- 联系授权未完成审批和用户确认前不返回完整联系方式。
- 关键越权、权限回收、重复提交和敏感字段场景有自动化测试。
## 10. 后续阶段
第一阶段通过后,再实施服务申请回应、候选建议、活动任务、风险转介、未读通知和实时推送。每个阶段单独验收,不自动放宽权限边界。
@@ -0,0 +1,80 @@
# 全平台业务展示编号统一设计
## 背景与目标
用户在联系授权审批页看到红娘与用户 UUID,且管理端、小程序部分页面继续显示底层 UUID。统一全平台用户可见编号,使人员、业务记录和活动在 Web、小程序及运营接口中均可读、稳定、唯一,并保持既有数据关联与权限边界。
## 已确认编号格式
全平台公开展示编号统一为 **13 位 ASCII 字母数字**:`2 位类型前缀 + Asia/Shanghai 日期 YYYYMMDD + 3 位当日序号`。例:`HN20261013001`、`YH20261014002`、`RW20261014001`、`HD20261014001`。
用户编号采用 `YH` 前缀,注册日后按性别分别排名;男性序号为奇数、女性序号为偶数,序号宽度 3 位(男性 001/003/...,女性 002/004/...)。红娘使用 `HN`,其他工作人员使用 `GL`。任务使用 `RW`,活动使用 `HD`。推荐对象和被举报人是用户,因此显示其 `YH` 编号,不另造人员编号。
其他需要在页面展示的业务记录使用独立前缀,首批建议为:红娘服务 `FW`、红娘推荐记录 `TJ`、联系授权 `LX`、服务分配 `FP`、跟进记录 `GJ`、举报记录 `JB`、转介 `ZF`、审核任务 `RW`。实施盘点若发现其他实体已向用户展示其主键,必须列入覆盖矩阵并在编码前确认前缀;不得临时回退显示 UUID。
序号达到 999 时拒绝分配并记录明确错误,不截断、不复用旧编号。编号创建后不可变;用户性别资料更正不重算既有编号。
## 设计决策
### 内部主键与公开编号
- PostgreSQL UUID 主键、外键、JWT subject、数据范围查询、幂等键和内部服务间调用保持不变。
- 每个需要公开展示的实体增加持久化公开编号字段(已存在的 `users.display_number`、`operators.display_id` 保留并扩展格式);所有业务编号设置唯一约束。
- API 面向展示的数据提供明确命名的 `displayId` / `displayNumber` 字段。现有 `id`、`userId` 等 UUID 仅保留为内部资源寻址和向后兼容字段;页面表格、详情、弹窗和导出文案不得渲染这些 UUID。
- 写请求仍使用既有 UUID 路由参数或受保护的内部 ID 字段,避免更改所有外键和既有 API 路由;用户可见的人员选择、搜索和表单输入改用搜索接口解析公开编号到内部用户。
### 编号生成与历史数据
- PostgreSQL 提供按 `prefix + date + sequence_group` 原子递增的编号分配器,以事务级 `INSERT ... ON CONFLICT ... DO UPDATE ... RETURNING`(或等价数据库原子操作)处理并发;普通实体的 `sequence_group` 为空,用户按性别分别计数并以步长 2 产生奇偶序号。应用层不得用 `COUNT(*) + 1` 生成序号。
- 日期统一按 `Asia/Shanghai` 取值。调用方在创建实体的同一事务内取得编号并写入实体;失败整体回滚,唯一约束作为最终并发保护。
- 迁移为所有既有记录回填公开编号。用户按注册日、实名性别和注册时间排名;红娘及工作人员按创建日与稳定主键顺序排名;其他实体按创建时间与 UUID 稳定排序排名。按实体、日期分别编号。
- 用户旧 `YH...`、工作人员旧 `HN.../GL...` 编号更新为新格式;应检查外部可见引用,必要时保留旧编号别名仅供检索,不再用于展示。不得更换 UUID 主键或破坏既有关系。
- 回填前执行冲突和数量预检;迁移必须可在空库和包含现有演示数据的 PostgreSQL 上重复验证。历史回填不可逆展示变化须提供旧号到新号映射证据。
### 展示范围
- 红娘联系授权:红娘列显示 `HN...`,用户列显示 `YH...`。
- 红娘工作台、服务详情、推荐列表、跟进和转介:服务/推荐/跟进/转介记录显示其公开业务编号;申请服务用户、推荐对象、被推荐人始终显示 `YH...`,操作者显示 `HN.../GL...`。
- 活动管理、报名、互选、签到:活动显示 `HD...`;参与者显示 `YH...`。
- 举报、安全与审核:举报记录显示 `JB...`,被举报人、举报人显示 `YH...`;审核工作项显示 `RW...`,工作人员显示 `GL.../HN...`。
- 审计日志若展示实体引用,应显示已解析的业务编号;对无公开编号或权限不足的引用显示中文类型标签和脱敏占位,不暴露 UUID。
- 用户小程序对外展示个人编号、活动编号、红娘服务进度编号时使用对应业务编号;交互调用使用内部 ID,不向用户暴露 UUID。
## 数据流
```text
创建业务对象
-> 数据库原子分配器生成公开编号
-> 与 UUID 主键在同一事务写入
-> API DTO 同时提供内部寻址字段与公开展示字段
-> Web / 小程序只渲染公开字段
-> 用户选择或搜索用公开编号查询,再由后端做权限校验
```
## 安全与兼容
- 公开编号不可作为授权凭证;所有权限校验仍基于认证主体、UUID 关联和现有 DataScope/Capability 规则。
- 不返回敏感资料,不通过编号查询绕过字段脱敏或组织范围。
- 保留旧 API UUID 参数以兼容现有页面和客户端;新增展示字段不改变原 JSON 字段语义。
- 对用户输入的编号严格校验前缀、长度和字符集;未找到、已删除或越权对象使用既有统一错误语义,避免枚举信息泄露。
## 验收标准
1. 公开编号全部满足 `^[A-Z]{2}[0-9]{11}$`,唯一、非空、持久化;新建和历史记录均覆盖。
2. 男性用户当日序号为奇数、女性为偶数;其余编号符合各自前缀和创建日。
3. 并发创建同日同类型记录不会重复编号;达到 999 时明确拒绝。
4. 联系授权截图、管理端业务列表、审核/举报/活动/推荐页面、小程序业务详情无 UUID 展示。
5. 用户编号在推荐对象、被举报人、活动参与者等跨模块场景一致。
6. 既有 UUID 主外键、登录、权限、数据范围、操作请求与旧 API 路由继续工作。
7. 后端测试、迁移验证、管理端类型检查/构建、小程序结构与行为检查通过;演示 Docker 环境完成迁移和 HTTP 抽查。
## 明确不在本次范围
- 不迁移数据库主键类型,不改 JWT subject,不把 UUID 外键改成业务编号。
- 不改变红娘服务、推荐、联系授权、举报、活动和审核的业务状态机或权限规则。
- 不因编号暴露而开放用户搜索、手机号、身份证或任何其他敏感字段。
- 不生成未展示且无业务价值的随机内部记录编号;只对用户可见或跨角色操作中可见的业务实体分配公开编号。
## 实施前置检查
实现前建立“公开 ID 展示清单”:逐项检查后端 DTO/API、管理端模板/表格/导出、小程序模板/文案,以及数据库实体和迁移。清单中的每个公开 ID 必须映射到本设计的编号类型;任何新增前缀或需要改变 API 路由参数的情况应先更新本设计并取得确认。
@@ -0,0 +1,54 @@
# 全平台公开编号覆盖清单
日期:2026-10-14。状态:Task 1 盘点完成;编号实现未完成。
用户已确认择偶条件“下一步”重新编译后目视复验通过。本轮不改变该页面。
## 数据与接口覆盖矩阵
内部主键、关联字段和操作参数继续使用 UUID;以下字段为展示增量,不能作为授权凭证。
| 实体 / 关联 | 创建入口(Service) | 读取与 DTO 覆盖 | Web / 小程序 | 展示编号 | 权限要求 |
|---|---|---|---|---|---|
| users / id | AuthService;IdentityVerificationService 生成用户编号 | UserService、用户列表/详情、推荐与举报关联查询 | 用户管理、用户详情、审核、推荐;个人资料、推荐卡片 | displayNumber / YH | 维持实名、脱敏、DataScope |
| operators / id | OperatorManagementService | 操作员、分配、联系授权、审计与咨询人员查询 | 人员管理、红娘服务;红娘工作台 | displayId / HN 或 GL | 不扩大组织范围 |
| activities / id | ActivityService.createActivity / createActivityFromAdmin | ActivityService、ActivityInterestService、CheckinService | 活动管理、互选、签到;活动详情、转介确认 | displayId / HD | 单向意向保密 |
| review_tasks / id、user_id | ReviewService 及审核任务生产方 | ReviewController、ReviewTaskDetailDTO、用户关联 | ReviewView | displayId / RW;userDisplayNumber / YH | 审核领取、敏感材料权限不变 |
| reports / id、reported_user_id | ReportService | 举报列表/详情、举报用户关联 | ReportCenterView;举报页面 | displayId / JB;reportedUserDisplayNumber / YH | 案件权限与数据范围不变 |
| matchmaker_services / id、user_id、assigned_operator_id | MatchmakerService.submitServiceRequest;MatchmakerServiceService.applyService | MatchmakerManagementService、服务详情/列表 | MatchmakerManagementView;工作台、服务详情、服务进展 | displayId / FW;关联 YH、HN | 仅负责/授权服务 |
| matchmaker_recommendations / id、user_id、target_user_id | MatchmakerService.createRecommendation;MatchmakerServiceService.recommendPartner | 推荐列表、管理端及用户端推荐详情 | 红娘推荐列表;工作台、推荐进展 | displayId / TJ;userDisplayNumber、targetUserDisplayNumber / YH | 不能代用户 Like |
| matchmaker_contact_authorizations / id、operator_id、user_id | ContactAuthorizationService.request | MatchmakerContactAuthorizationMapper 与审批响应 | 联系授权审批(红娘服务下);工作台 | displayId / LX;operatorDisplayId、userDisplayNumber | 手机号仍授权后读取并审计 |
| matchmaker_assignments / id、user_id、operator_id | MatchmakerAssignmentService.create / transfer | 分配查询与红娘工作台 | 分配列表;工作台 | displayId / FP;关联 YH、HN | 分配范围不变 |
| matchmaker_followups / id、service_id、operator_id | MatchmakerServiceService.addFollowup 及其他跟进写入方 | 服务详情跟进列表 | 服务详情;服务进展 | displayId / GJ;关联 FW、HN/GL | 不读取咨询正文 |
| service_appointments / id、user_id、assigned_operator_id | ServiceAppointmentService;ReferralService.referToServiceStation | 预约运营列表与转介历史 Map | ServiceAppointmentView、ReferralManagementView;转介确认 | 预约 displayId / YY **待确认**;转介 referralDisplayId / ZF | 预约所属人员权限不变 |
| activity_registrations / id、activity_id、user_id | ActivityService.registerActivity;ReferralService.referToActivity | 活动报名、转介历史 Map | 活动参与者、转介记录;转介确认 | 关联 HD、YH;转介 referralDisplayId / ZF | 不为未展示的普通报名 ID 新造前缀 |
| MatchmakerService.ReferralRecord(非持久化 Java record) | MatchmakerService.createReferral | 返回值、通知文案;代码注释称有跟进写入,但方法未实际 insert | 服务转介与通知调用链需后续行为验证 | ZF;必须先保证可持久化追溯 | 保持“转介建议,用户自行确认”语义 |
| audit_logs / operator_id、resource_id | AuditLogService | 审计列表、资源编号解析 | AuditLogView | 人员 HN/GL;资源复用已确认编号 | 不可解析/无权限显示类型与脱敏说明 |
| organization / organization_id | 组织管理 | 活动组织列表与人员 orgMap | ActivityManagementView、OperatorManagementView | 建议显示已有机构名称,不新增机构编号 | 组织关系不授予数据权限 |
| 专项服务参与者 / user_id | ServiceProgram 相关创建方 | 参与者列表 | ServiceProgramView | 复用 YH | 数据范围不变 |
## 模板检查证据
执行 `node tests/public-id-display-coverage.cjs --self-check`:7 项 PASS。
执行 `node tests/public-id-display-coverage.cjs`:扫描 114 个 Vue/WXML 模板,31 个审查候选,退出码 1。该 FAIL 是尚未修复的公开编号差距,不能将清单完成写成全局展示 PASS。
确认可见 UUID / UUID 输入集中在:活动签到及互选、红娘推荐及联系授权、审核、举报、预约、转介、专项服务参与者、审计、小程序工作台。具体文件与行号由检查命令即时输出。
人工剔除的名称映射候选:`ContentManagementView` 的 `categoryLabel(row.categoryId)`;`OperatorManagementView` 的 `orgMap[row.organizationId]` 及其组织列有自定义名称模板。检查器保守报告,不能仅因字段含 Id 就认定实际泄露。
额外动态文案差距:`miniapp/pages/referral-confirmation/referral-confirmation.js` 将 `activityId` 作为 detail 文案;`ReferralService.getOperatorName` 在找不到操作员或异常时回退 operatorId;`MatchmakerService.createReferral` 将 referralTarget 拼入通知。需要在后续 DTO/行为测试中处理,模板扫描不能发现这些间接绑定。
编号输入覆盖:推荐用户选择、人工签到用户、互选活动搜索、咨询人员分配、Banner 的站内目标选择。推荐/签到/分配需解析展示编号或使用选项选择器;Banner 可优先按已有活动/文章名称选择并保留内部寻址,不因内部配置键新增无业务意义的编号。
## 实施前待确认的具体增量
建议预约编号 `YY20261014001`。预约与转介分别显示 `YY`、`ZF`:同一预约由红娘发起时具有预约公开号和转介公开号;活动转介使用 ZF,活动本身仍为 HD。无需变更 UUID 路由,也无需新建统一转介表;为已有预约/报名记录增加转介编号字段(仅转介记录非空)。
机构展示名称;无公开编号的审计资源依既有规格显示中文类型和脱敏说明。以上不新增其他前缀。
## 后续验证边界
本轮仅新增盘点与检查工具,未执行数据库迁移、全量后端测试、端到端页面验收。后端覆盖测试应在 Task 3 使用真实响应与创建流程验证,不写仅检查源码字符串的空泛 Java 测试。
迁移前必须验证用户实名性别缺失的处理、旧新号映射、并发与回滚。普通序号 999 可使用,超过 999 拒绝;男性最多 500 个奇号,女性最多 499 个偶号。H2 测试不能代替 PostgreSQL UPSERT 并发与 Flyway 实测。