Files
xiaoqu_mcp_service/xiaoqu-agent-service/doc/crm-sync-integration-progress.md
T

126 lines
8.7 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.
# SaaS MCP → 小趣 AI 经营系统对接进度
> MCP 系统独立进度入口。最后核对:2026-09-15;代码基线:`76d461a`。
>
> 本文只记录 `xiaoqu_mcp_service` 的责任和状态。小趣 AI / CRM 的规则、事项、AI、页面与推送进度,以其仓库 `PROJECT.md` 为准。
## 1. 两个系统的边界
| 系统 | 必须负责 | 明确不负责 |
|---|---|---|
| SaaS MCP | 服务身份、源租户/数据域、工具授权、源系统行级权限、用户/物业/合同标准变化流、稳定游标、审计与标准错误 | 到期规则、经营优先级、AI决策、经营事项状态机、销售页面、APNs推送 |
| 小趣 AI / CRM | 租户连接、数据镜像、身份与客户映射、确定性规则、仅把命中数据交给AI、事项生成/流转、展示、操作、反馈、推送前复核 | 猜测源租户、绕过MCP权限、兼容不符合冻结Schema的错误字段 |
双方唯一连接面是版本化接口契约:`integration.context.get`、三条 `*.changes.list`、统一错误信封,以及真实端到端验收。任何一侧内部实现都不能成为另一侧的隐式依赖。
## 2. 当前结论
当前状态:**协议可连接,业务契约未通过,不能用于真实销售合同到期推送。**
已经具备:
- MCP Streamable HTTP 会话、SSE响应和Schema v2信封。
- `X-Open-Key` 管理、服务Token签发、Token作用域、工具白名单、审计和限流。
- `integration.context.get`。
- `users.changes.list`、`properties.changes.list`、`contracts.changes.list`及统一分页框架。
- 基于 `(modify_time, id)` 的分页、软删标记、错误码和基础单元测试。
尚未通过的不是“小趣AI页面问题”,而是MCP公开数据契约与可靠同步语义。小趣AI侧不得通过放宽校验来掩盖这些问题。
## 3. 已确认问题与处理顺序
### P0-1 服务身份没有绑定真实源租户
现状:`integration.context.get.tenant_id`由作用域编码拼接得到,`sync`被当成租户;服务Token又按`serviceName + scope`全局复用,创建它的Open Client身份没有进入Token。作用域代表“能用什么工具”,不是“属于哪个租户/数据域”。
影响:不能证明某个小趣租户连接的是哪个SaaS数据域,也不能可靠阻止不同接入方复用同一服务身份。
标准改造:
1. 为Open Client建立不可变的`source_tenant_id`(或等价数据域ID)绑定,不从请求体、scope或名称推断。
2. 服务Token持久化`open_client_id + source_tenant_id + subject_name`,ensure按该组合幂等签发。
3. `integration.context.get.tenant_id`返回真实`source_tenant_id`;`subject_id`返回稳定服务主体ID。
4. 每条SYNC查询都从鉴权上下文取得该数据域并强制过滤;若当前源库确实只有单一数据域,也必须以明确配置和测试证明,不能用“user为空即查全库”表达。
验收:两个Open Client即使使用相同`serviceName=crm`也得到不同服务Token和租户上下文;跨租户数据为零;吊销其中一个不影响另一个。
### P0-2 三条变化流不符合冻结字段Schema
现状与冻结契约的差异:
| 流 | 当前输出 | 必须输出 |
|---|---|---|
| users | `mobile`;数值型`user_id/organization_ids` | `verified_mobile`;字符串型稳定ID;状态使用公开枚举 |
| properties | 数值型`property_id` | 字符串型稳定ID;状态使用公开枚举 |
| contracts | 数值型`contract_id/property_id/owner_user_id`、数值状态`0..4`、数值`expire_remind`,缺`remind_days` | 字符串型稳定ID、`PENDING/REJECTED/ACTIVE/EXPIRED/TERMINATED/VOID`、布尔提醒标记、实际提醒天数 |
影响:小趣Gateway的严格Schema校验会正确拒绝当前users和contracts数据;合同不会进入镜像、规则和推送链路。
标准改造:在MCP边界使用独立DTO/枚举映射,将老库字段一次性转换成公开Schema;公开契约不得直接泄漏数据库整数状态和Java实体类型。没有权威来源的可选字段保持空,不伪造。
验收:用真实样例对三条流执行消费者契约测试;Gateway无需兼容代码即可全部通过,未知字段、未知状态和错误类型必须失败。
### P0-3 当前“快照”不能保证重放稳定
现状:令牌只保存`cutoff`,每页仍直接查询持续变化的业务表。分页期间,`cutoff`之前的记录被修改、删除或权限变化时,相同`sync_token + cursor + limit`可能得到不同结果;秒级`modify_time`也可能漏掉同一行在边界秒内的再次修改。
影响:合同规模扩大或同步期间发生业务写入时,存在漏数、重复、记录消失和重放不一致风险,达不到文档声称的“不重不漏”。
标准改造:建立通用变更日志/Outbox(每次变更拥有单调递增`change_seq`,保存实体ID、操作类型、版本和必要投影),同步窗口按`change_seq`冻结;游标按`change_seq`推进。若使用CDC,也必须落成可保留、可重放的变化流,不能直接分页扫活表冒充快照。
验收:同步中并发更新、删除、负责人变更、权限变更以及相同请求重放时,旧快照结果不变,新变化只进入下一轮;压测覆盖成千上万合同。
### P0-4 交接Token错误复用了24小时快照TTL
现状:轮内快照Token、页游标和已完成轮的`next_sync_token`统一执行24小时TTL。
影响:每日任务只要稍晚、停机或积压,就可能被迫全量重建;数据量增大后会形成周期性全量压力。
标准改造:只给轮内快照/游标设置短TTL;交接Token按变更日志保留期校验,或保存持久化消费位点。过期时返回可观测的最早可用位置及标准错误,消费者执行受控重建。
验收:间隔超过24小时仍可正常增量;只有位点早于服务端保留期才触发重建。
### P0-5 数据权限版本不能覆盖真实权限变化
现状:`data_scope_version`仅取`token_scope`关系的修改时间;Open Client租户绑定、scope-tool变化、源数据域ACL变化不会稳定反映。
影响:权限变化后旧同步位点可能继续使用,消费者无法判断需要重建或停止派发。
标准改造:维护数据域授权版本,任何租户绑定、工具授权、行级ACL语义变更都原子递增;上下文与同步Token使用同一个版本。
验收:修改任一影响可见数据的授权后,旧轮立即失败关闭,新轮在新数据域版本下重建。
## 4. 依赖顺序
1. 冻结真实`source_tenant_id`来源、数据域范围和合同状态/提醒字段字典。
2. 完成服务身份与源租户持久化模型,补迁移、后台配置、ensure和上下文测试。
3. 建立通用变更日志/Outbox与保留策略,再迁移三条变化流;不继续强化活表分页方案。
4. 使用独立公开DTO完成三条流字段映射和消费者契约测试。
5. 修正交接Token生命周期与统一数据权限版本。
6. 在测试环境用真实用户、物业、合同及变更/删除数据完成MCP侧验收。
7. 交付Open Client、真实源租户ID和凭证给小趣AI侧,联合验证“同步→映射→规则→事项→展示→推送前复核”。
## 5. 状态看板
| 工作项 | 状态 | 责任系统 | 下一步 |
|---|---|---|---|
| MCP协议与工具发现 | 已完成 | MCP | 保持兼容并纳入回归 |
| 服务密钥与Token基础生命周期 | 已完成 | MCP | 在租户模型完成后升级幂等键 |
| 真实源租户与服务主体隔离 | 未完成,P0阻塞 | MCP | 明确权威租户来源并设计迁移 |
| 三流公开字段Schema | 未完成,P0阻塞 | MCP | 建立DTO和状态字典,跑消费者契约测试 |
| 可靠变化日志与稳定快照 | 未完成,P0阻塞 | MCP | 设计Outbox/CDC及保留策略 |
| 权限版本与交接位点生命周期 | 未完成,P0阻塞 | MCP | 与租户/变化日志模型一起实现 |
| 小趣AI连接与消费代码 | 已完成,待部署联调 | 小趣AI | 见小趣AI仓库`PROJECT.md` |
| 真实销售合同到期推送 | 未开放 | 双方联合验收 | 所有P0通过后才允许从Shadow转Live |
## 6. 发布门禁
以下条件全部满足前,不得把MCP同步标记为生产可用,也不得向真实销售发送合同提醒:
- 真实源租户隔离、服务主体隔离和跨租户反向用例通过。
- 三条变化流通过冻结Schema及真实数据样例校验。
- 并发写入、删除、断点续传、超过24小时续传和权限变化测试通过。
- 凭证不入库明文、不入日志;轮换和吊销测试通过。
- 小趣AI侧完成负责人、客户双映射和发送前实时复核。
- 完整链路具有`request_id/snapshot_id/source_tenant_id`审计证据,可定位每条事项和推送的数据来源。