diff --git a/宇恒-松离线数据同步使用文档.md b/宇恒-松离线数据同步使用文档.md index b09e3ea..d12aba3 100644 --- a/宇恒-松离线数据同步使用文档.md +++ b/宇恒-松离线数据同步使用文档.md @@ -240,7 +240,9 @@ Content-Type: application/json | 无此成员 | 提示用绑定码;**勿**用超管号 `13531041945` 测 | | 生产联调样例 | 智建与宇恒均为 **`13531041944`** → 凭票或弹确认 | -### 未绑定时客户端流程(Z13d · 宇恒待接) +### 未绑定时客户端流程(Z13d · 宇恒已接 2026-08-05) + +> 宇恒落地:宿主 `ensure_sync_bound_interactive`;本机 `/database/sync/bind/*`;选「同步」走 `POST /database/sync/mode`(Z13e)。生产仍须智建部署含 `ticket-exchange` / `bind/policy` 的 gateway,并对齐凭票 Secret。 ```text 换票 / agents/me → sync_bound=false @@ -613,7 +615,7 @@ YXD_SYNC_ACCESS_TOKEN=... 5. 对白名单表插一行 → 看本机 B + outbox → agent 推上 A → 比对 UUID。 6. 多服务器演练:再建第二条通道指向另一 Postgres,换 `CHANNEL_ID` 验证不串库。 -7. **空表**:sync 周期调 `schema/ensure` + `schema`(Z10c),否则空表不会出现在线上。 +7. **空表**:sync 周期调 `schema/ensure` + `schema`(**Z10c 宇恒已接** `sync_schema.ensure_before_drain`),否则空表不会出现在线上。 --- diff --git a/联调后修改意见-宇恒松离线.md b/联调后修改意见-宇恒松离线.md index d74e749..f429054 100644 --- a/联调后修改意见-宇恒松离线.md +++ b/联调后修改意见-宇恒松离线.md @@ -1,19 +1,8 @@ # 联调后修改意见 · 宇恒松离线(形态 B) -> 初稿:2026-08-01 -> 修订:2026-08-03(对照智建已合入改动 + 宇恒压测结果回写) -> 再修订:2026-08-03 下午(用户自助 JWT / Binding / 库级策略复测,见 §5.3) -> 再修订:2026-08-04(§5.6 Z9 模块导入默认能力 · 方案 A) -> 再修订:2026-08-04 晚(§5.5 Z8f 本机镜像已通;§5.5.2 Z8g SyncPage) -> 再修订:2026-08-04(§5.7 **Z10 空表双侧建齐**;§0/§1/§5.4 现状回写) -> 再修订:2026-08-05(§5.6 **Z9e/Z9f 存量 import 必须扫库**;`coerce_fields` 复现) -> 再修订:2026-08-05(智建落实 **Z9e/Z9f、Z8g、Z11a/b**;Z12/Z13 仍待) -> 再修订:2026-08-05(智建落实 **Z12a/b/c/e、Z13a–c-1** API;Z12c-2/Z13d–e 待宇恒;绑定码控制台 UI 可后补) -> 再修订:2026-08-05(`宇恒-松离线数据同步使用文档.md`、`docs/数据同步-开通说明.md` 对齐 Z12/Z13 生产路径) -> 再修订:2026-08-05(**Z13c-2** 同号免验约定;**Z12c-2** 共享库;绑定码 SyncPage UI;成员管理可代绑手机) -> 再修订:2026-08-05(**宇恒凭票免登录** `POST /auth/yuheng/ticket-exchange`;gateway 放行 bind/ticket) -> 再修订:2026-08-05(试运行 `RequireForBind=false`;`GET /auth/bind/policy`;正式+凭票才禁 attested) -> 来源:宇恒客户端 `yuhengyihao_client` ↔ 本机智建 `127.0.0.1:8180`(gateway)/ `:8888`(platform) +> 初稿:2026-08-01 · 持续修订至 **2026-08-05** +> 本次整理:宇恒 Z10c/Z13 **客户端已接**回写;**§0.2** 拆成「已完成 / 仍待」;生产阻塞仅智建运维(部署/配号/Secret) +> 来源:宇恒客户端 `yuhengyihao_client` ↔ 智建 gateway/platform(本机 `8180`/`8888` 或生产 `aisite.yuxindazhineng.com`) > 依据:`松离线-dbsync方案-最终版.md`、`宇恒-松离线数据同步使用文档.md` --- @@ -22,15 +11,80 @@ | 级别 | 状态 | 说明 | |------|------|------| -| **硬改(阻塞宇恒上线)** | **无**(松离线主路径) | Z1–Z7、**Z9(含存量扫库)**、**Z10a/b** 已落实;主路径可上线 | +| **硬改(阻塞接口上线)** | **无** | Z1–Z13 API/技能大体齐;**生产联调**仍取决于 §0.2 **B 智建运维** | | **原建议项 2.1–2.5** | **智建侧基本已落实** | 见 §2 对照表;接口请保持兼容 | -| **用户自助 Z1–Z7** | **已落实** | Z2 宇恒复测通过;Z7 Binding 可读名已合入(需宇恒 ensure 时带 `database_name`/`display_name`) | -| **Z8 模块↔本机库+智能体库** | **大部分落实** | Z8a–f;**Z8g 展示已落实**(模块名 + 策略表文案);见 §5.5.2 | -| **Z9 模块导入默认能力(方案 A)** | **已落实(含存量)** | Z9a–f:启动扫库 + 一键开启导入 + 读路径内存兜底;见 §5.6 | -| **Z10 空表双侧建齐** | **智建 API 已落实;宇恒待接** | `schema/ensure` + `schema` + pull `columns`;**Z10c 待宇恒** sync 周期调用,见 §5.7 | -| **Z11 蓝图↔库列一致** | **智建已落实** | 发布自动 `ADD COLUMN IF NOT EXISTS`;导入 42703 可读提示;见 §5.8 | -| **Z12/Z13 开通/绑定 UX** | **智建已基本落实;宇恒待接** | 含凭票、试运行关短信(`RequireForBind=false`)、绑定码 UI;**Z13d/e 待宇恒**;见 §5.9–5.10 | -| **仍建议关注** | 性能/运维 | SQLite remote **高并发 push** 易锁;agent 宜单库串行 drain(属宇恒用法,非平台硬改) | +| **用户自助 Z1–Z7** | **已落实** | Z2 宇恒复测通过;Z7 可读名:宇恒 ensure 宜带 `database_name`(见 §0.2 A′) | +| **Z8 模块↔本机库+智能体库** | **已落实** | Z8a–g;见 §5.5 / §5.5.2 | +| **Z9 模块导入默认能力(方案 A)** | **已落实(含存量)** | Z9a–f;见 §5.6 | +| **Z10 空表双侧建齐** | **双方已接** | 智建 `schema/ensure`;宇恒 `sync_schema.ensure_before_drain`(§5.7) | +| **Z11 蓝图↔库列一致** | **智建已落实** | 发布自动 `ADD COLUMN IF NOT EXISTS`;见 §5.8 | +| **Z12 开通落点** | **双方已接** | 智建自动默认同步通道;宇恒换票/唯一通道/过渡 env(§5.9) | +| **Z13 绑定 UX** | **双方代码已接;生产待运维** | 智建 API+凭票+policy;宇恒技能/本机 bind API;见 §5.10、§0.2 B | +| **仍建议关注** | 性能/运维 | SQLite remote 高并发 push 易锁;agent 宜单库串行 drain | + +### 0.1 绑定产品冻结摘要(Z13 · 试运行) + +| 约定 | 内容 | +|------|------| +| 联调号 | 生产「宇信达」用 **`13531041944`**;**禁止**超管号 `13531041945` | +| 换票 | **凭票免登录**:宇恒签 `ticket-exchange`(`YXD_YUHENG_TICKET_SECRET` + `YXD_HOST_KEY` + 手机号);**不要**手写 `YXD_SYNC_LOGIN_PASSWORD` | +| 短信 | **试运行关闭**:`SMS.RequireForBind=false`;`GET /api/v1/auth/bind/policy` → `trial_mode=true`。接入短信后改 `true` | +| 宇恒未绑手机 | **仍可直接输入手机号**绑定(试运行免短信;正式须短信) | +| 同号 | 输入号 = 宇恒已绑号 → 正式可免短信 / 凭票;命中智建成员 → **必须弹「已有账号是否绑定」**,不得静默 | +| 确认 | 无论试运行与否,绑到已有账号都须用户 **确认**(`confirm=true`) | +| 当前阻塞 | **智建生产运维**(§0.2 B):部署含公开路径的 gateway、成员绑号、凭票 Secret 对齐 | + +### 0.2 待改清单(按负责方) + +> 明细仍见 §5.7 / §5.9–5.10。智建 Z12/Z13 API 已合入 **`d195aa4`**(凭票、`bind/policy`、试运行关短信);生产须 `./restart.sh --pull` 后才生效。 + +#### A. 宇恒 · 已完成(2026-08-05) + +| 编号 | 内容 | 落地 | +|------|------|------| +| **Z10c** | 空表双侧建齐调用 | `sync_schema.ensure_before_drain`;选「同步」force ensure;drain 前 TTL 节流 | +| **Z13b** | 绑定码兑换 | 表单「绑定码」+ `/database/sync/bind/redeem` | +| **Z13c-1** | 同号弹窗确认 | 技能 `bind_sync` + `/database/sync/bind/phone-confirm`(须 confirm) | +| **Z13c-2** | policy + 凭票 | `GET /database/sync/bind/policy`;试运行免短信;`ticket_exchange`(需 Secret) | +| **Z13d** | 未绑定检测 | 宿主启动 `ensure_sync_bound_interactive` | +| **Z13e** | 选「同步」即用 | `POST /database/sync/mode` → Binding + ensure + agent + full_push | + +#### A′. 宇恒 · 仍建议(非阻塞) + +| 优先级 | 编号 | 待改内容 | 验收要点 | +|--------|------|----------|----------| +| **P1** | **Z12e** | 过渡通道缓存 | 仅 1 条默认通道可写 env;终态以换票 `channel_id` 为准,勿当产品必填 | +| **P1** | **Z7** | Binding 可读名 | ensure / 登记 Binding 时带 `database_name` / `display_name` | +| **P1** | **§2.6** | agent 按库串行 drain | 同一 SQLite remote **勿**多线程齐推;加重试消化锁冲突 | + +**推荐调用顺序(未绑定)** + +```text +GET /auth/bind/policy + → sync_bound=false(换票 / agents/me) + → 有手机:phone-lookup → 弹窗 → phone-confirm 或 ticket-exchange + → 无手机 / 取消:绑定码 redeem + → 成功后库选「同步」→ Binding + drain(Z13e) +``` + +#### B. 智建 · 仍待办(运维 / 配置 · **当前生产阻塞**) + +| 优先级 | 项 | 说明 | +|--------|----|------| +| **P0** | 生产成员手机 | 「宇信达」成员管理绑定 **`13531041944`**;**勿**绑超管 `13531041945` | +| **P0** | **生产部署含凭票的 gateway** | 须 `./restart.sh --pull` 到含公开路径的版本:`GET /auth/bind/policy`、`POST /auth/yuheng/ticket-exchange`(旧 gateway 会 **401 missing bearer token**) | +| **P0** | 生产通道表白名单 | 形态 B 生产通道 **勿**用「填入测试默认」带 `article` 等演示表白名单;可空(整库 Binding) | +| **P1** | 默认同步 DSN | 生产填 `DBSync.DefaultRemoteDSN`(Postgres);空则仍为 sqlite 联调文件 | +| **P1** | 宇恒凭票 Secret | 生产 `Agent.YuhengTicket.Enabled=true` + Secret;与宇恒 `YXD_YUHENG_TICKET_SECRET` **同一值** | +| **P2** | 正式短信 | 接短信平台后:`SMS.Provider`≠`off` 且 `RequireForBind=true` | + +#### C. 双方已否决 / 不改 + +| 项 | 说明 | +|----|------| +| 终端冲突处理台 | 冲突仅平台超管侧 | +| 智建代改宇恒仓库 | 分工冻结,见 §3 | +| 平台 push 租约 | 正确性靠 version 幂等;并发由宇恒串行 drain | 宇恒对照脚本: @@ -69,7 +123,7 @@ | **生产 · 宇信达** | 公司管理 / 同号绑定联调 | **`13531041944`**(密码由开通时设定) | **专用联调号**;智建须在「宇信达」成员/管理员中写入此手机;宇恒 `YXD_SYNC_LOGIN_PHONE` 与 Z13 同号确认均以此号为准 | | 平台超管(禁止联调) | 控制台「填入超管手机」 | `13531041945` / `ljk_admin` | **最顶级管理员**;seed `ensureDevPhone(ljk_admin)`;**禁止**用作同步登录 / 绑定联调,会与公司账号冲突 | -> **智建待办**:生产「宇信达」写入成员手机 **`13531041944`**(成员管理「绑定」即可;勿绑到超管 `13531041945`)。 +> **智建待办(运维)**:见 **§0.2 B**(成员手机 `13531041944`、`./restart.sh --pull`、凭票 Secret、通道勿用测试表白名单)。 --- @@ -169,7 +223,7 @@ | **Z7** | **P1** | **SyncPage / Binding 展示「可读库名 + 映射」** | 通道「线上」列优先可读名;副文案 online_db_id / 落库路径;统计标注为 push 次数;Binding 列表「本地库名 ↔ 线上库名」。 | **已落实(2026-08-04)**:Binding 增 `database_name`/`display_name`;SyncPage 主标题优先本地 `database_name`,↑ 标注「推送次数 / 非表数」。宇恒 ensure 须带可读名,否则仍会回退到通道名或 driver | | **Z8** | **P0** | **模块数据:本机库可管理 + 按智能体上云** | 见 §5.5:本机 B 管理模块表;push 到智能体绑定的 A;废弃默认双轨 | **已落实(含 Z8g 展示)** | | **Z9** | **P0** | **模块默认 import + 存量扫库** | 见 §5.6 | **已落实 Z9a–f** | -| **Z10** | **P0** | **空表两侧建齐** | 见 §5.7:仅靠 outbox 不会建空表 | **智建 API 已落实**;**Z10c 待宇恒**接 ensure/schema | +| **Z10** | **P0** | **空表两侧建齐** | 见 §5.7:仅靠 outbox 不会建空表 | **双方已接**:智建 API + 宇恒 Z10c(`sync_schema`) | | **Z11** | **P1** | **蓝图增字段迁库** | 见 §5.8 | **智建已落实** ALTER + 导入提示 | ### 建议验收(智建改后) @@ -183,7 +237,7 @@ | 方 | 负责 | |----|------| -| 宇恒 | 库级三态 UI/API、写路径分流、outbox、用登录态调 push;**默认不按通道表白名单过滤**;**Z10c** 调 schema/ensure | +| 宇恒 | 库级三态 UI/API、写路径分流、outbox、用登录态调 push;**默认不按通道表白名单过滤**;**Z10c 已接** schema/ensure | | 智建 | 用户 JWT 鉴权、Binding 校验、任意表 push;**SyncPage/Binding 按可读名展示(Z7)**;**Z10a/b** 空表 API | --- @@ -245,7 +299,7 @@ | 弹窗 4 表「0 条记录 / 0 字段」 | 卡片统计不准;库内仍有数据 | **宇恒前端**(智建 SyncPage 无此卡片);可用数据预览或打开 remote db | | **要看线上表内容验同步** | SyncPage 原先只显示通道名/推送次数 | **智建已加**:「查看线上表」→ 表名/行数/字段 + 行预览;**可「删表」**(仅当前侧,需确认;不同步 DDL) | | **图1「线上表」≠ 图2 宇恒「数据表」** | 见 §5.4:一边是线上 A,一边是本机 B | **不是串库**;未 push / 未 ensure 的表不会出现在线上 | -| **模块数据按智能体进库** | 模块与 dbsync 原无关联 | **§5.5 Z8 大部分已通**;剩余 **Z8g** 展示与 **Z10c** 空表 | +| **模块数据按智能体进库** | 模块与 dbsync 原无关联 | **§5.5 Z8 已通**;空表 **Z10c 宇恒已接** | 同步链路本身可用;展示层勿把「通道文件名 + 推送次数」当成「本地库名 + 表行数」。 @@ -269,7 +323,7 @@ > 1. **模块数据也要能在本机库 B 里管理**(宇恒数据库区:建表/增删改查/导入),与普通业务表同一套体验,不是只能在聊天「模块操作」或线上 Postgres 里改。 > 2. 本机改完后,经松离线 **push → 该智能体绑定的线上库 A**;换机/仅线上可用 **pull/bootstrap** 灌回本机。 > 3. **哪个智能体的模块 → 进哪个智能体的库**(通道/`online_db_id` 绑定)。 -> **进展**:Z8f 本机镜像已通;智建绑库/筛通道已通;剩余主要是 **Z8g SyncPage 展示** 与空表 **Z10c**。 +> **进展**:Z8a–g 已通(本机镜像、绑库、SyncPage 模块展示);空表 **Z10c 宇恒已接**(`sync_schema`)。 **目标数据流** @@ -298,7 +352,7 @@ | 方 | 负责 | |----|------| | 智建 | Z8a 文案;Z8b 智能体↔通道/库绑定;**Z8g SyncPage 模块展示名**;Z10a/b API;开通说明 | -| 宇恒 | **本机库管理模块表(Z8f 已通)**;开通/全量推送时挂通道 `agent_id`/`app_slug`;**Z10c** sync 周期调 schema/ensure | +| 宇恒 | **本机库管理模块表(Z8f 已通)**;开通/全量推送时挂通道 `agent_id`/`app_slug`;**Z10c 已接** sync 周期 schema/ensure | **验收(Z8 完成后)** @@ -394,7 +448,8 @@ POST /api/v1/apps/coerce_fields/items/import 2. **旧模块**(Z9 合入前发布、之后未再发布)在跑完 Z9e 后同样不再 400。 3. 用户明确写「禁止导入」的表可不含 `import`(`disable_default_import` 或表级标记)。 4. 400 文案可读:指出是蓝图 operations 缺 import,而不是笼统「操作失败」。 -### 5.7 【智建已落实 Z10】空表也要两侧建齐(2026-08-04) + +### 5.7 【双方已接 Z10】空表也要两侧建齐(2026-08-04 / 宇恒接 2026-08-05) > **现象** > 本机有空表(如 `accounts` 0 行)时,线上「查看线上表」没有该表; @@ -404,7 +459,7 @@ POST /api/v1/apps/coerce_fields/items/import |------|--------|------|------| | **Z10a** | **P0** | 本机空表 → 线上建空表 | **智建已落实** `POST /api/v1/agent/sync/channels/{id}/schema/ensure` | | **Z10b** | **P0** | 线上空表 → 本机建空表 | **智建已落实** `POST .../schema`;`pull`/`bootstrap` 响应带 `columns` | -| **Z10c** | **P0** | 宇恒 sync 周期调用上述 API | **待宇恒**:drain **前**对本机业务表(含 0 行)ensure;bootstrap **前** schema + 本地 `CREATE IF NOT EXISTS` | +| **Z10c** | **P0** | 宇恒 sync 周期调用上述 API | **宇恒已接(2026-08-05)**:`sync_schema.ensure_before_drain`;选「同步」force ensure;drain 前 TTL 节流 | **契约摘要** @@ -472,82 +527,86 @@ POST .../schema 2. 账号 A 的本机库 push 不会出现在账号 B 的线上库;共享库仅在显式共享时可见。 3. 用户全程无需 F12、无需手填 `YXD_SYNC_CHANNEL_ID`。 -### 5.10 【智建 API 已落实 / 宇恒待接 Z13】绑定流程简化:绑定码 / 手机号(2026-08-05) +### 5.10 【双方代码已接 Z13】绑定流程简化:绑定码 / 手机号(2026-08-05) > **端到端体验(生产目标)** > 1. 后台已绑定(或用户用绑定码/手机号完成绑定)→ 宇恒本机库选 **「同步」** → **直接可用**(自动通道、自动 Binding、agent drain),无第二套配置。 > 2. 绑定流程必须比「登记智能体 + 抄通道 ID + 填 env」简单。 -> 3. **生产·宇信达联调账号**:`13531041944`(公司侧专用;**禁止**用超管号 `13531041945`);宇恒侧同号对齐此号做「已有账号是否绑定」联调。 +> 3. **生产·宇信达联调账号**:`13531041944`(公司侧专用;**禁止**用超管号 `13531041945`)。 +> 4. **试运行**:未接短信平台 → **关闭短信验证**;正式接入后再开(见下)。 **推荐交互** ```text 公司管理员(智建后台) - → 生成「绑定码」(一次性/短时有效,绑定到本公司 + 默认同步落点) - → 发给终端用户 / 贴在开通单 + → 生成「绑定码」→ 发给终端用户 宇恒 · AI建站智能体 - → 启动 / 换票前检测绑定状态 - │ - ├─ 已绑定本公司 → 静默换票;本机库选「同步」即可用 - │ + → 检测绑定状态 + ├─ 已绑定 → 静默换票;本机库选「同步」即可用 └─ 未绑定 - ├─ 宇恒已绑手机号,且智建侧同号有成员 - │ → 【必弹】「检测到手机号 xxx 在「宇信达」已有账号,是否绑定?」 - │ ├─ 确认 → 绑定(免短信) - │ └─ 取消 → 改走绑定码 / 换号 - ├─ 表单:【绑定码】或【手机号】(宇恒未绑手机时也允许直接填手机号) - │ · 填绑定码 → redeem - │ · 填手机号 - │ ├─ 【试运行】短信未接入:一律免短信,仅弹「是否绑定」确认 - │ ├─ 【正式】宇恒已绑号且输入=已绑号 → 免短信 → lookup → 确认 - │ ├─ 【正式】宇恒未绑 / 异号 → 须短信 → lookup → 确认 - │ └─ 智建无此成员 → 提示引导用绑定码 - └─ 都没有 → 明确提示联系管理员要绑定码 - → 绑定成功后:本机选「同步」→ 直接 drain,零通道配置 + ├─ 宇恒已有手机,且智建同号有成员 + │ → 弹「已有账号是否绑定?」→ 确认 / 取消 + ├─ 表单:【绑定码】或【手机号】 + │ · 宇恒未绑手机 → 仍可直接填手机号 + │ · 试运行:不校验短信,仅确认绑定 + │ · 正式:同号可免短信/凭票;异号须短信 + └─ 无成员 / 无码 → 提示联系管理员 + → 绑定成功 → 选「同步」→ drain,零通道配置 ``` -> **试运行约定(当前)**:尚未接入短信平台 → `SMS.RequireForBind=false`(或 `Provider=off`)**关闭绑定短信验证**;仍须用户确认「是否绑定」。接入短信后改为 `RequireForBind=true`,启用下表正式规则。 +**试运行 vs 正式** -**同号 / 验证规则(正式目标;试运行短信步骤可跳过)** +| 项 | 试运行(当前) | 正式(接短信后) | +|----|----------------|------------------| +| 配置 | `SMS.RequireForBind=false`(或 `Provider=off`) | `RequireForBind=true` | +| 探测 | `GET /api/v1/auth/bind/policy` → `trial_mode=true`,`sms_required_unless_attested=false` | `trial_mode=false` | +| 填手机号 | 可绑;**不校验短信** | 异号 / 宇恒未绑号须 `sms_code` | +| 同号免验 | 可不传 `sms_code`;确认即可 | 同号 attested 或走 `ticket-exchange` | +| 必保留 | **「已有账号是否绑定」确认**;`confirm=true` | 同左 | + +**同号 / 验证规则** | 场景 | 行为 | |------|------| -| **试运行 / 短信未接入** | **不校验短信**;填手机号 + 确认即可绑定 | -| 宇恒**未**绑定手机号 | **仍可直接输入手机号**;正式环境须短信 | -| 宇恒已绑手机,输入 = 已绑号 | **免短信**;命中智建账号仍弹「是否绑定」 | -| 宇恒已绑手机,输入 ≠ 已绑号 | 正式环境**必须短信** | -| 宇恒/输入手机 = 公司内已有成员 | **必须先询问**「已有账号,是否绑定」;不得静默绑定 | -| 用户点确认 | 绑定到该已有账号;智能体 host_key 挂到该公司 | -| 用户点取消 | 不绑定;可改输绑定码或其他手机号 | -| 手机号在公司不存在 | 提示无此成员;引导用绑定码 | -| 生产联调样例 | 宇恒号与智建均为 **`13531041944`** → 弹确认;**勿用** `13531041945` | +| 试运行 / 短信未接入 | **不校验短信**;填号 + 确认即可 | +| 宇恒未绑手机 | **仍可直接输入手机号**;正式环境须短信 | +| 宇恒已绑且输入 = 已绑号 | 正式可免短信 / 凭票;命中成员仍弹确认 | +| 宇恒已绑且输入 ≠ 已绑号 | 正式**必须短信** | +| 命中公司成员 | **必须询问**「已有账号是否绑定」;不得静默 | +| 用户确认 | 绑定该账号 + 公司默认同步落点 | +| 用户取消 | 不绑;可改绑定码 / 换号 | +| 公司无此号 | 提示用绑定码 | +| 联调样例 | **`13531041944`**;勿用 `13531041945` | | 编号 | 优先级 | 诉求 | 说明 | 负责 | |------|--------|------|------|------| -| **Z13a** | **P0** | **后台生成绑定码** | `POST/GET/DELETE /api/v1/admin/bind-codes`;SyncPage「绑定码」区可生成/复制/撤销 | **智建已落实**(API + 控制台) | -| **Z13b** | **P0** | **绑定码兑换 API** | `POST /api/v1/auth/bind-code/redeem`(`host_key` + `code`)→ 激活并绑定落点 | **智建已落实** | -| **Z13c** | **P0** | **手机号探测 API** | `POST /api/v1/auth/bind/phone-lookup` → `{ exists, tenant_name, masked_name, need_confirm, sms_required_unless_attested }`,**不**直接绑定 | **智建已落实** | -| **Z13c-1** | **P0** | **同号确认绑定** | `POST /api/v1/auth/bind/phone-confirm`(`confirm=true` 才绑);写审计 | **智建已落实** + **宇恒弹窗待接** | -| **Z13c-2** | **P0** | **验证策略 / 凭票** | **试运行**:关短信(`RequireForBind=false` / `Provider=off`);`GET /auth/bind/policy` 可探测。**正式**:异号 `sms_code`;同号凭票优先,**正式且启凭票**才禁 attested | **智建开关+凭票+policy 已落实** + **宇恒对接** | -| **Z13d** | **P0** | **未绑定检测与提示** | `sync_bound=false`:有手机号先 lookup;命中则弹确认;未命中再出绑定码/手机号表单 | **宇恒技能**(智建字段已提供) | -| **Z13e** | **P0** | **选同步即用** | 库选「同步」→ 自动 Binding + drain;零手填通道 | **宇恒**(依赖 Z12/Z13) | -| **Z13f** | **P1** | **安全** | 试运行关短信;正式后异号强制短信;确认绑定写审计 | **智建开关已落实** | +| **Z13a** | **P0** | **后台生成绑定码** | `POST/GET/DELETE /api/v1/admin/bind-codes`;SyncPage「绑定码」区 | **智建已落实** | +| **Z13b** | **P0** | **绑定码兑换** | `POST /api/v1/auth/bind-code/redeem`(`host_key` + `code`) | **双方已接**(智建 API + 宇恒表单) | +| **Z13c** | **P0** | **手机号探测** | `POST /api/v1/auth/bind/phone-lookup`(不直接绑定) | **智建已落实** | +| **Z13c-1** | **P0** | **确认绑定** | `POST /api/v1/auth/bind/phone-confirm`(`confirm=true`) | **双方已接**(宇恒弹窗 + 本机 API) | +| **Z13c-2** | **P0** | **验证策略 / 凭票 / policy** | 试运行关短信;`GET /auth/bind/policy`;正式异号短信;凭票 `ticket-exchange` | **双方已接**(生产须对齐 Secret + 部署 gateway) | +| **Z13d** | **P0** | **未绑定检测与提示** | `sync_bound=false` → lookup / 表单 | **宇恒已接** `ensure_sync_bound_interactive` | +| **Z13e** | **P0** | **选同步即用** | 库选「同步」→ Binding + drain;零手填通道 | **宇恒已接** `POST /database/sync/mode` | +| **Z13f** | **P1** | **安全** | 试运行关短信;正式强制异号短信;审计 | **智建开关已落实** | **验收** -1. 管理员生成绑定码 → 用户填码 → 绑定成功 → 库选「同步」→ 数据进该公司线上库。 -2. **宇恒与智建同号 `13531041944`** → 必须弹出「已有账号是否绑定」;确认后绑定,取消则不绑(禁止用超管号 `13531041945` 测)。 -3. **宇恒未绑手机** → 仍可直接输入手机号;**试运行免短信**,正式后须短信。 -4. **试运行**:`RequireForBind=false` 时不带 `sms_code` 也可 confirm(仍须 `confirm=true`);`GET /auth/bind/policy` 返回 `trial_mode=true`。 -5. 未绑定用户:先同号探测,再绑定码/手机表单;**不**出现 DSN/通道 ID。 -6. 他人绑定码 / 未确认的同号,不能把数据绑进别的公司或别人账号。 -7. **正式且启凭票**:同号走 `ticket-exchange`,不再依赖明文 `attested_same_phone`。 +1. 绑定码 → 填码 → 绑定成功 → 库选「同步」→ 数据进公司线上库。 +2. 同号 `13531041944` → 弹「已有账号是否绑定」;确认绑、取消不绑;禁用 `13531041945`。 +3. 宇恒未绑手机 → 仍可直接填号;试运行免短信,正式须短信。 +4. 试运行:无 `sms_code` 也可 confirm;`GET /auth/bind/policy` → `trial_mode=true`。 +5. 未绑定用户只见绑定码/手机表单,**不见** DSN/通道 ID。 +6. 未确认 / 他人绑定码,不能绑进别的公司或别人账号。 +7. 正式且启凭票:同号走 `ticket-exchange`,不再依赖明文 `attested_same_phone`。 + --- ## 6. 联系与附件 +- **待改清单(优先看)**:§0.2(宇恒已完成 A / 仍建议 A′ / **智建运维阻塞 B**) - 方案:`松离线-dbsync方案-最终版.md`(含 2026-08-01 联调建议落地记录) -- 宇恒使用说明:`宇恒-松离线数据同步使用文档.md`(含 Z10 schema/ensure) +- 宇恒使用说明:`宇恒-松离线数据同步使用文档.md`(含 Z10 schema/ensure、Z13 绑定) - 开通说明:`docs/数据同步-开通说明.md` +- 绑定策略探测:`GET /api/v1/auth/bind/policy`(`trial_mode` / `require_for_bind`) - 本意见如与冻结方案冲突,**以冻结方案为准**;§5.1–5.10 为产品增量与复测记录,不推翻 H1–H6 默认无感约束。