Files
danyang-match/docs/PHASE26-GO-LIVE-CHECKLIST.md
T
WorkBuddy 44f75acebe fix(uat): 闭环 UAT 4 项硬阻塞(推荐恒空/保存即失败/越权端点/文档不一致)+ 小程序字段契约
UAT 走查(docs/UAT-WALKTHROUGH-2026-09-23.md)发现 4 项硬阻塞,本次闭环其中 3 项
(#2 微信登录、#5 照片直传不在本轮范围),并顺带修掉走查中新发现的跨端字段契约缺陷。

后端
- #6 推荐恒空:新增 MatchScoringService 作为唯一评分事实源(复用 UserPreference 既有
  10 维权重,零新造常量);RecommendationEngineService.calculateScore/generateReasons 由
  桩(return 50.0)改为委托;MatchEligibilityService 3 处桩全部去雷。此前 50 < 阈值 60
  → GET /recommendations 恒返回空数组。
- #4 保存即失败:updateProfile / updateBasicProfile / savePreference 改为
  「无则插入、有则更新」。注意 UserPreference 实体 @TableId=id 与库主键 user_id 不一致
  (V037 后补的可空列),故按 user_id 定位更新而非 updateById(后者会静默不更新)。
  gender / birth_date 为 NOT NULL 且向导不采集,缺失时从已通过实名认证的 user_identities
  补齐,仍缺则抛 400 业务拒绝,不再让 DataIntegrityViolationException 渲染成 500。
  GET /me/profile 的 preferences 补回 5 个此前未返回字段(regionPriority / maritalPriority /
  minEducationCode / educationPriority / childrenPriority)。
