# 数据同步 · 开通说明（管理员）

> 依据：`松离线-dbsync方案-最终版.md`、`联调后修改意见-宇恒松离线.md`（Z12/Z13）  
> **默认客户无感**：未显式开通时，终端保存与自增表行为与现网一致。  
> **生产开通主路径**：启用智能体自动绑通道 / 绑定码 / 同号确认；**不要**把「手建通道 + 抄通道 ID」当作普通开通必经步骤。

## 三分模式（客户端配置）

| 模式 | 含义 | 谁改 |
|------|------|------|
| `local_only` | 仅本地，无同步 | 默认之一 |
| `online_primary` | HTTP 双写 / 离线 pending（旧路径） | 已配线上 API 且未写 MODE 时兼容升 |
| `local_dbsync` | 松离线 + 本机 agent（表白名单或 Binding 整库） | **仅显式配置**或用户库级选「同步」，禁止静默全员升 |

是否走 `local_dbsync` 由客户端环境变量 / 库级策略决定，平台**不会**替全员切默认。

## 联调账号

| 环境 | 手机号 | 密码 | 说明 |
|------|--------|------|------|
| 本机演示公司 | `13800000001` | `demo123` | 仅本机；勿推生产宇信达通道 |
| **生产 · 宇信达** | **`13531041944`** | 开通时设定 | 公司侧联调专用；智建须在「宇信达」写入此成员手机；宇恒 `YXD_SYNC_LOGIN_PHONE` 与同号绑定均对齐此号 |
| 平台超管（禁止联调） | `13531041945` | `ljk_admin` | 最顶级管理员；**禁止**用作同步/绑定联调 |

## 线上库 A：统一 Postgres

| 场景 | 推荐 |
|------|------|
| **生产 A** | **`postgres`**（经智建 agent push 写入；可与平台同机或独立实例） |
| 本机 B | 宇恒侧多为 SQLite（形态 B 下平台可不连 B） |
| 联调临时 A | 可用 sqlite 文件；**不宜**多 agent 并发写 |

公司默认同步通道的 remote DSN：生产在 `platform.yaml` / 环境配置 `DBSync.DefaultRemoteDSN`；空则联调用 sqlite 文件。

Postgres DSN 示例：

```text
postgres://user:pass@127.0.0.1:5432/app_online?sslmode=disable
```

## 生产开通（推荐 · Z12/Z13）

普通管理员路径：**启用智能体 → 完成**（勿引导先「新建通道」、勿要求用户抄 `channel_id`）。

| 步骤 | 做什么 |
|------|--------|
| 1 | 确认公司默认同步 DSN（`DefaultRemoteDSN`）指向生产 Postgres |
| 2 | 「用户管理」**启用智能体** → 平台自动创建 `is_system_default` 通道，并写回该智能体 `channel_id` / `online_db_id` |
| 3 | （可选）`POST /api/v1/admin/bind-codes` 生成绑定码，发给终端用户 |
| 4 | 终端：已绑则换票带 `sync_bound=true`；未绑则 **绑定码兑换**、**宇恒凭票**或 **手机号 lookup→确认**（同号必须弹窗，禁止静默绑） |
| 5 | 宇恒本机库选「同步」→ 自动 Binding + agent drain；本地未装 agent 仍可保存，文案「需 agent 才上云」 |

同号硬约束：宇恒手机 = 公司成员手机（联调样例 **`13531041944`**）→ 必须询问「已有账号是否绑定」；**勿用**超管号 `13531041945`。

**试运行**：`SMS.RequireForBind=false`；`Provider: "off"`（**须加引号**，裸 `off` 会被 YAML 当成布尔导致 platform 起不来）。正式接短信后改为 `RequireForBind: true` 且 Provider 非 `"off"`。宇恒可先 `GET /api/v1/auth/bind/policy` 看 `trial_mode` / `yuheng_ticket_enabled`。

换票 / 自查：

- `POST /api/v1/auth/token` → `channel_id` / `online_db_id` / `database_name` / `sync_bound`
- `GET /api/v1/agents/me`（智能体 Bearer）
- `POST /api/v1/auth/yuheng/ticket-exchange`（仅宇恒 HMAC 凭票）
- `POST /api/v1/auth/yuheng/restore-by-host`（按宇恒 `host_key` 恢复已有绑定并自动补齐建站权限；票内 phone 可空）

