实现 SourceMessage Inbox 与 AgentBus 入站闭环
This commit is contained in:
250
docs/project/go-live-notes.md
Normal file
250
docs/project/go-live-notes.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# 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`
|
||||
|
||||
上线前确认:
|
||||
|
||||
- 目标数据库为空库或 Flyway history 与当前代码一致。
|
||||
- MySQL 版本满足项目要求,默认使用 MySQL 8.0+。
|
||||
- migration 在 UAT 或测试库已经跑过。
|
||||
- 表和字段中文注释能正常创建。
|
||||
- 数据库时间按 UTC 写入,接口层负责返回 ISO 8601。
|
||||
|
||||
禁止事项:
|
||||
|
||||
- 禁止直接修改已发布 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 写操作。
|
||||
|
||||
只要上述任何一项没人确认,就不要打开生产实时入口。
|
||||
Reference in New Issue
Block a user