Tenant Onboarding:新客户怎么获得 tenant,存量客户怎么桥接
今天一个新客户 onboard,从头到尾不会碰 tenant。 Signup 只有 Google OAuth(无公司名表单),3 步 onboarding(连 RingCentral → 配店 → 看 dashboard)没有任何一步创建 tenant;建店时的 mapping 同步在「user 没有 tenant」时静默 skip,且调用方不看返回值。全 repo 只有两个地方能创建 tenant:手动 seed 脚本和内部 admin 后台。唯一真实 tenant(orangeTheory)就是 2026-06-11 手动 seed 的。
这份文档回答三个问题:现状链路断在哪(实测)/ V1 新客户流程怎么设计(提案)/ 存量客户怎么桥接(一次性动作)。配对 v1-gaps.md(缺口 6 指向本文)和 prod-rollout-checklist.md(桥接的 prod 执行时点)读。
一、现状实测:链路与断点
新用户从注册到用上产品的完整链路,和每一步与 tenant 的关系(证据来自 studio-website-monorepo 2026-07-01 main):
仅有的两个 tenant 创建路径(都是手动):
断点的本质:tenant 建档是运营动作,建店是客户动作,两者没有顺序保证也没有对账兜底——客户先建店,mapping 就永远缺(ensure 只在建店那一刻跑);没人建 tenant,客户就永远「三无」且无人知晓(fail-open 静默)。
二、V1 设计(提案):admin-led 建档 + 对账 auto-heal 兜底
为什么不做 self-serve 自动建 tenant:当前获客是 sales-led,客户总数个位数。让用户 signup 填公司名 = 为不存在的 self-serve 通道建产品面,还会制造垃圾 tenant(control plane 里 test / test b 两个脏 tenant 就是这么来的)。
V1 流程(顺序无关,靠机制兜底):
这个设计的关键洞察:缺口 4 的对账 job 同时就是 onboarding 的兜底机制——它不只是防漂移,还让「先建店后建档」这个最常见的真实顺序自动收敛。所以对账 job 的优先级比单看缺口 4 更高。
auto-heal 的边界要写死:只有 derived owner 恰好有 1 个 active tenant 时才自动补 mapping;owner 无 tenant、多 active tenant、或跨 tenant 冲突时只进日报/告警,不自动写。
要补的两个小件(都很小):
- 「有店但 owner 无 tenant」进对账 job 的日报(现在这种状态完全不可见;fail-open 的
logger.warn没人看) - status 生命周期接线:onboarding 完成的判据(mapping 齐 + 写入带 tenant_id 验证过)→ 运营在 admin 后台把
provisioning翻active。admin 后台当前没有改 status 的操作,要加一个
三、存量客户桥接(一次性,现有 4 个店主,其中 3 个待桥接)
2026-07-01 实测,所谓「存量客户」就这么多(reproducer:SELECT user_id, count(*) FROM rc_stores GROUP BY user_id 分别在 test / prod 库跑):
去重后只有 3 个 user 没有 tenant(644854c8 / d4a8d448 / b4d86488,test 和 prod 是同一批人)。桥接动作(每人):
- control-plane-admin 建 tenant + 加 owner member(或直接跑 seed 脚本,它就是为这个场景写的)
- mapping:seed 脚本
--apply,或等对账 job 上线自动补 - 历史行回填:
backfill-tenant-ids.ts --apply(mapping 齐了之后跑)
prod 侧的执行时点已固化在 prod-rollout-checklist.md Step 2-3;test 侧随时可做。
四、Self-serve 的触发条件(现在不做)
当获客通道产品化(自助注册付费)时,再把 tenant 创建挪进产品流:signup 后首次 setup 让用户填公司名 → 自动建 tenant(provisioning)+ owner member → 接 tenant_provisioning_jobs 账本(见 best-practices.md §Silo 自动化必备的 7 件事)。触发信号:运营手动建档成为瓶颈,或第一个非 sales 触达的客户出现。在那之前,admin-led 是正确的懒。
五、待拍板(3 个)
- V1 方向:admin-led 建档 + 对账 auto-heal 兜底,这个方向 OK?(替代方案:signup 即自动建 tenant——不推荐,理由见 §二)
- status 生命周期:
provisioning→active的判据用「mapping 齐 + 新写入带 tenant_id 验证通过」、由运营在 admin 后台手动翻,可以吗? - 存量名单:
644854c8/d4a8d448/b4d86488这 3 个 user 分别是谁(真实客户/团队号)?真实客户才建档,测试号不建。
Source of Truth
studio-website-monorepo/apps/api/src/middleware/tenant-context.ts— fail-open 行为studio-website-monorepo/apps/api/src/services/control-plane.ts—ensureTenantMappingsForStores与 skip 逻辑studio-website-monorepo/apps/api/scripts/seed-tenant-store-mappings.ts/backfill-tenant-ids.ts— 手动建档与回填工具studio-website-monorepo/apps/control-plane-admin/— 内部 admin 后台能力边界v1-gaps.md— 机制缺口总账(缺口 6 = 本文)