# Phase 0 报告显式确认发送：交付与验收记录

日期：2026-08-02  
状态：Code Complete / Ready for Release（生产迁移与真实环境 smoke 待执行）

## 角色与范围

| 字段 | 值 |
|---|---|
| Owner | Report Media Backend / Store Miniapp FE / Store Admin FE |
| Paired QA | Report Share QA |
| Data Model Review | Yes |
| Architecture Review | Yes |
| Access / Privacy Review | Yes |
| 范围 | Report 发送字段与迁移、确认 API、BusinessEvent、工作台、漏斗、小程序分享弹层、Admin 报告列表、本体与发布文档 |
| 明确排除 | 微信投递回执、自动发送、历史发送猜测、再次预约归因、生产数据库变更 |

## 冻结口径

- 复制链接、复制话术、二维码、预览或打开报告都不自动计为发送。
- 历史报告迁移为 `unknown`；迁移后新报告默认 `unsent`。
- 仅本店 boss/staff 可选择 `wechat|qr|other` 显式确认为 `sent`。
- 首次回执不可覆盖；重复确认幂等成功，不重复写 `report_sent`。
- 工作台只提醒 `unsent`，不把历史 `unknown` 冒充未发送。
- 公开 token 响应不返回发送状态、回执或确认员工。

## 自动验收结果

| 检查 | 结果 |
|---|---|
| Backend `mvn test` | PASS：175 tests，0 failures，0 errors |
| Backend `mvn -DskipTests package` | PASS |
| 迁移 H2 MySQL mode | PASS：历史 unknown、新记录默认 unsent、回执一致性 |
| Admin `npm run build` | PASS |
| Frontend `npm run build:h5` | PASS |
| Frontend `npm run build:mp-weixin` | PASS；`verify-mp-app-json` OK |
| Release shell syntax | PASS：`release-preflight.sh`、`production-smoke.sh` |
| Ontology validate | PASS：242 条目、引用完整 |
| Ontology drift | PASS：57/57 HTTP endpoints，13/13 JPA entities，0 drift |
| `git diff --check` | PASS（四仓） |

## 关键自动化覆盖

- 新报告强制 `unsent`，忽略请求体伪造的发送字段。
- 首次确认写 `sentAt/sentByUserId/sendChannel` 和低敏 `report_sent`。
- 重复确认保留首次回执且不重复保存/发事件。
- customer、跨店员工、非法渠道与非法筛选状态均拒绝。
- 发送确认不改写 `Report.updateTime`，避免重置成片处理超时计时。
- Admin 工作台新增 `unsent_report`，准确总数、低敏预览和服务端发送状态筛选均覆盖。
- 公开报告响应继续隐藏内部身份、token 和发送回执。

## 发布前仍需人工完成

- [ ] 备份并在隔离库恢复验证。
- [ ] 按固定顺序执行第五个迁移 `20260801_create_report_send_status.sql`，三项验证均为 0。
- [ ] 以最终生产配置运行 JPA `validate` + 18 项只读不变量预检。
- [ ] boss/staff/customer 三角色 smoke：复制不变更、三渠道确认、重复确认、跨店拒绝、公开页裁剪。
- [ ] 核对工作台 `unsent_report` 与当日 `report_sent` 漏斗数字。
- [ ] 生产变更另行授权；本交付未连接或修改生产数据库。