## 运维高级：手建通道（过渡 / 多机）

「数据同步」页仍可新建/改通道（改 DSN、多服务器、排障），**不是**普通开通必经 UI。

| 部署 | 怎么配 |
|------|--------|
| **单服务器** | 优先用公司**一条**默认同步通道（自动创建）；宇恒优先换票落点，`YXD_SYNC_CHANNEL_ID` 仅作过渡缓存 |
| **多服务器** | **每台线上库一条通道**（不同 remote DSN）；宇恒按 `local_database_id` / Binding 选用对应 `channel_id` |

手建时建议：方向 **本地 → 线上**，策略 **源端覆盖（lww_source）**；表白名单可空（整库 Binding）；若填表须 UUID PK + FK 闭包。

Binding：`POST /api/v1/admin/sync/bindings` 登记 `local_database_id → online_db_id`，并带上 `channel_id`。  
管理员 Token 或**登录用户 JWT**均可登记；普通用户只能登记/查看本人 Binding。

## 模块与本机库（一份表 · Z8）

| 原则 | 说明 |
|------|------|
| **本机 B 管理面** | 模块业务表应能在宇恒本机库（如「AI建站智能体API」）里增删改查/导入，与普通表同一体验 |
| **上云** | 开通 sync 后经 outbox → agent push → 智能体绑定的线上库 A |
| **智能体绑库** | 生产由启用智能体自动写入；控制台仍可查看/改 `channel_id` / `online_db_id` / `database_name`；「数据同步」可按智能体筛通道 |
| **发布落库** | 智能体 Token 新建发布时，若已设 `database_name`，优先 `database_per_app` 写入该库 |

不要默认维持「模块只在平台 `/apps` schema、松离线又一套 SQLite」双轨；对账时本机有、线上无 = 尚未 push / 未 ensure，不是串库。

## 用户自助（库级三态）

客户端对每个库可选：仅本地 / 仅线上 / 同步。选同步后：

1. 确认已绑定本公司落点（换票 `sync_bound` 或 Binding）；未绑先走绑定码 / 同号确认  
2. 用户 JWT → `POST /api/v1/admin/sync/bindings`（带 `channel_id`）  
3. 同 JWT → `GET .../agent/sync/channels/{id}/whitelist`  
4. 同 JWT → `POST .../push`，Body 须含本人 `online_db_id`  

通道表白名单**非空**时只同步命中表；**空名单**（默认同步通道常见）时平台接受整库表名（UUID PK）。  
「仅线上 / 下行拉齐」：`POST .../agent/sync/channels/{id}/pull`（`mode=bootstrap|pks|rows`）或 `.../bootstrap`；平台返回 A 上行，客户端写入本机 B。  
**空表也要两侧建齐**：本机空表 → `POST .../schema/ensure`；线上空表 → `POST .../schema`（或 pull 的 `columns`）在本机 `CREATE IF NOT EXISTS`。仅靠 outbox 行 push **不会**带上空表。  
控制台「查看线上表」可 **删表**（`POST .../admin/sync/channels/{id}/drop-table`）：只删当前查看侧，**不同步** `DROP` 到另一侧；本机仍有同名表时下次 push/ensure 可能再建回来。

## 谁能看什么

| 角色 | 可见 |
|------|------|
| 公司管理员 | 启用智能体、绑定码、通道配置（运维）、对账统计；**无**冲突台 / LWW 覆盖明细 |
| 普通登录用户 | 不可配通道；可自助 Binding + 用登录 JWT push 本人库；可走绑定码/同号确认 |
| 平台超级管理员 | LWW 覆盖审计（平台工作台） |
| 未开通终端用户 | **零同步文案**，无强制状态条 |

## 相关文档

- [同步表约定.md](./同步表约定.md)  
- [数据同步-迁移手册.md](./数据同步-迁移手册.md)（旧客从 HTTP 双写迁入）  
- [数据同步-中间件.md](./数据同步-中间件.md)  
- `联调后修改意见-宇恒松离线.md`（Z12/Z13 验收与分工）  
- `宇恒-松离线数据同步使用文档.md`（宇恒对接契约）  
