实现 SourceMessage Inbox 与 AgentBus 入站闭环
This commit is contained in:
@@ -38,25 +38,33 @@ server/src/main/java/<base-package>/
|
||||
├── service/
|
||||
│ ├── XxxService.java
|
||||
│ └── impl/XxxServiceImpl.java
|
||||
├── api/
|
||||
├── control/
|
||||
│ └── XxxController.java
|
||||
├── dto/
|
||||
│ ├── XxxCreateRequest.java
|
||||
│ ├── XxxUpdateRequest.java
|
||||
│ └── XxxQueryRequest.java
|
||||
└── vo/
|
||||
└── XxxResponse.java
|
||||
├── repository/
|
||||
│ └── XxxRepository.java
|
||||
└── common/
|
||||
├── request/
|
||||
│ ├── XxxCreateRequest.java
|
||||
│ ├── XxxUpdateRequest.java
|
||||
│ └── XxxQueryRequest.java
|
||||
├── result/
|
||||
│ └── XxxResult.java
|
||||
├── dto/
|
||||
│ └── XxxSnapshot.java
|
||||
└── enums/
|
||||
└── XxxStatus.java
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- `platform` 放通用能力。
|
||||
- `workflows` 放业务流程。
|
||||
- `integrations` 放外部系统适配器。
|
||||
- `integrations` 放外部系统适配器;外部协议适配类建议放在 `integrations/<capability>/<provider>/adapter`。
|
||||
- 平台层不得依赖具体业务流程。
|
||||
- 业务层不得直接依赖外部系统 DTO。
|
||||
- Controller 不直接访问 Mapper。
|
||||
- 前端不直接调用外部系统。
|
||||
- 外部协议到内部命令或 DTO 的转换类使用 `Adapter`、`Converter` 等后缀,不使用 `Mapper` 命名,避免和 MyBatis Mapper 混淆。
|
||||
|
||||
## 3. 低耦合与可维护性
|
||||
|
||||
@@ -71,6 +79,7 @@ server/src/main/java/<base-package>/
|
||||
- 跨模块调用通过 Service、Port、API 契约或事件完成,不直接访问对方 Mapper、Entity 或私有工具类。
|
||||
- Controller 只调用本模块或明确授权的应用服务,不跨层访问 Mapper 或 Adapter。
|
||||
- Mapper 只负责本聚合或本表的数据访问,不承载跨业务编排。
|
||||
- 不为了重命名 MyBatis-Plus 自带方法而在 Mapper 中写薄 default 包装;语义化查询优先放在 Repository 或确有必要的自定义 Mapper 方法中。
|
||||
- 公共能力先放在业务模块内,出现真实重复和稳定语义后再提升到 `platform`。
|
||||
- 不为少量相似代码提前抽象大而全的 `CommonService`、`CommonUtil` 或通用模型。
|
||||
- 当修改一个模块会牵动多个无关模块时,应优先检查依赖方向和接口边界。
|
||||
@@ -269,6 +278,7 @@ XxxQueryRequest
|
||||
规则:
|
||||
|
||||
- 不使用一个大而全的 `Bo` 承载所有场景。
|
||||
- Request、Command、Query 条件建议放在模块内 `common/request`。
|
||||
- 创建、更新、查询参数分开。
|
||||
- 使用 Bean Validation 做基础校验。
|
||||
- 查询对象可以包含分页、排序、时间范围等条件。
|
||||
@@ -289,6 +299,7 @@ XxxQueryRequest
|
||||
- Long ID 返回给前端时按字符串处理。
|
||||
- 时间统一按 API 规范格式化。
|
||||
- 列表接口使用统一分页响应。
|
||||
- Result、分页结果、操作结果建议放在模块内 `common/result`;跨层 DTO、Snapshot、Draft 建议放在模块内 `common/dto`。
|
||||
|
||||
## 10. Mapper 规范
|
||||
|
||||
@@ -312,6 +323,8 @@ public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
|
||||
- Mapper 只负责数据库访问。
|
||||
- 复杂业务判断不放在 Mapper。
|
||||
- 优先使用 MyBatis-Plus Wrapper。
|
||||
- MyBatis-Plus 自带的 `selectById`、`insert`、`updateById` 等继承方法不需要额外 default 包装。
|
||||
- 自定义 default 方法只有在表达明确业务语义且能减少真实重复时才添加,不能只是改名转调。
|
||||
- 手写 SQL 必须使用 `#{}` 参数绑定。
|
||||
- 禁止使用 `${}` 拼接业务参数。
|
||||
- 手写 SQL 要避免返回过宽字段。
|
||||
|
||||
@@ -33,13 +33,19 @@ server/src/main/java/<base_package>
|
||||
├── config
|
||||
├── modules
|
||||
│ └── <business-domain>
|
||||
│ ├── controller
|
||||
│ ├── control
|
||||
│ ├── service
|
||||
│ ├── service/impl
|
||||
│ ├── domain
|
||||
│ ├── mapper
|
||||
│ └── repository
|
||||
│ ├── repository
|
||||
│ └── common
|
||||
│ ├── dto
|
||||
│ ├── request
|
||||
│ ├── result
|
||||
│ └── enums
|
||||
├── integrations
|
||||
│ └── <capability>/<provider>/adapter
|
||||
└── support
|
||||
```
|
||||
|
||||
@@ -52,6 +58,8 @@ server/src/main/java/<base_package>
|
||||
- 跨模块调用优先通过 Service、Port、API 契约或事件完成。
|
||||
- 禁止直接访问其他模块的 Mapper、Entity 或内部实现。
|
||||
- 外部系统通过 `integrations` 或 Adapter 隔离,业务层只依赖稳定端口。
|
||||
- 外部协议适配类放在具体集成模块的 `adapter` 包,例如 `integrations.<capability>.<provider>.adapter`。
|
||||
- 外部协议转换类使用 `Adapter`、`Converter` 等后缀,不使用 `Mapper` 命名,避免和 MyBatis Mapper 混淆。
|
||||
- 外部 DTO、数据库 Entity、领域对象和 API Response 必须分离。
|
||||
- 公共代码只有在出现真实重复和稳定语义后再抽取。
|
||||
|
||||
@@ -64,6 +72,11 @@ server/src/main/java/<base_package>
|
||||
- Repository 是领域侧持久化接口。
|
||||
- Mapper / Entity / SQL 属于持久化细节,不应向上泄漏到 API 层。
|
||||
- 外部调用通过 Port / Adapter 隔离,业务层不依赖厂商 SDK 或厂商 DTO。
|
||||
- Request、Command、Query 条件建议放在模块内 `common.request`。
|
||||
- Result、分页结果、操作结果建议放在模块内 `common.result`。
|
||||
- 跨层 DTO、Snapshot、Draft 等通用数据载体建议放在模块内 `common.dto`。
|
||||
- 枚举、状态码和失败原因建议放在模块内 `common.enums`。
|
||||
- 生成或迁移代码前应先阅读项目规范并查看同模块既有代码习惯;目录归属、类名后缀或依赖方向不明确时,先询问再实现。
|
||||
|
||||
## 5. 数据建模规则
|
||||
|
||||
@@ -128,6 +141,8 @@ Secret 只能通过环境变量、本地 `.env` 或部署平台 Secret 注入。
|
||||
|
||||
- 架构文档、设计文档、目录结构、数据模型、字段映射和接口示例必须优先使用中文说明业务含义。
|
||||
- 领域对象、应用服务、外部适配器、Controller、配置属性和复杂参数对象应说明业务含义、边界或调用约束。
|
||||
- Mapper 中 ORM 自带继承方法不强制补中文注释;不要为了重命名 `selectById`、`insert`、`updateById` 等自带方法而写薄包装。自定义语义化查询、写入、更新方法应根据业务复杂度合理补充中文注释。
|
||||
- Entity 字段建议有中文注释,说明字段业务含义、来源、代码值范围或安全限制。
|
||||
- 复杂流程、幂等键、并发控制、事务边界、错误转换、外部字段映射和安全脱敏逻辑必须说明原因。
|
||||
- 注释不得只复述类名、方法名或字段名。
|
||||
- 不得用“TODO 待完善”替代真实说明。
|
||||
@@ -164,11 +179,15 @@ cd server
|
||||
- 修改接口前确认领域模型、字段映射、前端影响和测试范围。
|
||||
- 不修改与当前任务无关的用户变更。
|
||||
- 修改后运行项目已配置的检查命令。
|
||||
- 生成或迁移代码前先参考当前项目代码规范和既有代码习惯;如果目录归属或命名不确定,先确认再继续。
|
||||
- Git commit message 使用中文,清楚说明本次提交的业务或技术变更。
|
||||
|
||||
## 13. 后端提交前检查清单
|
||||
|
||||
- [ ] Controller 是否没有直接访问 Mapper 或外部 Adapter?
|
||||
- [ ] Request、Result、DTO 是否按语义放在 request、result、dto 目录,而不是混在 Service 或临时 application 包?
|
||||
- [ ] 外部协议适配类是否放在 integrations 的 adapter 包,并避免使用 Mapper 命名混淆 ORM Mapper?
|
||||
- [ ] Mapper 是否没有为了 ORM 自带继承方法写薄 default 包装?
|
||||
- [ ] 外部 DTO 是否没有进入领域模型?
|
||||
- [ ] DTO、Entity、Domain、Response 是否没有混用?
|
||||
- [ ] 跨模块调用是否通过稳定接口完成?
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
|
||||
- `backend-development-guidelines.md`:当前项目后端专属规范。
|
||||
- `frontend-development-guidelines.md`:当前项目前端专属规范。
|
||||
- `go-live-notes.md`:当前项目上线注意事项,记录上线前检查、环境变量、安全、AgentBus、验证和回滚。
|
||||
- `requirements/M001-source-message-inbox-prd.md`:M001 邮件来源入口 PRD,记录 AgentBus 邮件 JSON 入库、历史查询、原文读取和媒体引用边界。
|
||||
- `integrations/superagent-agentbus-project-integration-guide.md`:当前项目 SuperAgent 与 AgentBus 验证记录和项目级接入细节。
|
||||
|
||||
@@ -72,22 +72,63 @@ integrations
|
||||
|
||||
- `platform` 保存部门中立能力,例如消息、证据、AI 调用审计、Operation、Receipt、审计。
|
||||
- `workflows` 保存部门业务流程,当前明确的是 `reservation`。
|
||||
- `integrations` 保存外部系统适配器,例如 OHIP、SuperAgent、AgentBus。
|
||||
- `integrations` 保存外部系统适配器,例如 OHIP、SuperAgent、AgentBus;外部协议转换类应放入具体集成模块的 `adapter` 包。
|
||||
- 平台核心不得依赖预订部专有字段。
|
||||
- 部门工作流可以依赖平台核心,平台核心不能反向依赖部门模块。
|
||||
- 外部系统 DTO、Oracle DTO、Provider DTO、领域模型和 API Response 必须分离。
|
||||
- Oracle DTO 或生成代码只能位于 `integrations.ohip`,不得进入平台领域模型。
|
||||
- 外部协议到内部命令或 DTO 的转换类使用 `Adapter`、`Converter` 等能表达适配语义的后缀,不使用 `Mapper` 命名,避免和 MyBatis Mapper 混淆。
|
||||
|
||||
当前项目后端模块内部目录强制按以下结构组织:
|
||||
|
||||
```text
|
||||
<module>
|
||||
├── control
|
||||
├── service
|
||||
│ └── impl
|
||||
├── domain
|
||||
├── mapper
|
||||
├── repository
|
||||
└── common
|
||||
├── dto
|
||||
├── request
|
||||
├── result
|
||||
└── enums
|
||||
```
|
||||
|
||||
中文说明:
|
||||
|
||||
| 目录 | 中文职责 | 放置内容 |
|
||||
| --- | --- | --- |
|
||||
| `control` | HTTP 入口层 | Controller 具体实现类,只处理请求契约、参数校验和响应映射 |
|
||||
| `service` | 服务契约层 | Service 接口,只表达模块对外提供的稳定业务能力 |
|
||||
| `service.impl` | 服务实现层 | Service 实现类,负责编排事务、幂等、Repository 和外部端口 |
|
||||
| `domain` | 数据实体层 | Entity 类,字段必须有中文注释,不能与 Response 或外部 DTO 混用 |
|
||||
| `mapper` | MyBatis 访问层 | Mapper 类和语义化 Mapper 方法,Controller 与 Service 不直接跨层暴露 Mapper |
|
||||
| `repository` | 持久化封装层 | Repository 接口和具体实现,对 Service 屏蔽 Mapper 与数据库细节 |
|
||||
| `common.dto` | 通用数据载体层 | 模块内部跨层传递的 DTO、快照、草稿等数据载体 |
|
||||
| `common.request` | 请求模型层 | Controller、Service 或外部适配器输入侧的 Request、Command、Query 条件 |
|
||||
| `common.result` | 结果模型层 | Service 或 Controller 输出侧的 Result、分页结果、操作结果 |
|
||||
| `common.enums` | 模块枚举层 | 本模块稳定业务枚举、状态码和失败原因枚举 |
|
||||
|
||||
后续生成或移动 Java 代码时必须严格遵守上述目录,不再新增 `api`、`application`、`persistence` 等同义包来承载这些职责,除非先更新本规范并说明迁移原因。已有或迁移来的 `application` 包中的 Request、Result、DTO 类,应按语义移动到对应模块的 `common.request`、`common.result`、`common.dto`。如果类职责或目录归属不明确,必须先询问再继续。
|
||||
|
||||
## 4. Controller / Service / Repository 规则
|
||||
|
||||
- Controller 只做 HTTP 契约、参数校验、权限入口和响应映射。
|
||||
- Controller 不直接访问 Mapper。
|
||||
- Controller 不直接调用外部适配器。
|
||||
- Application Service 编排事务、领域对象、Repository 和外部端口。
|
||||
- Domain 对象表达稳定业务语义,不引入 HTTP、JSON、MyBatis 或外部 Provider 细节。
|
||||
- Repository 是领域侧持久化接口。
|
||||
- Infrastructure / Persistence 负责 Entity、Mapper 和数据库细节。
|
||||
- Service 接口位于 `service` 包,表达模块对外提供的稳定业务能力。
|
||||
- Service 实现类位于 `service.impl` 包,编排事务、Entity、Repository 和外部端口。
|
||||
- Request、Command、Query 条件位于 `common.request` 包。
|
||||
- Result、分页结果、操作结果位于 `common.result` 包。
|
||||
- 跨层 DTO、Snapshot、Draft 等通用数据载体位于 `common.dto` 包。
|
||||
- Entity 位于 `domain` 包,表达数据库表字段与业务含义,不与 DTO、Response 或外部 Provider DTO 混用。
|
||||
- Mapper 位于 `mapper` 包,只负责本模块数据库表访问和语义化查询方法。
|
||||
- Repository 位于 `repository` 包,负责封装 Mapper 和数据库细节,作为 Service 的持久化边界。
|
||||
- 外部调用通过端口和 Adapter 隔离,业务层不依赖厂商 SDK 或厂商 DTO。
|
||||
- 外部协议适配类位于对应 `integrations.<capability>.<provider>.adapter` 包,负责把外部 DTO 或 JSON 转换为内部稳定命令。
|
||||
- 生成或迁移代码前必须先阅读本规范并查看同模块既有代码习惯;如果放置目录、类名后缀或依赖方向不确定,先询问再实现。
|
||||
|
||||
## 5. 数据建模规则
|
||||
|
||||
@@ -177,6 +218,10 @@ groupCode
|
||||
|
||||
- 架构文档、设计文档、目录结构、数据模型、字段映射和接口示例必须优先使用中文说明业务含义。
|
||||
- 领域对象、应用服务、外部适配器、Controller、配置属性和复杂参数对象应说明业务含义、边界或调用约束。
|
||||
- `control`、`service`、`service.impl` 中的方法必须有中文注释,说明业务动作、调用边界、幂等或安全约束。
|
||||
- `mapper` 中 MyBatis-Plus 自带继承方法不强制补中文注释;不要为了重命名 `selectById`、`insert`、`updateById` 等自带方法而写薄 default 包装。本项目自定义的语义化查询、写入、更新方法应根据业务复杂度合理补充中文注释。
|
||||
- `domain` 中 Entity 的每个字段必须有中文注释,说明字段业务含义、来源、代码值范围或安全限制。
|
||||
- `repository` 中对外暴露的方法必须有中文注释,说明持久化语义和是否返回安全字段。
|
||||
- 复杂流程、幂等键、并发控制、事务边界、错误转换、外部系统字段映射和安全脱敏逻辑必须说明原因。
|
||||
- 注释不得只复述类名、方法名或字段名。
|
||||
- 不得用“TODO 待完善”替代真实说明。
|
||||
@@ -239,6 +284,8 @@ cd server
|
||||
./mvnw -Dtest=SomeFocusedTest test
|
||||
```
|
||||
|
||||
默认 `test` profile 使用 H2 MySQL Mode,保证普通测试不依赖本机 MySQL。需要连接真实测试 MySQL 时,使用 `test,test-mysql` profile,并通过 `TH_HOTEL_TEST_DB_URL`、`TH_HOTEL_TEST_DB_USERNAME`、`TH_HOTEL_TEST_DB_PASSWORD` 注入测试库连接信息。测试 MySQL 只能使用本地或 CI 测试库,不得连接生产库或包含真实酒店、客户、支付数据的数据库。
|
||||
|
||||
如果命令尚未配置或因环境问题无法运行,必须明确说明,不能假装通过。
|
||||
|
||||
## 16. Git 与协作流程
|
||||
@@ -254,7 +301,13 @@ cd server
|
||||
## 17. 后端提交前检查清单
|
||||
|
||||
- [ ] 是否遵守 platform / workflows / integrations 分层?
|
||||
- [ ] 模块内部是否遵守 `control` / `service` / `service.impl` / `domain` / `mapper` / `repository` / `common.dto` / `common.request` / `common.result` / `common.enums` 目录规则?
|
||||
- [ ] Controller 是否没有直接访问 Mapper 或外部 Adapter?
|
||||
- [ ] Request、Result、DTO 是否放在 `common.request`、`common.result`、`common.dto`,而不是混在 `service` 或临时 `application` 包?
|
||||
- [ ] `control`、`service`、`service.impl`、`repository` 方法是否有中文注释?
|
||||
- [ ] Mapper 自定义语义化方法是否按复杂度合理补充中文注释,且未为了 MyBatis-Plus 自带继承方法强行加无意义注释?
|
||||
- [ ] 外部协议适配类是否放在 `integrations.<capability>.<provider>.adapter`,并避免使用 `Mapper` 命名混淆 MyBatis Mapper?
|
||||
- [ ] Entity 字段是否有中文注释?
|
||||
- [ ] 外部 DTO 是否没有进入领域模型?
|
||||
- [ ] 写接口是否有幂等、版本或审计设计?
|
||||
- [ ] Flyway SQL 是否有规范中文注释?
|
||||
|
||||
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 写操作。
|
||||
|
||||
只要上述任何一项没人确认,就不要打开生产实时入口。
|
||||
@@ -78,21 +78,22 @@ integrations
|
||||
└── agentbus
|
||||
```
|
||||
|
||||
TH Hotel 当前代码中的可参考文件:
|
||||
TH Hotel 当前 M001 相关代码中的可参考文件:
|
||||
|
||||
| 目的 | 参考文件 |
|
||||
| --- | --- |
|
||||
| SuperAgent 配置 | `server/src/main/java/cn/nianxx/thhotel/integrations/ai/deerflow/SuperAgentProbeProperties.java` |
|
||||
| SuperAgent HTTP 客户端 | `server/src/main/java/cn/nianxx/thhotel/integrations/ai/deerflow/SuperAgentOpenApiClient.java` |
|
||||
| SuperAgent SSE 解析 | `server/src/main/java/cn/nianxx/thhotel/integrations/ai/deerflow/SuperAgentSseParser.java` |
|
||||
| SuperAgent 能力适配器 | `server/src/main/java/cn/nianxx/thhotel/integrations/ai/deerflow/SuperAgentCapabilityAdapter.java` |
|
||||
| SuperAgent 探针 API | `server/src/main/java/cn/nianxx/thhotel/platform/system/api/SuperAgentProbeController.java` |
|
||||
| AI 调用审计 API | `server/src/main/java/cn/nianxx/thhotel/platform/ai/api/AiCapabilityInvocationController.java` |
|
||||
| AgentBus WebSocket 客户端 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/AgentBusProbeWebSocketClient.java` |
|
||||
| AgentBus frame 处理 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/AgentBusFrameProcessor.java` |
|
||||
| AgentBus 到 SourceMessage 映射 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/AgentBusSourceMessageMapper.java` |
|
||||
| AgentBus 入站持久化 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/PersistingAgentBusSourceMessageCaptureService.java` |
|
||||
| SourceMessage Replay | `server/src/main/java/cn/nianxx/thhotel/platform/message/application/SourceMessageReplayApplicationService.java` |
|
||||
| SourceMessage 查询与原文 API | `server/src/main/java/cn/nianxx/thhotel/platform/message/control/SourceMessageController.java` |
|
||||
| SourceMessage 捕获服务 | `server/src/main/java/cn/nianxx/thhotel/platform/message/service/impl/SourceMessageCaptureServiceImpl.java` |
|
||||
| SourceMessage 原文读取服务 | `server/src/main/java/cn/nianxx/thhotel/platform/message/service/impl/SourceMessageOriginalServiceImpl.java` |
|
||||
| SourceMessage 持久化边界 | `server/src/main/java/cn/nianxx/thhotel/platform/message/repository/MybatisSourceMessageInboxRepository.java` |
|
||||
| AgentBus WebSocket 客户端 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusWebSocketClient.java` |
|
||||
| AgentBus frame 处理 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusFrameProcessor.java` |
|
||||
| AgentBus 到 SourceMessage 适配 | `server/src/main/java/cn/nianxx/thhotel/integrations/messaging/agentbus/adapter/AgentBusSourceMessageAdapter.java` |
|
||||
| AgentBus 状态 API | `server/src/main/java/cn/nianxx/thhotel/platform/system/control/AgentBusProbeStatusController.java` |
|
||||
| SourceMessage 表结构 | `server/src/main/resources/db/migration/V1__create_source_message_inbox.sql` |
|
||||
| SourceMessage 原文读取审计表 | `server/src/main/resources/db/migration/V2__create_source_message_original_access_audit.sql` |
|
||||
|
||||
SourceMessage Replay 到 MessageEvent / Evidence 尚未实现,需等 MessageEvent、Evidence 字段模型确认后再进入后续 checkpoint。
|
||||
|
||||
## 4. SuperAgent 对接
|
||||
|
||||
@@ -269,6 +270,7 @@ AGENTBUS_MAX_SAMPLES=100
|
||||
AGENTBUS_CAPTURE_ENABLED=true
|
||||
AGENTBUS_DEFAULT_HOTEL_ID=HOTEL-TEST
|
||||
AGENTBUS_REPLY_MODE=NONE
|
||||
SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY=
|
||||
```
|
||||
|
||||
变量说明:
|
||||
@@ -288,6 +290,7 @@ AGENTBUS_REPLY_MODE=NONE
|
||||
| `AGENTBUS_CAPTURE_ENABLED` | 否 | 是否写入 SourceMessage Inbox。 |
|
||||
| `AGENTBUS_DEFAULT_HOTEL_ID` | 否 | AgentBus 未提供租户上下文时的默认业务上下文。 |
|
||||
| `AGENTBUS_REPLY_MODE` | 否 | 调试回复模式。真实客户渠道应保持 `NONE`。 |
|
||||
| `SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY` | 是 | 原文读取接口的临时受控访问 key,后续可替换为正式权限体系。 |
|
||||
|
||||
### 5.2 WebSocket 连接
|
||||
|
||||
@@ -508,6 +511,7 @@ MessageEvent
|
||||
- `DEERFLOW_OPEN_API_KEY`
|
||||
- `SUPERAGENT_PROBE_ACCESS_KEY`
|
||||
- `AGENTBUS_WS_TOKEN`
|
||||
- `SOURCE_MESSAGE_ORIGINAL_READ_ACCESS_KEY`
|
||||
- `SOURCE_MESSAGE_REPLAY_ACCESS_KEY`
|
||||
- 数据库密码
|
||||
- 任何真实客户渠道 Token
|
||||
|
||||
Reference in New Issue
Block a user