文件
hyb-oa/docs/integration-boundaries.md
T

290 行
24 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# 集成边界冻结(P19 / P19+IM-1 / P19+ERP-3 / R10 / P19+MCP-1 / P19+AI-1 / P20+TRAVEL-1 / P20+TRAVEL-2 / P20+TRAVEL-3 / P21+PWA-1 / P21+PWA-2)
**快照日期**:2026-03-12
**当前基线**:`P19+IM-1`、`P19+ERP-1`、`P19+ERP-2`、`P19+ERP-3`、`P19+MCP-1`、`P19+AI-1`、`P20+TRAVEL-1`、`P20+TRAVEL-2`、`P20+TRAVEL-3`、`P21+PWA-1` 与 `P21+PWA-2` 已完成;当前运行时已落地企微群机器人 + 深链 + Outbox 异步派发的一期协同适配,以及 ERP 主数据 Pull、报销付款凭证切片、采购双阶段 journal / 归档摘要出站、资产台账摘要出站、Postgres MCP 只读工具基线、报销 / 采购 / 资产详情页 AI 只读建议挂件、差旅申请主单 / 行程段 / 审批预算锁定 / `travel_orders` 关联入站、混合双轨对公支付闭环与批次级对账摘要桥的三期差旅基线,以及浏览器 PWA 下的移动资产扫码、盘点快捷录入与离线队列重放、移动审批 deep link 直达、本地会话快照离线守卫与审批草稿重放。
**目标**:在保持核心域稳定的前提下,冻结 ERP / IM / AI / MCP / TRAVEL / PWA 的长期边界,并记录 IM 一期、ERP 三期、AI 一期、差旅三期与 PWA 两期的已实现范围、禁入规则以及 R10 主线闭环后的固定收口结论。
## 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
- **失败处理**:
- 在适配层重试
- 失败记录在适配层日志 / Outbox 中,不回写核心事务状态为“失败”
### 2.3 明确禁止事项
- 禁止在 `PurchaseRequest`、`AssetCard`、`BudgetPool` 等核心表中直接加入 ERP 专有主键、分录号、凭证表字段。
- 禁止应用直接连写 ERP 主表。
- 禁止把 ERP 状态机复制到 `hyb-oa` 核心路由中。
### 2.4 建议后续专项
- `P19+ERP-1`:主数据同步协议
- `P19+ERP-2`:采购双阶段 journal 与归档摘要出站
- `P19+ERP-3`:资产台账摘要导出协议(已完成一期)
### 2.5 P19+ERP-1 已实现范围
- 已新增 `IntegrationBinding` 与 `IntegrationSyncState` 两张集成层私有表,用于维护 ERP 映射与同步状态,不向核心事务表注入 ERP 私有字段。
- 已实现 `LegalEntity`、`CostCenter`、`Supplier` 的 ERP 全量 Pull,同步方式固定为 `manual + cron`;其中 `ERP_MASTER_DATA_SYNC_CRON` 为空时不自动调度。
- 已实现 `reimbursement.paid` 的标准化凭证切片导出,运行时通过 `erp.journal.export` 写入 `IntegrationOutbox` 并由 dispatcher 异步派发。
- 已兼容保留历史 `erp.reimbursement.paid` 派发路径;成功导出后统一回写 `integration_bindings(provider=erp, entity_type=reimbursement_journal)`。
- 已明确 `ERP_SYNC_ENABLED` 与 `erp_sync` feature flag 共同构成 ERP 管理端总闸,任一关闭都必须阻断主数据同步与手动导出。
### 2.6 P19+ERP-2 已实现范围
- 已冻结采购双阶段财务语义:`purchase_request.approved` 自动生成 `purchase_request_commitment` journal,`purchase_order.archived` 首次归档自动生成 `purchase_order_accrual` journal。
- 已新增 `erp.procurement.export` 用于 `purchase_order_archive` 摘要出站;commitment / accrual 仍统一复用 `erp.journal.export`,避免额外拆分出站总线。
- 已为 `purchase_order_archive` 建立“同一条 outbox 覆盖同步”语义:当 `poNo` / `contractNo` / `archivedFiles` 变化时,仅重置 summary 对应 outbox 并覆盖 payload,不重复创建 accrual journal。
- 已在 `integration_bindings` 中落地采购映射:`purchase_request_commitment_journal`、`purchase_order_accrual_journal`、`purchase_order_po`、`purchase_order_contract`;成功派发后回写 ERP 外部编号与最近同步时间。
- 已明确 `IntegrationSyncState` 继续只表示资源级主数据同步状态,不承载采购单据级轨道;采购详情轨道只允许由 `IntegrationOutbox + IntegrationBinding + 当前单据事实` 推导。
- 已将采购 ERP 轨道挂件固定在采购详情 / 归档区:所有可读用户仅查看阶段状态,`integration.manage` 才能查看 ERP 外部编号并执行手动补发 / 重试。
### 2.7 P19+ERP-3 已实现范围
- 已新增 `erp.asset.export` 单一资产 ERP 事件,固定用于 `asset_card` 的 ledger summary export,不进入 `erp.journal.export`,也不向核心资产表注入 ERP 私有字段。
- 已冻结资产一期触发边界:仅 `POST /api/assets` 建卡成功,以及 `PATCH /api/assets/:id` 导致 `legalEntityId / costCenterId / status(retired|archived)` 发生变化时自动出站。
- 已明确 `POST /api/assets/:id/assign`、`POST /api/assets/:id/return`、`POST /api/assets/:id/transfer` 与仅 `name / location / serialNo / activatedAt` 变化不触发 ERP,同步边界仅覆盖财务台账摘要。
- 已为单资产固定 `asset_card:{assetId}:ledger_summary` dedupe key,并采用“同一条 outbox 覆盖同步”语义:payload 无变化时返回历史记录,payload 有变化或失败 / 死信时仅重置同一条记录。
- 已在 `integration_bindings` 中固定资产映射 `asset_erp_card`;成功派发后回写 ERP 资产外部编号与最近同步时间。
- 已将资产 ERP 轨道挂件固定在资产详情侧边栏:所有可读用户查看同步状态,`integration.manage` 才能查看 ERP 外部编号并执行补发 / 重试;`IntegrationSyncState` 继续不承载资产单据级轨道。
## 3. IM / 协同适配边界
### 3.1 一期已实现能力(P19+IM-1)
- 已复用 `IntegrationOutbox` 与派发作业,实现 `notification.im` 异步派发。
- 已新增 `NotificationChannel` 的创建 / 更新 / 列表 / 测试接口与后台页面。
- 已接入企微群机器人两种模式:
- `mock`
- `wecom_webhook`
- 企微 `wecom_webhook` 已补齐生产化护栏:Webhook Secret 加密存储、遮罩回显、测试接口诊断与迁移脚本。
- 已支持三维路由过滤:
- `roleCodes`
- `domainScopes`
- `allowedTypes`
- 已支持 `APP_ORIGIN + targetPath` 生成深链;缺少 `APP_ORIGIN` 时允许发送但不阻断业务。
- 站内通知、邮件、IM 三通道并存;业务事务内只负责写通知与 Outbox,真正派发在作业中完成。
### 3.2 一期明确覆盖范围
- 待办类:`workflow.task_assigned`
- 报销结果:`reimbursement.approved / rejected / returned / paid`
- 请假结果:`leave.approved / rejected`
- 采购结果:`purchase_request.approved / rejected`
- 资产流转:`asset.assigned / returned / transferred`
- 盘点结果:`inventory_check.completed`
### 3.3 一期明确不做
- 飞书、钉钉真实适配器
- 员工 IM OpenID / UserID / UnionID 主数据
- 点对点个人消息
- IM 卡片回调审批
- 新的 Outbox 表或消息总线
- 默认全员广播频道
### 3.4 运行时回滚策略
- 设置 `IM_NOTIFIER_ENABLED=false`
- 在管理页中禁用全部通知渠道
- 保留 `integration_outbox` 历史记录,不回删
- 即使 IM 全部关闭,站内通知与邮件仍继续工作
### 3.5 后续专项建议
- `P23+IM-2`:真实 IM 适配器 refresh;已完成企微 webhook 生产化,飞书 / 钉钉 provider 继续 backlog
- `P19+IM-3`:个人直达与 IM 身份映射
- `P19+IM-4`:消息卡片交互与回调审批(仍必须回到 OA 鉴权)
## 4. AI 增强边界
### 4.1 允许能力
- 审批摘要生成
- 采购 / 资产异常提示
- 主数据重名与重复建议
- 文档 / 制度 / 流程问答检索
### 4.2 强制约束
- AI 只做建议,不直接写库。
- AI 输出必须允许人工复核和拒绝。
- 任何模型调用都不得绕过现有权限校验。
- 若未来接入外部大模型,必须先明确脱敏策略与日志留存边界。
### 4.3 禁止事项
- 禁止 AI 自动创建、审批、归档业务单据。
- 禁止 AI 直接修改预算、工作流、资产归属等核心状态。
### 4.4 P19+AI-1 已实现范围
- 已新增 `GET /api/ai/status` 与三条详情建议接口:`/api/ai/suggestions/reimbursements/:id`、`/api/ai/suggestions/purchase-requests/:id`、`/api/ai/suggestions/assets/:id`。
- 已新增 `ai.assist` 权限、`ai_assist` feature flag 与 `AI_ASSIST_ENABLED / AI_PROVIDER / AI_BASE_URL / AI_MODEL / AI_TIMEOUT_MS / AI_AUTH_TOKEN` 环境变量;默认仍保持关闭。
- 已固定 AI 运行时只支持同步只读建议层,不新增 Prisma 表、不使用 Outbox、不接入 MCP 运行时,也不持久化 AI 历史结果。
- 已固定只读白名单快照:报销不暴露发票号码、付款凭证、姓名工号与明细原文;采购不暴露申请人个人信息、附件原名、长文本 reason 与外部 ERP 编号;资产不暴露 assignee 身份信息与外部 ERP 编号。
- 已在报销详情、采购详情、资产详情挂载 AI 建议卡片;当权限不足、总闸关闭、feature flag 未命中、上游超时或响应非法时,仅在卡片内降级展示,不影响主体页面渲染与业务动作。
- 已固定审计动作 `AI_SUGGESTION_REQUESTED`,仅记录 `targetType / targetId / provider / model / promptHash / tokenUsage / featureFlag`,不记录原始 prompt、脱敏前 payload 或上游全文。
## 5. 差旅边界
### 5.1 P20+TRAVEL-1 已实现范围
- 已新增 `TravelRequest`、`TravelRequestSegment` 与 `travel_orders.travel_request_id`,形成“差旅申请主单 + 行程段明细 + 外部订单事实关联”的一期差旅模型。
- 已固定独立 `travel.*` 权限命名空间,并将 `travel_request` 纳入工作流实体映射、待办页、移动审批与通知深链 `/travel-requests?id=<id>`。
- 已固定差旅一期持久状态仅 `draft / reviewing / approved / rejected`;`return` 与 `withdraw` 均回到 `draft`,释放预算并允许修改后重提。
- 已复用预算三段语义:提交 `reserve`、审批通过 `confirm`、驳回 / 退回 / 撤回 `release`;预算池由 `legal_entity_id + cost_center_id + start_date` 自动解析。
- 已固定一期工作流为直属经理单层审批,并把审批通过 / 驳回结果分别映射到 `travel_request.approved`、`travel_request.rejected` 通知类型。
### 5.2 差旅一期明确不做
- 不创建 `travel_request_commitment` journal,不写 `IntegrationOutbox`,不提前进入 `erp.travel.export`。
- 不接真实票务 / 酒店 / 商旅供应商 API,不做自动出票、改签、退票。
- 不做企业卡授权、交易导入、对公支付与清结算,这些能力继续固定在 `P20+TRAVEL-2` / `P20+TRAVEL-3`。
- `travel_order.imported` 当前仍只是内部集成事实与入站表更新,不提升为稳定公共事件名。
### 5.3 P20+TRAVEL-2 已实现范围
- 已新增 `CardAuthorization`、`CardTransaction`、`travel_orders` 支付字段与 `invoice_pool.travel_order_id`,形成“申请预算轨 + 企业卡支付轨 + 手工结算入口”的混合双轨模型。
- 已新增 `travel.payment.manage` 权限,以及 `GET /api/travel/authorizations`、`POST /api/travel/authorizations/import`、`GET /api/travel/transactions`、`POST /api/travel/transactions/import`、`POST /api/travel/transactions/:id/freeze-suggestion`、`POST /api/travel-orders/:id/mark-paid`、`GET /api/travel-requests/:id/payment-track`。
- 已固定 `travel_request` 申请预算语义继续停留在 `reserve / confirm / release`;`TRAVEL-2` 新增支付预算语义 `authorize / settle / reverse`,实体维度分别落在 `card_authorization` 与 `card_transaction`。
- 已固定 `charge + settled + 金额币种精确匹配` 才能把 `TravelOrder` 从 `imported` 推进到 `confirmed`;`mark-paid` 只允许 `confirmed -> paid` 或同 payload 幂等重放,不回改差旅申请审批状态。
- 已固定 `travel_order.paid` 为本期唯一新增稳定公共事件名,并在 `erp_sync` 总闸开启时直接复用 `erp.journal.export` 出站 `travel_order_payment` journal;发票仅绑定到订单,默认不自动归档,AP 摘要与核销仍留给 `TRAVEL-3`。
### 5.4 差旅二期明确不做
- 不接真实商旅供应商 API,不做出票、改签、退票、拒付、退款回调或银行清结算。
- 不把 `travel_request.approved -> budget confirm` 的申请预算语义后移到支付阶段。
- 不在 `TRAVEL-2` 提前实现 AP 摘要桥接、核销批次、requeue / dead-letter 运营面板;这些能力继续固定在 `P20+TRAVEL-3`。
- `card_authorization.imported`、`card_transaction.imported`、`card_transaction.reversed` 当前仍只作为内部导入事实与支付轨道明细,不提升为稳定公共事件名。
### 5.5 P20+TRAVEL-3 已实现范围
- 已新增 `TravelReconciliationBatch` 与 `TravelReconciliationItem`,固定采用“批次快照 + 明细快照”持久化结构;人工确认、ERP 出站、track / requeue 都基于 batch,而不是 request-level 运行时即席对比。
- 已固定 `TRAVEL-3` 只覆盖 `TravelOrder.status = paid` 的统付订单、同范围 `CardTransaction.status in (settled, reversed)` 的支付交易,以及不落在本批次范围内的 `orphan transaction`;`linked_reimbursement_id` 仅作为只读快照上下文保留。
- 已新增 `/api/travel/reconciliation/batches`、`/api/travel/reconciliation/items/:itemId/confirm|reopen`、`/api/travel/reconciliation/batches/:batchId/finalize`,并固定 `matched` 项自动确认、其余 anomaly 必须人工确认后才能把 batch 从 `draft` 推进到 `reconciled`。
- 已新增批次级集成事件 `erp.travel.export`,在 `erp_sync` 总闸开启且 batch 已 `reconciled` 时,按 `travel_reconciliation_batch:<batchId>:summary` dedupe key 出站 AP/对账摘要;成功派发后统一沉淀 `travel_payable_summary` 与 `travel_settlement_batch` 两类 binding。
- 已把前端入口固定在 `/travel-requests?tab=reconciliation&batchId=<id>`,在同一路径下展示 KPI、异常明细、人工确认与 ERP 轨道,不新增独立差旅对账路由。
### 5.6 差旅三期明确不做
- 不自动修正 `TravelOrder.amount/status`、不自动改 `TravelRequest`、不自动改预算账轨;对账只做差异发现与人工接受,不做自动修复。
- 不把 `travel_order_payment` journal 并入 `erp.travel.export`;`TRAVEL-2` 的订单支付出站继续保留,`TRAVEL-3` 只新增批次级 AP/对账摘要桥。
- 不做真实商旅供应商清结算、拒付、退款回调、税分摊、复杂票规,也不新增 workflow 审批实例。
- 若源数据变化,只允许新建下一批 reconciliation batch,不回刷已 finalized 的历史批次快照。
### 5.7 P21+PWA-1 已实现范围
- 已新增 `/mobile/assets/scan`、导航入口与 `MobileAssetScanPage`,固定采用“相机扫码 + 手工输入兜底”的移动资产查找体验,不新增独立原生壳或平台私有 SDK。
- 已固定扫码引擎优先使用浏览器 `BarcodeDetector`,不支持时回退到 `@zxing/browser`;相机不可用时仍允许通过 `assetNo / serialNo / name` 手工检索。
- 已对现有 `GET /api/assets` 做最小扩展,新增 `q` 查询参数;匹配规则固定为 `asset_no` 精确匹配、`serial_no` 精确匹配、`name contains` 兜底模糊匹配,继续沿用现有资产读权限与 `mine` 语义。
- 已把盘点录入固定在 `inventoryCheckId` 上下文内复用现有 `fetchInventoryChecks / startInventoryCheck / recordInventoryItems`,实现 `draft -> start`、`counting -> record`、`completed -> readonly` 三态,不新增移动专用后端协议。
- 已新增 `IndexedDB` 离线队列,仅缓存“已解析出 `assetId` 的盘点结果”;联网后自动或手动重放,且以 `inventoryCheckId + assetId` 做 last-write-wins 去重。
### 5.8 P21+PWA-2 已实现范围
- 已保持 `workflow.task_assigned` 的 canonical `targetPath = /workflow/tasks/:taskId` 不变,并在客户端补齐移动 / PWA / IM WebView 环境下的自动兜底跳转:命中移动规则时统一落到 `/mobile/approvals?taskId=<id>`。
- 已为移动审批补齐 `taskId` deep link 模式:待办即使不在第一页列表中,也可单独拉取详情;离线时若该待办曾被本地缓存,则允许直接在移动审批页内查看与起草草稿。
- 已新增仅含 `me + permissions + savedAt` 的本地会话快照,不持久化 access token;离线冷启动时只允许 `/mobile/approvals` 与 `/workflow/tasks/:taskId` 两类路径进入壳页面。
- 已新增 `approve / reject` 审批草稿队列,采用 `taskId` 级 last-write-wins 去重;恢复联网后支持自动或手动重放,并把 `already_processed` / 403 / 404 明确标记为冲突态。
- 已升级 `vite-plugin-pwa` 的 runtime cache:静态资源使用 `StaleWhileRevalidate`,审批相关 GET API 使用 `NetworkFirst`,导航仍通过 `navigateFallback=/index.html` 回到 SPA 壳。
### 5.9 PWA 二期明确不做
- 不做飞书 / 钉钉真实消息适配器、JS-SDK、开放平台回调审批;本期企微只承接群机器人 webhook 出站,不引入消息卡片与回调审批。
- 不做 Background Sync、Push、原生 App、小程序、双栈移动壳,也不把审批动作 POST 请求交给 Service Worker 代理。
- 不做完整离线登录、全量待办镜像、复杂冲突合并或离线自动修复;未缓存的待办详情离线仍要求联网重试。
- 不改写现有 workflow 动作 API,不给 `approve` 新增 comment,也不把 `return / transfer` 纳入离线草稿范围。
## 6. 事件与通知交付规范
### 6.1 事件最小结构
后续若继续扩展领域事件 / Outbox,建议统一包含:
- `eventName`
- `eventId`
- `occurredAt`
- `actorId`
- `entityType`
- `entityId`
- `payloadVersion`
- `payload`
### 6.2 幂等要求
- 同一 `eventId` 必须可安全重放。
- 消费端必须以 `eventId` 或 `entityId + status / version` 方式做幂等。
- 不允许消费端以“收到多次事件”为理由修改核心业务状态。
### 6.3 当前 IM 一期实现说明
- 运行时仍以通知类型驱动 IM 入队,而不是直接暴露新的领域事件名。
- `notification.im` 的 `dedupeKey` 固定为:
- `${notificationType}:${targetType}:${targetId || targetPath}:${channelId}`
- IM 失败仅影响 Outbox 状态,不回滚业务事务。
## 7. MCP 基线
### 7.1 P19+MCP-1 已实现范围
- 已新增 `docs/mcp-tools.md`,作为项目级 MCP 工具目录与使用边界事实源。
- 已新增 `.mcp.json.example`,仅提供 `postgres` 只读示例配置,不提交任何真实密钥、PAT 或数据库连接串。
- 已新增 `scripts/validate-mcp-tools.py`,用于校验工具目录、示例配置与 `AGENTS.md` 引用关系。
- 已明确当前 shell 中 `codex mcp list --json` 不可作为唯一事实源,因此工具目录固定以官方 package 文档、执行合同与仓库校验脚本共同收口。
### 7.2 当前允许的 MCP 范围
- `postgres MCP`:当前唯一允许启用的 MCP server,用于只读排障、迁移核对、账本核对。
- `postgres:query`:固定用于只读 SQL 查询;所有查询必须处于 `READ ONLY` 事务语义下。
- schema resources:允许读取表结构、字段类型与 schema 元数据,不得反向修改业务数据。
### 7.3 Deferred candidate
- `github MCP`:当前仅记录为 deferred candidate,不纳入 enabled servers。
- 原因:官方 GitHub MCP server 当前暴露读写混合工具集,不满足 `Read-only Tools Baseline`。
- 若未来需要启用,必须通过新的路线合同显式解锁,并单独治理最小权限 PAT、读写边界与回滚策略。
### 7.4 禁止事项
- 禁止提交真实 `.mcp.json`、真实数据库连接串、PAT、API Token 或其他密钥。
- 禁止在没有 `docs/mcp-tools.md` 的前提下默认启用 MCP。
- 禁止用 MCP 绕过仓库内已存在的本地验证命令。
- 禁止将 MCP 用作写生产数据或修改业务状态的通道。
## 8. 当前阶段明确不做
- 不新增新的集成总线表结构
- 不接入 ERP 真实写回逻辑
- 不接入飞书 / 钉钉真实生产推送
- 不新增 AI 写库动作
- 不引入绕过工作流与权限体系的外部回调路径
## 9. R10 后续路线冻结
### 9.1 固定主线顺序
- `P21+PWA-2` 已完成后,`R10` 主线正式闭环;后续若进入新阶段,必须通过新的路线合同显式启动。
- 历史主线顺序保持为:`P19+MCP-1 -> P19+AI-1 -> P20+TRAVEL-1 -> P20+TRAVEL-2 -> P20+TRAVEL-3 -> P21+PWA-1 -> P21+PWA-2`。
- 后续阶段继续遵循“先治理,再工具,再建议,再业务,再移动”的总顺序,不并行开启两个重业务 phase。
- 每个 phase 固定遵循:`执行合同 CSV -> 方案批准 -> 开发 -> 测试 -> 文档矩阵收口 -> 合并 main`。
### 9.2 MCP / AI 前置关系
- `P19+MCP-1` 已完成,并已把 `docs/mcp-tools.md`、`.mcp.json.example` 与 MCP 校验脚本固化为仓库治理基线。
- 当前唯一允许启用的 MCP server 为 `postgres`;`github` 继续保持 deferred,不进入 enabled servers。
- `P19+AI-1` 已在 `P19+MCP-1` 之后完成落地,并继续遵守“AI 只做建议,不直接写库”的硬边界。
- 当前 AI 一期已覆盖采购、报销、资产详情的只读建议工作台;自由聊天、自动审批与 agent 自治仍明确不做。
### 9.3 差旅统付主线
- `P20+TRAVEL-1` 已完成差旅申请、行程段、审批预算与 `travel_orders` 入站整合,作为对公统付的前置流程基线。
- `P20+TRAVEL-2` 固定采用企业卡 / 虚拟卡授权与交易导入路线,优先复用 `docs/adr/adr-enterprise-card-control.md` 的既有结论。
- `P20+TRAVEL-3` 固定负责核销闭环与 ERP / AP 摘要桥接;个人垫资报销继续与对公统付并存,不互相替代。
### 9.4 PWA 兑现顺序
- `P21+PWA-1` 已完成移动资产扫码与盘点增强,优先兑现一线资产作业的生产价值,并固定采用浏览器 PWA + 离线队列重放路线。
- `P21+PWA-2` 已完成移动审批 deep link、离线守卫、本地草稿重放与缓存策略升级,继续复用现有 `APP_ORIGIN + targetPath` 深链规范且不改写服务端通知协议。
- PWA 路线已按浏览器 / PWA 栈闭环,不引入原生 App、小程序或双栈移动壳。
### 9.5 后置 backlog
- `P23+IM-2` 已完成企微真实 webhook 出站;飞书 / 钉钉 provider 子项与 `IM-3 / IM-4`、`P22+VEH-1`、`P22+ASSET-FIN-1` 继续作为后置 backlog。
- 这些方向只保留“触发条件 / 进入时机”的规划地位,不提前写入已完成矩阵或事实源校验器。
- 若后续优先级发生变化,必须通过新的路线合同显式改序,不直接口头跳 phase。