- #8 越权端点:POST /activities/{id}/interests/confirm 不再直调「建 Match 原语」
  RelationshipService.confirmActivityInterest,改为与 /activities/{id}/mutual/* 同一条
  二阶段同意链路(createMutualConsent + confirmConnection),单方调用不再可能建 Match
  (INV-014 / INV-015)。
- #10 文档不一致:MatchmakerController 类注释更正(operator 端点实际在 /operator/matchmaker)。
- 存量 500 家族:RuntimeExceptionThrowGuardTest 的正则只认 throw new RuntimeException(,
  而 17 处裸抛写作 orElseThrow(() -> new RuntimeException(...)),整体绕过守卫(CI 全绿却
  仍有 500 家族缺陷)→ 17 处全量改为 GlobalExceptionHandler.BusinessException;
  守卫扩为「整段代码 + 该形态」,并加自检断言防止守卫退化成恒真空断言。

小程序(跨端字段名 / 取值契约)
- 字段名对齐后端规范名:hasChildren→childrenStatus、occupationCategory→occupationCode、
  workRegion→workRegionCode、ageMin/ageImportance→minAge/agePriority、
  educationAccepted/maritalStatusAccepted→minEducationCode/maritalStatuses。
  此前字段名对不上,后端读不到 → 字段被静默丢弃。
- 取值修 4 类违反 DB CHECK(写入直接 500)的项:has→yes;high_school→senior_high、
  phd→doctor(chk_profile_edu);occasional→sometimes(chk_profile_smoking/drinking)。
- 预填改读服务端真实字段:此前读 profile.hasChildren / occupationCategory / workRegion,
  而服务端返回的是 childrenStatus / occupationCode / workRegionCode → 表单永远回填不上。
- profile-confirm 完成度改为直接采用服务端 profileCompletion(AGENTS 第 9 条:DB 是
  Source of Truth),废弃原先 22 条「读服务端不存在字段」的本地猜测式断言。
- 择偶条件页新增「展示形态 ↔ 服务端规范形态」适配器(toApiPayload / fromApiPayload)。

测试与门禁
- 新增 MatchScoringServiceTest、RecommendationEngineServiceBehaviorTest、
  ProfileSaveUpsertBehaviorTest、ActivityInterestConfirmConsentBehaviorTest 与
  ui-tests/miniapp-profile-contracts.mjs(桩 stores,真跑三个页面的事件处理与 onNext,
  断言提交负载用规范字段名与枚举码)。
- MIN_GUARDS 21→23(并修正上一轮漏改:该值当时仍为 21,与守卫数不符,使「数量下限」
  保护形同虚设)。
- 负向注入实测:把 #6 评分改回桩 50.0、#4 改回恒 insert、#8 改回绕开二阶段、并注入
  orElseThrow 形态裸异常 → 4 个守卫全部变红(含精确定位到 RecommendationEngineService.java:282)。
- 后端:795 tests / 0 failures / 3 skipped;UI 守卫 23/23;语种审计 0 命中;tsc 通过;
  wcc/wcsc 真编译 88 WXSS + 86 WXML / 0 失败。

仍未修(需产品/数据决策,见报告 8.3)
- regionScope 需 GB/T 2260 单值区划码,而小程序选项含「镇江其他辖区」这类非单值项 →
  不臆造区划码(该约束默认 preferred 软约束,不误过滤);
- occupationPreference 后端无对应列;settlementPreference 后端无取值字典。
2026-09-23 14:33:43 +08:00

80 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 26 — 上线前 13 项手动验证清单
> 用途:V1.1 进入 **UAT / 生产上线** 前,由 **运营 / 产品 / 运维** 人工逐项确认的清单。
> 本清单只覆盖「上线前必须肉眼或真机确认」的项;自动化回归已由 CI 覆盖
> (后端 `mvn verify` 757 绿 / E2E 65 passed / UI 契约 22/22 / 真编译 WXSS 88+WXML 86)。
>
> 判据纪律(沿用项目一贯要求):**断言 ≠ 证据**。`✅ 已完成` 类文档声明一律以
> 「当前代码 + 测试 + 人工验收」为准。本清单每项都给出 **可执行的验证方式**,
> 不靠口头确认。
>
> 关联决策:`docs/PENDING_DECISIONS.md`(13 项产品待确认)、`docs/governance/open-questions.md`。
> 冒烟脚本:`infrastructure/scripts/smoke-test.sh`(自动化子集)。
> ⛔ **2026-09-23 走查结论:本清单第 2/4/5/6 项为硬阻塞,当前不具备上线条件。**
> 详见 `docs/UAT-WALKTHROUGH-2026-09-23.md`(含源码证据 + 本地栈运行时实测 + 容器异常栈)。
> 摘要:微信登录无真实 `code2session`(仅 Mock);资料/择偶条件**保存即失败**(409/500);
> 照片直传后**不落库**、不可见;推荐列表**恒空**(评分函数为桩,恒 50 < 阈值 60)。
> 以上均逃过 757 后端测试 + 65 E2E + 22 UI 守卫(测试盲区)。**修复并复测前不得按本清单放行。**
---
## 验证总表
| # | 验证项 | 验证方式 | 通过标准 | 负责方 | 关联决策 / 配置 |
|---|--------|----------|----------|--------|------------------|
| 1 | 部署栈存活 | `bash infrastructure/scripts/smoke-test.sh` | live/ready/version 全 200;postgres/redis/seaweedfs 就绪 | 运维 | — |
| 2 | 微信小程序登录链路 | 真机「善缘丹阳」小程序微信授权登录 | 返回 `accessToken`+`refreshToken`,进入首页;token 过期触发重新登录 | 产品+运营 | 微信 appid/secret 生产配置;`WECHAT_APP_SECRET` 已填 |
| 3 | 运营端登录与越权隔离 | 管理后台 `/admin/` 用 seed 账号登录;尝试越权访问用户端资源 | 登录成功;运营 token 不能进入用户端(`hasRole("USER")` 兜底) | 运营 | 运营账号仅 seed 创建(迁移无 operator 种子) |
| 4 | 用户资料与择偶条件读写 | 小程序「我的 → 编辑资料 / 择偶条件」保存并回读 | 保存 2xx 且落库正确;下拉选项**全中文简体**(本次中文化成果) | 产品 | 见第 9 项 |
| 5 | 照片上传(SeaweedFS 直传) | 小程序上传头像/相册,上传后打开查看 | presigned PUT 直传成功、GET 下载字节一致;`MINIO_PUBLIC_ENDPOINT` 对外可达 | 运维 | prod `MINIO_PUBLIC_ENDPOINT`(ingress 域名) |
| 6 | 推荐 / 匹配核心链路 | 首页推荐 → Like / Pass → 互选双确认 → 开聊 | 推荐列表中文标签正确;Match/会话建立;Block 优先 | 产品 | 推荐阈值 `matching.recommendation.minScore`(技术默认 60,OQ-MATCH-001);照片上限 `profile.photo.maxCount`(技术默认 6,OQ-PROFILE-001) |
| 7 | 即时聊天(WebSocket) | 互选成功后双方发文本消息 | 握手鉴权、消息实时下行、历史可拉取;图片经安全检测 | 产品 | — |
| 8 | 活动全链路 | 浏览多类型活动 → 报名 → 运营审核 → 签到码核销 | 报名/审核/签到全通;互选活动双确认建 Match+会话 | 运营 | 服务站开放时间(待确认);活动意向端点语义(见 OQ) |
| 9 | 婚恋咨询 / 婚前辅导 | 申请 → 分配 → 排期 → 跟进 → 完成(四态) | 状态机合法迁移;counselor 仅见指派数据;manager 见摘要不见正文 | 运营 | 咨询资质要求、预约时段规则(待确认) |
| 10 | 公益红娘转介 | 红娘建立服务关系 → 推荐 / 转介 | 归属校验生效;不能替非本人负责用户操作、不能自荐 | 运营 | — |
| 11 | 内容 / 反诈 / 课堂 / 服务站 | 运营端 Banner+文章 CRUD、服务站公告;用户端展示 | 内容发布/下架正确;Banner 不外链;服务站公告可见 | 运营 | Banner 最大活跃数量(OQ-BANNER-001,代码暂无限制,需定值) |
| 12 | 管理端驾驶舱口径真实 | 管理后台数据统计页 | 漏斗/安全卡显示**真实值**(非硬编码 0);与汇总表同源 | 产品 | 有效交友匹配报送口径(待确认) |
| 13 | 合规与备份 | ① 未认证 401 / 越权 403 / 非法枚举 400;② 敏感访问有审计;③ 注销后数据保留 ≥36 个月;④ 数据库备份可恢复演练 | 4 项均达成;保留期配置 `account.data-retention-months=36` | 运维+产品 | 数据保留期(2026-09-19 产品确认下限 36 个月);本地资格佐证保留期限(待确认) |
---
## 执行说明
### 1. 部署栈存活(自动化)
```bash
export BASE_URL="https://你的生产域名"
bash infrastructure/scripts/smoke-test.sh
```
脚本断言 `live / ready / version` 与关键匿名接口应 401;任一 FAIL 即退出 1。
带 token 的子集(推荐/匹配/聊天等需登录链路)在提供 `OPERATOR_TOKEN` 后展开,
未提供时明确打印「需人工真机验证」,**不做假绿**。
### 2~13. 人工链路(真机 / 管理端)
- **小程序**:用真机微信账号走「善缘丹阳」小程序,逐项核对页面文案**全中文简体**
(重点:我的页 → 择偶条件 → 子女下拉;详情页学历/职业/婚姻/子女状态标签)。
- **管理端**:浏览器开 `/admin/`,用 seed 运营账号逐模块走查;数据统计页核对数字真实性。
- **合规**:抽查 `/api/v1/operator/audit-logs`(或对应审计接口)确认敏感访问被记录;
数据库做一次备份恢复演练。
### 上线前配置核对(必填,部署时)
| 配置项 | 位置 | 说明 |
|--------|------|------|
| `WECHAT_APP_SECRET` | 后端环境变量 / secret | 生产微信 secret,不得留空 |
| `MINIO_PUBLIC_ENDPOINT` | `infrastructure/docker-compose.prod.yml` | 对外可达的 SeaweedFS 网关域名(presigned URL host),缺省 `http://seaweedfs:8333` 仅容器内通 |
| `JWT_ACCESS_SECRET` / `JWT_REFRESH_SECRET` | 后端环境变量 | 生产必须用强随机值,且与微信登录验签密钥分离(2026-09-22 已修复 refresh 用错密钥) |
| `ENCRYPTION_KEY` | 后端环境变量 | 身份证等敏感字段加解密密钥 |
| HTTPS 证书 | ingress / 反向代理 | 证书到期须纳入监控(部署文档第七十五章) |
| 限流(若启用) | 后端配置 | `RATE_LIMITED`/429 已就位,是否启用及阈值待产品确认 |
---
## 不计入本清单(需产品拍板,非技术阻塞)
- 人脸核验 Provider 选型(`identity.liveness.provider` 默认 `none`,Feature Flag 控制)
- 本地资格佐证触发策略 / 文件保留期限(需合规审核)
- 匹配报送口径、Banner 活跃上限、咨询资质/预约时段、服务站开放时间
- 第三方开放(API Key / OAuth / 限流配额 / OpenAPI 发布)—— 范围扩张,待决策
> 以上在 `docs/PENDING_DECISIONS.md` 逐项跟踪;未确认不影响「核心功能可上线」,
> 但相关默认值(阈值 60、照片 6 张等)应以产品正式确认值替换并落 `decision-register.md`。