Files
ai_site/松离线-dbsync方案-最终版.md
whm b04b180d30 feat: harden loose-offline sync for user JWT, schema, and console ops
Enable Binding-scoped agent push/pull, empty-table schema ensure, SyncPage inspect/drop-table, default module import, and agent-bound publish docs from the 宇恒联调意见.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 09:47:35 +08:00

13 KiB
Raw Blame History

松离线 + dbsync 方案 · 最终版(冻结)

效力:本文为双方协商后的唯一开工依据
原方案稿 / 审评追加 / 决议草稿见同目录 松离线-dbsync方案.md(过程稿,不再改口径)。
冻结日期2026-07-31


0. 一句话

技术:松离线写本地 B最终 UUID+ 本机 agent 经 dbsync 幂等对齐线上 A冲突自动 LWW落败入平台超级管理员覆盖日志。
产品:宇恒默认零影响;仅显式 local_dbsync + 表白名单 opt-inM4 前不对全员切默认。


1. 硬约束(不可回退)

# 约束
H1 未开通同步的用户:保存 / 自增表 / 插件行为与现网一致(行为 diff = 0
H2 默认不得自动升为 local_dbsync
H3 agent 停运不得导致 apply_write / 保存失败;心跳只驱动 UI
H4 默认建表模板保持自增;仅「同步表模板」为 UUID
H5 online_primary 客户禁止静默关双写;仅新客或显式迁移客评估切换
H6 未开通用户零同步文案(无强制状态条、无「已自动合并」)

2. 架构定案

定案
离线 松离线:开通且白名单表 → 本地正式库落最终 UUID立刻可见
同步 接法① dbsync(非 HTTP 双写主路径)
通道形态 B 本机 sync agent(平台不直连用户 SQLite
首期方向 B→A;双向另开,默认关
冲突 自动 LWW;首期投递以 outbox 单调 version 为主,偏源(本机推上)时覆盖目标并记审计
落败追溯 LWW 自动覆盖日志仅平台超级管理员;公司 top 403;建议 TTL 90 天
终端冲突 UI 不做
形态 A / CRDT / 对账替代 UUID 不做
[开通 + 白名单表]
  业务写 ──► BUUID──► outbox ──► 本机 agent ──► Aingest/upsert
  UI仅本机 / 待同步 / 已同步(不影响保存成败)

[未开通]
  现网路径不变local_only 或 online_primary

3. 模式三分(宇恒)

模式 含义 默认
local_only 只写本地 可作默认之一
online_primary 现网 HTTP 双写 / 离线 pending 已上线客户保留
local_dbsync 松离线 + agent 仅显式配置
  • 未配置 / 未识别 → 不得当成 local_dbsync
  • 互斥粒度(定案 O6同一张表不可同时走 online_primary 双写与 local_dbsync同一库允许部分表白名单走 local_dbsync,其余表保持该库原模式写本地(不强制整库切模式)。

4. 白名单(定案 O1 / O2

定案
源 of truth 智建通道配置
宇恒 本地缓存副本;拉取前 / 拉失败 → 视为未开通同步表(走原写路径)
谁可改 公司 top(现「数据同步」权限);终端只读
闭包 父子外键须同进白名单,否则保存通道失败
入通道 id TEXT UUID → 拒绝

5. 写路径规则

5.1 未进白名单或未开 local_dbsync

与现网完全一致:可不传 id、允许自增;online_primary 语义不变。

5.2 已开 local_dbsync 且表在白名单

  1. id网关自动补 UUID(规范化小写带连字符),响应带回 id / inserted_id;并记 auto_id 日志。
  2. 始终写 B 正式表;成功即返回成功。
  3. 写 outboxagent 异步推 A。
  4. agent 未装 / 停运:本地成功 + UI「待同步」不失败保存(定案 R1
  5. deleteoutbox delete 或墓碑agent 按 outbox id 保序;失败禁止换新 UUID

开通判定(写路径)mode=local_dbsync 白名单缓存命中该表;否则走 §5.1。

5.3 M1 无 agent 时「开通」含义(定案 O3

允许只落 B + 积压待同步;文案须写明 「需 agent 才上云」,不得暗示已上云。


6. 建表(定案 R2

模板 主键
默认 create双端 仍自增(不动)
同步表模板(双端新增) id TEXT UUID + 建议 updated_at / 配合 outbox version

禁止「全局默认改成 UUID」。


7. version / LWW定案 O5

定案
主序 outbox 单调 id / version
客户端 updated_at(不对时不挡保存
落败 写超管覆盖日志(两边 payload、胜出策略、tenant、表、pk、时间
弱提示「已自动合并」 默认;仅开通用户可配置打开(定案 R4

8. 绑定与迁移

定案
Binding API P1不挡 M2(定案 O4M2 可用现网派生 online_db_id
存量 online_primarylocal_dbsync 另附迁移手册(定案 O7加白名单 → 装 agent → 观察 → 关 HTTP禁止静默迁移(定案 R5/H5

9. 本机 agent 最小集

  • 可选装;未开通可不装。
  • _ajz_sync_outbox(或等价),保序推 A复用/扩展智建 ingest
  • 凭证:最小权限、按 online_db_id 隔离、可吊销outbox 敏感列脱敏或加密。
  • 心跳 → UI only。

10. 智建平台交付

优先级
P0 入通道 UUID + 闭包校验ingest 认客户端 UUID 幂等;模式/开通说明(默认客户无感)
P0 M3超管 LWW 审计 API/存储与租户「数据同步」菜单分离TTL
P1 Binding 登记/查询;限流 reconcile设置页「同步修复」可选、不弹窗强打断
P1 表白名单 B→A / 双向开关(默认 B→A
P2 超管按快照回滚单行

公司 top配通道、白名单、对账现权
平台超管:覆盖日志。
终端:无冲突台。


11. 分期与退出标准

阶段 目标 退出标准
M0 同步表模板 + 入通道校验 + 模式三分文档 自增表无法误入通道
M1 宇恒旁路:local_dbsync + 白名单松离线写 B可无 agent 未开通用户自动化回归 = 现网;开通用户离线可见;文案不承诺上云
M2 agent 最小 B→A + ingest 幂等 同 UUID 上云、不双行agent 停仍可本地保存
M3 超管 LWW 日志 + 限流 reconcile top 403双入口覆盖可查
M4 扩白名单;评估新客或显式迁移客是否默认 local_dbsync 旧客默认不变

M4 前禁止全员切默认、禁止一刀切关 HTTP 双写。


12. 验收清单(冻结)

不影响原有

  • 未开 local_dbsync:现网回归通过(自增不传 id、原 online_primary)。
  • 非白名单:不强制 UUID入通道拒绝。
  • local_dbsync / 清白名单缓存:行为回原模式。
  • 未开通:无强制 agent、无同步文案、保存不因同步失败。
  • 同表未同时走双路径;关同步后无双写放大。

开通后(白名单)

  • 离线写 B 可见;联网同 UUID 上 A幂等不双行。
  • agent 停:可保存 + 待同步;恢复后追上。
  • delete/重放保序;不换新 UUID。
  • LWW 落败在超管日志;公司 top 不可见。
  • 闭包不完整无法保存通道。
  • M1 文案不暗示已上云。

13. 双方承诺(冻结)

宇恒

  1. M0/M1模式三分 + 白名单进网关;旧分支零行为 diff附回归清单
  2. agent 非安装强依赖;同步 UI 仅开通后出现。
  3. M2 起对接 ingest不自造第二套写语义。
  4. 合入门禁:未开通用户行为 diff ≠ 0 → 不予合入。

智建

  1. M0入通道 UUID + 闭包校验。
  2. M2 前ingest 幂等认客户端 UUID。
  3. M3超管审计与租户控制台分离。
  4. 发版说明写明:默认客户无感;local_dbsync 为增值开通。
  5. 书面确认R1R4 全部按上文硬约束执行(已并入本文 §1/§5/§6/§7/§8

14. 对第二轮「待拍板」的最终答复

编号 决议
R1 确认:心跳只驱动 UI永不因 agent 拒绝保存
R2 确认:只加同步模板,默认建表仍自增
R3 确认:不一刀切关旧客 HTTP 双写
R4 确认:弱提示默认关,仅开通用户可配
O1 通道为源;宇恒缓存;无名单=未开通
O2 公司 top 改白名单;终端只读
O3 M1 可无 agent;文案「需 agent 才上云」
O4 Binding 不挡 M2
O5 outbox 单调 version 为主;不对时不挡保存
O6 同表互斥(非同库整库互斥)
O7 迁移手册 + 禁止静默迁移

15. 最终口径

旁路 opt-in 的松离线 + 本机 agent + dbsyncLWW 自动、超管可追溯;默认不影响宇恒现网。按 M0→M4 开工,本文冻结。


宇恒追加-实施钉死项(摘录已并入 §16

见过程稿全文;下列 §16 为智建复核后的采纳与补钉(不回退 H1H6


16. 实施钉死项 · 智建复核结论2026-07-31

宇恒 N1N6 总体可采纳,与最终版无冲突。下列为「写死值 + 防坑补钉」。

16.1 对 N1N6 的定案

# 宇恒建议 智建结论 写死值
N1 无 id → 网关自动补 UUID 采纳 自动生成并在响应带回 id(可用 inserted_id 作别名兼容);同时打日志「auto_id」 便于排障
N2 开通判定 采纳并收紧 硬条件mode=local_dbsync 白名单缓存命中该表。租户「同步开通」标志若存在,作为下发白名单的前提(无标志则不下发名单),再在写路径上增加第三道易漂移条件
N3 按表分支 + 单测 采纳 M1 必测:同库表白名单 / 非白名单分叉
N4 outbox未开通不建表 采纳并优选 优先与 permanent 同库 _ajz_sync_outbox(触发器简单);未开通库不创建该表;首次开通时迁移创建
N5 UUID 小写带连字符 采纳 双端入库前 normalize(小写 + 标准 8-4-4-4-12
N6 旧字段保留、新字段仅开通附加 采纳 未开通响应形状与现网一致(可多不可少成功语义)

16.2 宇恒反馈有没有问题?

没有方向性问题。 N1N6 都是在落实「不影响原有」,应进 M0/M1。
需注意的不是反对项,而是执行时的灰区(见下补钉)。

16.3 仍不完善 · 建议补钉P0/P1

# 缺口 建议 优先级
P0-a 白名单缓存过期 定 TTL如 515 min+ 开通/改名单后主动推送或下次启动强制拉;过期失败 → 未开通(已定),避免长期用过期「仍在名单」误走同步 P0
P0-b 同表从 HTTP 双写迁入白名单 迁移手册写死:先停该表 online_primary 双写 → 再进白名单 / local_dbsync;禁止「边双写边进名单」 P0并入 O7 手册)
P0-c 未开通回归套件归属 宇恒维护基线用例;智建提供「通道拒绝非 UUID」用例M1 退出双方签字 P0
P1-a M1 无 agent 积压 outbox/待同步条数告警阈值(如 >N 提示装 agent仍不挡保存 P1
P1-b agent 凭证续期 ingest Token 刷新与吊销流程写入 agent 最小集;过期只影响上云,不影响本地写 P1
P1-c local_database_id 回归:同一 user 多库绑定不串 online_db_id;名单按库缓存 P1
P2-a 自动补 UUID 掩盖调用方漏传 开通路径 metricsauto_id_count;超管/日志可查,不挡业务 P2

16.4 不采纳 / 不回潮

  • 不因「自动补 UUID」改为默认 local_dbsync
  • 不恢复「写前 agent 心跳失败则拒绝保存」。
  • 不把 LWW 审计开放给公司 top。

16.5 复核一句话

宇恒钉死项应采纳;再补缓存 TTL、迁表白名单与双写互斥顺序、回归归属M0/M1 即可干净开工。


17. 变更记录(落地)

日期 范围 说明
2026-07-31 M0 智建 通道保存 / PrepareChannelUUID TEXT PK + FK 闭包校验(platform/internal/dbsync/validate.go);文档 docs/同步表约定.mdSyncPage 表白名单提示
2026-07-31 M2 智建 PushToRemote + `/api/v1/agent/sync/.../push
2026-07-31 约定 M1宇恒 local_dbsync 旁路)与 agent 消费 outbox以本文 + docs/同步表约定.md 为接口约定,不在智建仓改宇恒代码
2026-07-31 M3 智建 LWW 覆盖审计 lww_overrides.jsonGET /api/v1/platform/dbsync/lww-overrides(仅超管);公司 conflicts API 403对账限流默认 lww_sourceSyncPage 去冲突台
2026-07-31 M4 智建 Binding API开通说明/O7 迁移手册;中间件文档 LWW 对齐SyncPage「同步修复」+ opt-in 文案apidef 补全。全员默认 / 宇恒灰度由对方与运营决策,本仓不改宇恒