docs(P19-1,P19-2,P19-3,P19-4): 冻结事件清单与集成边界

这个提交包含在:
2026-03-07 23:23:34 +08:00
父节点 c69ea538df
当前提交 c9b75f0757
共修改 2 个文件,包含 201 行新增和 0 行删除
+63
查看文件
@@ -0,0 +1,63 @@
# 领域事件清单(P19 冻结版)
**快照日期**:2026-03-07
**目标**:冻结 `hyb-oa` 当前采购与资产域对外发布的标准事件名称、触发时机与最小载荷,为未来 ERP / IM / AI 适配提供统一事实源。
## 1. 使用原则
- 本文档只定义**领域事件名与边界**,不代表当前已实现事件总线。
- 未来若落地 Outbox / webhook / MQ,事件名与载荷应保持向后兼容。
- 事件仅表达“已经发生的领域事实”,不表达待办命令。
## 2. 标准事件清单
| 事件名 | 触发时机 | 领域对象 | 最小载荷字段 | 推荐消费者 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `purchase_request.submitted` | 采购申请提交成功后 | `purchase_request` | `purchaseRequestId`, `requestNo`, `applicantId`, `departmentId`, `legalEntityId`, `costCenterId`, `supplierId`, `budgetPoolId`, `totalAmount`, `status` | IM 通知、ERP 预处理、AI 摘要 | 仅表示进入 `reviewing` |
| `purchase_request.approved` | 采购申请审批通过后 | `purchase_request` | `purchaseRequestId`, `requestNo`, `approvedBy`, `legalEntityId`, `costCenterId`, `supplierId`, `budgetPoolId`, `totalAmount`, `status` | ERP、IM、AI | 对应预算 `confirm` 已完成 |
| `purchase_request.rejected` | 采购申请审批驳回后 | `purchase_request` | `purchaseRequestId`, `requestNo`, `actorId`, `reason`, `status` | IM、AI | 若存在预算预留,应已释放 |
| `purchase_request.withdrawn` | 申请人撤回采购申请后 | `purchase_request` | `purchaseRequestId`, `requestNo`, `actorId`, `status` | IM、AI、ERP 补偿 | 表示由 `reviewing` 回到 `draft` |
| `asset.card.created` | 资产卡片创建成功后 | `asset_card` | `assetId`, `assetNo`, `name`, `categoryId`, `legalEntityId`, `costCenterId`, `purchaseRequestId`, `status` | ERP、IM、AI | 资产域不接 workflow |
| `asset.assigned` | 资产领用成功后 | `asset_card` | `assetId`, `assetNo`, `employeeId`, `assignedAt`, `location`, `status` | IM、AI | 对应新增 open assignment |
| `asset.returned` | 资产归还成功后 | `asset_card` | `assetId`, `assetNo`, `employeeId`, `returnedAt`, `location`, `status` | IM、AI | 对应关闭 open assignment |
| `asset.transferred` | 资产调拨成功后 | `asset_card` | `assetId`, `assetNo`, `fromEmployeeId`, `toEmployeeId`, `fromLocation`, `toLocation`, `transferredAt`, `status` | ERP、IM、AI | 可只改位置,不一定改归属人 |
| `inventory_check.completed` | 盘点任务完成后 | `inventory_check` | `inventoryCheckId`, `checkNo`, `scopeType`, `scopeRefId`, `completedAt`, `itemCount`, `summary` | ERP、IM、AI | `summary` 建议包含 matched/missing/extra/damaged 计数 |
## 3. 事件名与运行时对象映射
| entityType | 推荐事件前缀 | 当前事实源 |
| --- | --- | --- |
| `purchase_request` | `purchase_request.*` | `P17A` / `P17B` |
| `asset_card` | `asset.*` | `P18A` / `P18B` |
| `inventory_check` | `inventory_check.*` | `P18B` |
## 4. 最小 Envelope 建议
未来若落地事件投递,建议统一使用如下 envelope:
```json
{
"eventName": "purchase_request.submitted",
"eventId": "uuid",
"occurredAt": "2026-03-07T23:22:00+08:00",
"actorId": "user-id",
"entityType": "purchase_request",
"entityId": "entity-id",
"payloadVersion": 1,
"payload": {}
}
```
## 5. 兼容性规则
- 事件一旦对外承诺,名称不得随意修改。
- 新增字段必须保持向后兼容;删除字段需要单独版本升级。
- 载荷字段命名应与 HTTP camelCase 输出保持一致,不直接暴露数据库 snake_case 列名。
## 6. 明确不纳入 P19 的事件
- `purchase_request.archived`:待未来需要对接采购归档通知时再冻结
- `inventory_check.started`:当前不作为外部关键事实源
- `asset.repaired` / `asset.retired`:待未来维修/报废专项后再定义
## 7. 推荐的首批消费场景
- IM:采购提交、采购审批结果、资产领用归还、盘点完成提醒
- ERP:采购审批通过摘要、资产卡片新增摘要、盘点完成摘要
- AI:审批摘要、异常提示、主数据重复建议、盘点结果总结
+138
查看文件
@@ -0,0 +1,138 @@
# 集成边界冻结(P19)
**快照日期**:2026-03-07
**当前基线**:`P18B` 已完成并进入 `docs/feature-matrix.md`。
**目标**:冻结 `hyb-oa` 在 ERP/财务、IM/协同、AI 与 MCP 使用上的边界,作为后续专项实施的约束,不直接引入任何运行时代码。
## 1. 总体原则
### 1.1 只通过边界集成
- 外部系统只允许通过两种形式接入:
- 领域事件(推荐,后续可落到 Outbox)
- 显式 API 适配层
- 禁止外部系统直写核心业务表。
- 禁止为了对接外部系统,在核心事务表中提前加入 ERP 私有字段、IM 私有字段或 AI 中间状态字段。
### 1.2 核心域优先
- `purchase_request`、`asset_card`、`inventory_check` 等领域模型继续由业务服务自己维护。
- 集成层只能消费既有领域事实,不能反向篡改领域判定逻辑。
- 若未来需要双向同步,必须先定义“系统主责方(source of truth)”,再设计幂等回写接口。
### 1.3 回滚优先
- 所有未来集成必须支持“关闭适配器后核心域仍可独立运行”。
- 外部调用失败只能影响外围联动,不得阻断核心单据保存、审批和查询。
- 对外推送必须具备可重试、可补偿、可审计能力。
## 2. ERP / 财务适配边界
### 2.1 允许进入适配层的对象
- 主数据:`LegalEntity`、`CostCenter`、`Supplier`
- 采购:`purchase_request` 的审批结果、预算占用确认结果、PO/合同归档摘要
- 资产:`asset_card` 基础卡片信息、归属变更摘要、盘点完成摘要
### 2.2 推荐适配方式
- **主数据同步**:
- 由 `hyb-oa` 输出标准化读模型或事件
- ERP 适配器负责字段映射与批量/增量同步
- **财务凭证/单据接口**:
- 先生成中间格式(例如 JSON/CSV/显式 API payload)
- 再由独立适配器调用外部 ERP
- **失败处理**:
- 在适配层重试
- 失败记录在适配层日志/事件投递表,不回写核心事务状态为“失败”
### 2.3 明确禁止事项
- 禁止在 `PurchaseRequest`、`AssetCard`、`BudgetPool` 等核心表中直接加入 ERP 专有主键、分录号、凭证表字段。
- 禁止应用直接连写 ERP 主表。
- 禁止把 ERP 状态机复制到 `hyb-oa` 核心路由中。
### 2.4 建议的后续专项
- `P19+ERP-1`:主数据同步协议
- `P19+ERP-2`:采购审批结果导出/回写协议
- `P19+ERP-3`:资产台账摘要导出协议
## 3. IM / 协同适配边界
### 3.1 允许能力
- 飞书 / 企微消息通知
- 待办提醒
- 深链跳转(例如采购审批详情、资产盘点详情)
- 审批摘要的只读推送
### 3.2 边界约束
- IM 适配器只消费领域事件,不直接读取或修改数据库。
- IM 适配器可以构造消息文案、跳转链接、卡片摘要,但不能替代工作流审批判定。
- 任何“点击消息即审批”的能力,必须仍然回到 `hyb-oa` 的鉴权与工作流接口执行。
### 3.3 禁止事项
- 禁止把 IM 用户标识写入核心审批流状态字段。
- 禁止在 IM 侧持久化领域真相状态并反向覆盖业务库。
## 4. AI 增强边界
### 4.1 允许能力
- 审批摘要生成
- 采购/资产异常提示
- 主数据重名与重复建议
- 文档/制度/流程问答检索
### 4.2 强制约束
- AI 只做建议,不直接写库。
- AI 输出必须允许人工复核和拒绝。
- 任何模型调用都不得绕过现有权限校验。
- 若未来接入外部大模型,必须先明确脱敏策略与日志留存边界。
### 4.3 禁止事项
- 禁止 AI 自动创建、审批、归档业务单据。
- 禁止 AI 直接修改预算、工作流、资产归属等核心状态。
## 5. 领域事件交付规范
### 5.1 事件最小结构
后续若引入事件投递,建议统一包含:
- `eventName`
- `eventId`
- `occurredAt`
- `actorId`
- `entityType`
- `entityId`
- `payloadVersion`
- `payload`
### 5.2 幂等要求
- 同一 `eventId` 必须可安全重放。
- 消费端必须以 `eventId` 或 `entityId + status/version` 方式做幂等。
- 不允许消费端以“收到多次事件”为理由修改核心业务状态。
## 6. MCP 基线
### 6.1 当前结论
- `P19` 阶段 **不启用 MCP**。
- 当前仓库中 **不创建** `docs/mcp-tools.md`,因为尚未进入实际 MCP 使用场景。
### 6.2 首次启用前置条件
若未来需要启用 MCP,固定顺序如下:
1. 明确真实用途(数据库只读排障、GitHub PR/Issue/CI 协作等)
2. 新增 `docs/mcp-tools.md`
3. 使用 `mcp-tools-catalog` 生成工具目录
4. 在执行合同中记录启用原因、风险与禁用边界
### 6.3 允许的 MCP 范围
- `postgres MCP`:只读排障、迁移核对、账本核对
- `github MCP`:PR / Issue / CI 协作
### 6.4 禁止事项
- 禁止在没有 `docs/mcp-tools.md` 的前提下默认启用 MCP
- 禁止用 MCP 绕过仓库内已存在的本地验证命令
- 禁止将 MCP 用作写生产数据的通道
## 7. 本阶段明确不做
- 不实现 Outbox 表
- 不新增对外 webhook
- 不接入 ERP、飞书、企微或大模型 SDK
- 不修改任何路由、Prisma 模型、前端页面和工作流逻辑
## 8. 下一步专项建议
- 若优先打通 ERP,请先开“主数据同步协议”专项
- 若优先做协同体验,请先开“IM 待办通知”专项
- 若优先做智能化,请先开“审批摘要与异常提示”专项