Files
th-hotel-simple/docs/project/go-live-notes.md

281 lines
11 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.

# TH Hotel 上线注意事项
本文给产品、研发、测试、运维和后续协作 agent 使用,目标是把上线前必须确认的事项放在同一个地方。这里记录的是当前项目专属要求,不作为可整份复制到其他项目的通用模板。
## 1. 当前上线范围
当前后端已经具备以下能力:
- `GET /api/health`:后端健康检查。
- `GET /api/source-messages`:查询 SourceMessage Inbox 安全摘要。
- `GET /api/source-messages/{id}`:查询单条 SourceMessage 安全摘要。
- `GET /api/source-messages/{id}/original`受控读取邮件原文、HTML 和媒体 URL并记录访问审计。
- `GET /api/system/agentbus-probe`:查看 AgentBus WebSocket 连接状态和安全计数器。
- AgentBus WebSocket 入站链路:默认关闭,开启后只把业务 frame 写入 SourceMessage Inbox。
当前不要把以下能力当作已上线:
- SourceMessage Replay 到 MessageEvent / Evidence。
- AI 识别、Case 匹配、Task 创建、Operation、Receipt。
- 自动 ACK、`task.result` 或客户回复。
- 业务前端页面展示邮件原文。
- OHIP 或其他业务系统写操作。
## 2. 上线前必须确认
上线前至少确认以下事项:
- 当前分支、提交和部署包来源清楚,不能混入本地临时文件、真实 Secret、真实客户邮件样本或构建产物。
- `server` 后端通过完整检查:`cd server && ./mvnw verify`
- 生产或 UAT 数据库已经备份,并确认 Flyway migration 只新增不修改历史脚本。
- 所有 Secret 都通过环境变量、部署平台 Secret 或密钥管理系统注入,不写入仓库、镜像、前端环境变量或普通配置文件。
- 生产默认不保存 AgentBus raw frame 样本。
- AgentBus 实时链路开启前,已经确认 WebSocket URL、Token、Bot Address、外部消息幂等键和断线重连语义。
- 原文读取接口开启前,已经确认谁可以使用、在哪些场景使用、如何轮换访问 key。
- 日志采集、错误响应和监控面板都不会展示邮件正文、HTML、附件 URL、Token、Cookie、客户姓名、邮箱、电话或支付信息。
## 3. 环境变量
### 3.1 数据库
| 变量 | 是否 Secret | 上线注意事项 |
| --- | --- | --- |
| `TH_HOTEL_DB_URL` | 否 | 指向目标环境数据库。URL 包含 `&` 时要加引号。 |
| `TH_HOTEL_DB_USERNAME` | 是 | 使用最小权限账号,不使用个人账号。 |
| `TH_HOTEL_DB_PASSWORD` | 是 | 只能通过 Secret 注入,不写入仓库。 |
| `TH_HOTEL_DB_DRIVER` | 否 | MySQL 使用 `com.mysql.cj.jdbc.Driver`。 |
### 3.2 SourceMessage
| 变量 | 是否 Secret | 上线注意事项 |
| --- | --- | --- |
| `SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY` | 是 | 原文读取临时访问 key。未配置时原文读取默认关闭。 |
注意:
- 原文读取 key 不是用户体系,后续接入正式登录和角色权限后应替换。
- 任何能读取原文的调用都必须有调用方和访问场景,并写入审计表。
### 3.3 AgentBus
| 变量 | 是否 Secret | 上线注意事项 |
| --- | --- | --- |
| `AGENTBUS_PROBE_ENABLED` | 否 | 是否启用 WebSocket 长连接。生产首次上线建议先保持 `false`,完成连通性窗口后再打开。 |
| `AGENTBUS_WS_URL` | 否 | AgentBus WebSocket 地址。 |
| `AGENTBUS_WS_TOKEN` | 是 | WebSocket 鉴权 Token只能通过 Secret 注入。 |
| `AGENTBUS_WS_RECONNECT_DELAY` | 否 | 断线重连间隔,默认 `5s`。 |
| `AGENTBUS_CONNECT_TIMEOUT` | 否 | 连接超时,默认 `15s`。 |
| `AGENTBUS_MAX_FRAME_BYTES` | 否 | 单个入站 frame 最大字节数,默认 `1048576`。 |
| `AGENTBUS_CAPTURE_ENABLED` | 否 | 是否把业务 frame 写入 SourceMessage Inbox。 |
| `AGENTBUS_DEFAULT_HOTEL_ID` | 否 | AgentBus 未提供酒店上下文时的默认业务上下文。 |
注意:
- `AGENTBUS_PROBE_ENABLED=true` 只表示启用连接和入站接收,不代表可以回复客户。
- `AGENTBUS_CAPTURE_ENABLED=false` 时,业务 frame 会被忽略,不会写入 SourceMessage Inbox。
- 当前实现不发送 ACK、不发送 `task.result`、不自动回复客户。
## 4. 数据库上线注意事项
当前 SourceMessage 相关 migration
- `server/src/main/resources/db/migration/V1__create_source_message_inbox.sql`
- `server/src/main/resources/db/migration/V2__create_source_message_original_access_audit.sql`
当前 M002 订单任务相关 migration
- `server/src/main/resources/db/migration/V3__create_reservation_ai_task_workflow.sql`
- `server/src/main/resources/db/migration/V4__harden_reservation_task_queue_and_manual_conversion.sql`
上线前确认:
- 目标数据库为空库或 Flyway history 与当前代码一致。
- MySQL 版本满足项目要求,默认使用 MySQL 8.0+。
- migration 在 UAT 或测试库已经跑过。
- 表和字段中文注释能正常创建。
- 数据库时间按 UTC 写入,接口层负责返回 ISO 8601。
- 执行 V4 前,如果目标库已有 M002 试运行数据,必须先检查 ACTIVE 订单业务号重复和同订单任务队列序号重复。
V4 前置检查 SQL
```sql
SELECT hotel_id, order_key_type, order_business_key, COUNT(*) AS duplicate_count
FROM workflow_reservation_order
WHERE order_status = 'ACTIVE'
AND order_key_type IN ('GROUP_CODE', 'CONFIRMATION_NUMBER')
AND order_business_key IS NOT NULL
GROUP BY hotel_id, order_key_type, order_business_key
HAVING COUNT(*) > 1;
SELECT hotel_id, order_id, queue_participation, execution_order, COUNT(*) AS duplicate_count
FROM workflow_reservation_task
GROUP BY hotel_id, order_id, queue_participation, execution_order
HAVING COUNT(*) > 1;
```
处理要求:
- 如果任一 SQL 返回记录,不要继续执行 V4。
- ACTIVE 订单业务号重复时,先由业务确认保留哪一条 ACTIVE其他订单应转为 `LOGIC_DELETED``ENDED` 或完成任务迁移后再上线。
- 同订单任务队列序号重复时,先按来源顺序和审计证据重新分配 `execution_order`,确认前置任务关系正确后再上线。
- 不要为了让唯一索引创建成功而随意删除订单、任务或 AI 原始记录。
禁止事项:
- 禁止直接修改已发布 migration。
- 禁止手工改生产表结构后再让代码“凑合跑”。
- 禁止把真实邮件正文、附件 URL 或客户数据做成测试种子数据提交。
## 5. 安全与日志
上线前必须确认普通日志、错误响应和状态接口不会输出:
- Authorization、Cookie、CSRF Token。
- Provider API Key、AgentBus Token、数据库密码。
- 邮件正文、HTML、附件 URL、原始 payload。
- 客户姓名、完整邮箱、电话、证件号。
- 支付信息。
SourceMessage 普通列表和普通详情只能返回安全摘要:
- 可以返回SourceMessage ID、酒店 ID、provider、channel、外部邮件 ID、外部邮件链 ID、状态、时间、发送人摘要、主题摘要、安全短摘要。
- 不应返回完整正文、HTML、附件 URL、原始 payload。
原文读取接口只允许在明确授权场景下使用:
```text
GET /api/source-messages/{id}/original
Header: X-TH-Hotel-Source-Original-Read-Key
Header: X-TH-Hotel-Actor
Header: X-TH-Hotel-Access-Scene
```
前端展示 `htmlBody` 前必须 sanitize。后端返回 `htmlSanitizeRequired=true` 是提醒前端不要直接信任 HTML。
## 6. AgentBus 上线注意事项
AgentBus 是消息入口,不是 AI Provider。生产实时链路必须保持以下边界
- 只写 SourceMessage Inbox。
- 不创建 MessageEvent、Evidence、Case、Task、Operation、Receipt。
- 不调用 OHIP、ERP、支付系统等业务写接口。
- 不自动发送 ACK、`task.result` 或客户回复。
- 不在普通日志里输出 raw frame、邮件正文、HTML 或附件 URL。
建议上线顺序:
1. 保持 `AGENTBUS_PROBE_ENABLED=false`,先部署服务并确认健康检查。
2. 确认数据库 migration 和 SourceMessage 查询接口正常。
3. 配置 AgentBus URL 和 Token但仍保持连接关闭。
4. 在约定观察窗口打开 `AGENTBUS_PROBE_ENABLED=true`
5. 观察 `/api/system/agentbus-probe`,确认连接状态、`sessionReady`、计数器和最近错误代码。
6. 用合成测试邮件验证 SourceMessage Inbox 是否写入。
7. 确认日志和监控没有泄露 raw frame、正文或附件 URL。
如果出现异常:
- 先关闭 `AGENTBUS_PROBE_ENABLED`,停止接收入站 frame。
- 如果只是想暂停入库但保留连接,可关闭 `AGENTBUS_CAPTURE_ENABLED`
- 保留状态接口、应用日志和数据库记录用于排查,但不要导出真实邮件正文或附件 URL。
## 7. 上线后冒烟验证
后端服务启动后,按顺序验证:
```text
GET /api/health
```
期望:
- HTTP 200。
- `status = UP`
```text
GET /api/system/agentbus-probe
```
期望:
- HTTP 200。
- 返回 `enabled``connected``sessionReady`、计数器和最近错误代码。
- 响应中不包含 Token、Authorization、raw frame、payload 或邮件正文。
```text
GET /api/source-messages?pageNum=1&pageSize=20
```
期望:
- HTTP 200。
- 只返回安全摘要。
- 不包含正文、HTML、附件 URL 或原始 payload。
```text
GET /api/source-messages/{id}
```
期望:
- HTTP 200 或 404。
- 如果存在记录,只返回安全摘要。
```text
GET /api/source-messages/{id}/original
```
期望:
- 未携带正确访问 key 时返回 403。
- 携带正确访问 key、调用方和访问场景时返回原文内容并写入 `platform_source_message_original_access_audit`
## 8. 监控建议
至少监控:
- 应用进程是否存活。
- `GET /api/health` 是否正常。
- AgentBus `connected``sessionReady` 状态。
- AgentBus `failedFrameCount``rejectedFrameCount` 是否持续增长。
- SourceMessage Inbox 每小时入库数量是否异常突增或归零。
- `FAILED` SourceMessage 数量和安全错误摘要。
- 原文读取审计数量是否异常。
- 数据库连接池、慢 SQL、磁盘空间和 migration 状态。
告警信息不得包含 Secret、正文、HTML、附件 URL 或客户个人信息。
## 9. 回滚与降级
优先降级开关:
```text
AGENTBUS_PROBE_ENABLED=false
AGENTBUS_CAPTURE_ENABLED=false
SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY=
```
说明:
- 关闭 `AGENTBUS_PROBE_ENABLED` 可以停止 WebSocket 入站连接。
- 关闭 `AGENTBUS_CAPTURE_ENABLED` 可以保留连接但暂停写入 Inbox。
- 清空 `SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY` 可以关闭原文读取接口。
数据库回滚注意:
- 已执行的 migration 不应直接删除或手工回滚。
- 如果新版本已写入 SourceMessage 数据,回滚应用前要确认旧版本是否能兼容新表存在。
- 需要修复表结构时,应新增 migration而不是修改已发布 migration。
## 10. 上线责任确认
上线前需要有人明确确认:
- 部署版本:确认本次上线的分支、提交和构建产物。
- 数据库:确认 migration、备份和连接信息。
- Secret确认所有密钥由部署平台注入。
- AgentBus确认是否开启 WebSocket是否允许捕获入库。
- 安全:确认日志、错误响应、状态接口和监控面板没有敏感数据。
- 业务:确认当前上线范围不包含 replay、AI、Case、Task、客户回复或 OHIP 写操作。
只要上述任何一项没人确认,就不要打开生产实时入口。