DB Redesign 需求分析(场景清单 + 查询清单)

6 阶段设计流程(需求分析 → 概念设计 → 选型 → 逻辑设计 → 物理设计 → 实现调优)的第 1 阶段产出。来源:2026-07-02 会议 transcript、entity-relationship-map.md / why-tenant.md / v1-gaps.md、studio-api 代码实扫(apps/api 全部读路径)、test 库实测量级。 状态:DRAFT — 待 Max/Peter 确认频率与补充遗漏场景;§C 的 4 个问题正在用 brainstorming 流程逐个敲定。

A0. 能力需求总表(需求的锚点:一套系统的两个面)

retaintive 是一套系统的两个面,谁也不能缺:

  • Revenue 引擎(帮客户从电话/lead 里找到钱):信号进入 → AI 理解 → 派任务 → 执行 → 度量 → 变现放大
  • 管理面(我们经营这套 SaaS):onboarding → 身份权限 → 计费套餐 → 客户生命周期 → 内部运营 → 合规

两面咬合:Revenue 引擎的每行数据都 stamp 着管理面定义的边界(tenant / store / person);管理面的每次变更(挪店、转让、churn)都不许弄脏引擎的历史。数据地基必须同时撑住两面——只修管理面是为架构而架构,只做引擎功能就是回到现在这个状态。

判定口径:✅ 骨架已撑住(只差机制收口)/ ⚠️ 方向对但缺前置 / ❌ 模型缺概念。

Revenue 引擎(R 侧)

#能力现在 → 未来撑得住?差什么
R1信号进入电话/SMS/lead email → 全渠道(email/IG/web chat)⚠️多渠道身份没地方挂——person 层(顾客身份从"某店某号码"升级成"人")
R2AI 理解转录、单通/客户级分析、身份裁决(system-worldview)pipeline 已跑;历史 backfill 按当前映射误 stamp 要修(S22)
R3任务派发9 类任务;57 golden cases 已体系化,96.5% 准确率lead↔task 桥接补齐中(会上 Max 认领)
R4执行员工 today → AI agent(Vapi 语音/SMS 助手)future⚠️记账(timeline)/policy guard 已有;DNC/consent person 层是 AI 触达的合规前置
R5度量复盘老板一眼看清钱在哪漏(dashboard/funnel/trend)指标语义层:同名指标 3 套口径("intro booked" 三个定义),一个指标必须一个定义
R6变现放大AI daily report、收购尽调产品、对外 API、coaching 资产化R5 是前置;尽调需要"评估型访问"概念;资产化和尽调都需要历史不可被改写(temporal 归属)

管理面(M 侧)

#能力现在 → 未来撑得住?差什么
M1Onboardingadmin-led(signup→连 RC→建店→建 tenant)→ self-serve;评估型 onboarding(尽调用)⚠️设计已有(tenant-onboarding.md);"onboarding 不建 tenant"待落地;评估型无模型
M2身份与权限user / tenant member / store grants;离职、转让⚠️role 双轨要统一(D2);转让撞 one-active-tenant 约束(D1);OAuth 连接挂个人,人走管道断(S15)
M3计费与套餐tier / quota / Stripe;按店计费、超额加钱(Peter 的 basic/plus 愿景)模型预留正确(全挂 tenant),缺 quota enforcement——机制活,不动模型
M4客户生命周期provisioning→active→suspended→churned;店的买卖 / M&Astatus 无语义(3 个 tenant 全卡 provisioning);store 无 archive/lineage,转让语义未定义
M5内部运营control-plane-admin、对账、告警、audit⚠️admin 工具已有;对账 job 与 NULL 率告警缺(v1-gaps 缺口 2-4)
M6合规DNC/consent;审计;future 航空垂直(企业级,PCI/SOC2,单租户搬 pod)person 级 DNC 缺;audit 有底子(config_change_log/timeline);航空垂直另需 temporal 证据链 + DB placement(deferred 有触发条件)

判定汇总:骨架合理,五个概念级的洞

tenant/store/事件表三层骨架不用推倒。但 5 个"模型缺概念"的洞,不补则上表一半撑不住:

卡住的能力性质
① 指标语义层(一个指标一个定义)R5 → R6 全链杠杆最高、工程量最小(定义问题,非重构)
② temporal 归属 + 搬家/纠错二分(phone→store)R6 尽调、M4 M&A、航空证据链、Peter P2概念缺失,ER map §四 #1 的目标策略
③ person 层(顾客 = 人,不是某店某号码)R1 全渠道、R4 AI 触达合规概念缺失(D4)
④ tenant 模型两个口子(D1 多 membership、D5 评估型访问)R6 尽调产品线、M2 转让、BPO 商业模式决策待拍(D1/D5)
⑤ location 生命周期(店的身份连续性:archived/reattach/lineage)M4 店买卖与 M&A、Peter P3;根在 rc_stores unique key 含 user_id+connection概念缺失,独立于 ②——phone 的时间轴解不了店自身的生死与传承(2026-07-03 codex review 提出)

不用现在还的债(有触发条件,提前做是浪费):v2/v3 双平面合并(跟 DDB 退役走)、rc_* 改名(Final)、DB placement(第一个 Silo 客户来时)。

场景 SoT 索引(已有的成体系场景库,不在本文重复)

场景库条数位置
Task 决策 golden eval cases(C1-C57)57docs/ai/product/task-accuracy/baseline-v1-scenario-review.md
Task 业务场景(V1 lifecycle)12docs/product-design/v1/tasks-feature/task-lifecycle.md §四
Task flow 终态 + 人机竞争 + 冲突决策11+5+6docs/product-design/v2/tasks-feature/design/task-pipeline-deliverable-codex.md §8-§10
Store 隔离已覆盖场景13store-level-isolation.md §2
电话类型与跟进机制(业务语义底座)6 类 × 子场景docs/industry-knowledge/
全局 flow 骨架docs/product-design/system-worldview.md + north-star.md

A. 变更/完整性场景清单(A0 的证据层:会发生什么事)

A1. 店与电话拓扑(高危区,全部有实锤)

#场景触发者估计频率当前系统行为证据
S1电话被分错店,需要挪到正确的店(纠错)我们(RC 拓扑不可信,配置系手工复制)已发生多次历史 calls 的 store_id 不跟着改,全部变错Peter 会上实锤
S2电话真实换店(搬家,店重组/号码转移)客户低频但必然与 S1 无法区分,系统只有"覆盖"codex 指出二者语义相反
S3删店重建(误删/重整)客户或我们已发生lead email 绑定丢、mapping 变 orphan、历史断链Peter 实操;6 条 orphan 实测
S4新店 onboarding(RC sync 或手动建)我们/客户每新客户建店写 mapping 已闭环(#516);但 onboarding 不建 tenant(会上 assign Peter)会议 01:15
S5number porting / 号码回收再分配电话商低频未定义codex 补充
S6同一号码同时绑多店配置错误可能无唯一性约束防护(P0 泄漏风险)codex 引 repo 文档
S7店合并 / 拆分客户(M&A、重组)低频未定义(无 lineage 概念)overview 8 问 + codex

A2. 客户/租户生命周期

#场景触发者频率当前行为证据
S8tenant 转让给另一个人(接手方已有 tenant)客户Peter 已提出撞 one-active-tenant-per-user,当场 workaround=再建账号会议 01:36(→决策 D1)
S9客户扩张 1→N 店 / 缩小 N→1客户常态mapping 支持;quota 无 enforcementwhy-tenant
S10tier 升降 / 改付款人客户常态(billing 上线后)tenants.tier 有列,无 enforcement;Stripe futurewhy-tenant §六
S11客户 churn / suspend我们必然status 有枚举无语义,3 个 tenant 全卡 provisioningv1-gaps 缺口 5
S12评估型访问:潜在买家拿目标店的 RC login 做收购尽调销售(Oliver/Will 场景)已出现无模型("不支持访客"),但这是真实销售场景会议 01:19
S13一个客户多个 RC accounts / 换电话商客户必然provider connection 挂个人 OAuth,无 tenant 级归属deferred 表触发条件

A3. 人员与权限

#场景触发者频率当前行为证据
S14老板给经理只开某几家店的权限(Alan 7 店)客户已有真实需求store_members 支持;但 role 双轨混乱(→决策 D2)会议 01:35
S15员工离职/换店(含 owner 本人离开)客户常态user_connections 挂个人,人走 OAuth 断codex 补充
S16staff 名字归属(通话→staff,task→staff)pipeline每通电话staff 归属靠 AI 识别名字;tasks.closed_by_staff 基本是 system/NULL代码实扫 §6

A4. 顾客(contact)生命周期

#场景触发者频率当前行为证据
S17顾客在同客户多店消费 / 换店顾客常态(store_id, phone) 主键 → 跨店档案分裂Peter P4(→决策 D4)
S18顾客换手机号 / 家庭共享号码 / 号码易主顾客低频必然phone 即身份,无 person 层codex
S19DNC / consent(拒绝联系)顾客合规敏感挂 contacts(店级);跨店不生效codex:若自动触达已开=立刻修
S20lead 从 email 进来 → 归到店 → 生成任务 → 跟进 → 转化顾客+系统313 条/周(test)lead email 绑死 store 行;lead↔task 桥接缺失(Max 会上认领)会议 01:07-01:17

A5. 数据管道(写入侧场景)

#场景频率当前行为
S21正常事件流:call/SMS → 转录 → AI 分析 → contact/task/timelinecalls ~1.7k/周,msgs ~5k/周(test)phone→store 反查(Neon rc_store_phones,phone-identity 0.36.0 起;DDB 已不读)+ store_id/tenant_id stamp,fail-open
S22late event / 历史 backfill / 管道重跑每次修 bug 都会发生按"当前"映射 stamp 老事件 = 误 stamp(codex:必须现在修)
S23部署积压/管道断供后补数已发生(lead-tracking 6 周)NULL 累积,靠 sweeper 底座(未定时化)

A6. 平台化(future,设计时留口即可)

对外 API(per-tenant key + rate limit)、AI agent 介入(MCP)、3 方 CPaaS、BPO 转售、Pool/Silo 搬家 —— 均以 tenant_id 为锚,见 why-tenant §十一。

B. 查询清单(workload inventory,来自 apps/api 代码实扫)

B1. 隔离键机制(现状)

  • 三层中间件:auth(Cognito JWT→userId)→ tenant-context(control-plane 查 user→tenant)→ store-guard(storeId 从请求参数提取,只校验归属,TENANT_GUARD_ENFORCE=false 时 fail-open)
  • 真正的授权兜底在每个 route 的 getStoreContext():rc_stores.user_id(owner)→ store_members(shared)→ 取 store_phones
  • 双数据平面:v2 路由读 DynamoDB(phone-keyed),v3 读 Neon(store_id-keyed)

B2. 主要读路径(按页面)

页面隔离键聚合维度
Dashboard overviewcontacts+calls+messages(6 并行查)store_id30 天窗、按天趋势、lifecycle_stage 分桶
Dashboard summarycalls + tasksstore_id周/月窗,current vs previous
Leads funneltasks(cohort)+calls+messages+timeline+leadsstore_id5 层漏斗、期间对比、speed-to-lead 中位数
Leads pipeline/listcontacts(=lead)+ leads 表store_id 和 account_id 混用lead_status 分组
Tasks trendtasksstore_id按天 × type_category,open/closed/AI vs 人工
Tasks listtasks+contacts+calls+messages+timelineaccount_id AND store_id 双键status/group/tab/priority
Multi-store6 批查,全表user_id 发现店集合→per-store 窗口GROUP BY store_id,Team Productivity 跨表比值
Staffcalls(主)+tasksstore_idGROUP BY staff_name
Coachingcalls+coaching_reviews+contactsstore_id + tenant_id(review 层)tab/staff/read 状态
control-plane-admintenants/members/mappings内部工具直连 control plane

B3. 口径冲突(代码实扫发现,6 条)

  1. "intro booked" 三个源:summary 从 calls(outcome=success+revenue_impacting);multi-store/funnel 从 tasks(close_result='booked');lead-tracker 从 inbound calls
  2. lead funnel 三套实现:task-based / contacts-based / inbound-call-based —— 同名指标不同分母
  3. "leads 数"分裂:dashboard 从 contacts.lifecycle_stage='lead';pipeline incoming 从 leads 表(account 级)—— 永远对不上(= 会上 Vivian 报的问题的完整版)
  4. store_id vs account_id 隔离混用:leads/lead-communications/contacts-profile 按 account_id,其余按 store_id;多处 store_id=$1 OR (store_id IS NULL AND account_id=$x) 兜底
  5. v2(DDB/phone)vs v3(Neon/store_id)双平面,calls 数两边可能不一致
  6. staff 的 task 归属缺失:closed_by_staff_name 基本是 system/NULL,staff 绩效只能 call-based

B4. 写路径

写路径分两类,不能混成"全部 phone→store 反查":

类别写入方store_id 来源redesign 关注点
事件 / pipeline 写入message-processor / transcribe-processor / ai-analysis-processor / contacts-analyzer / lead-processor / lead-tracking pollerCall/SMS 走 phone→store 解析;lead email 走 leadEmail→store 路由;写入时 stamp store_id / tenant_id,rollout 期 tenant_id fail-opentemporal assignment、late event/backfill point-in-time resolve、NULL/错值监控与 repair
手动 / API 写入studio-api task 操作、coaching review、store 管理storeId 来自 request/session 选中的店,再由 getStoreContext() / store guard 验证访问权request-store authorization、selected store 有效性、tenant/store guard enforcement;不是 phone-derived,也不该套用 phone assignment fix

C. 待 Max/Peter 回答(第 1 步收口条件)

  1. A1-A4 每个场景的频率/重要性确认;有没有漏的场景?
  2. 指标口径的业务定义(这是需求不是实现):"intro booked" 以哪个源为准?lead funnel 以哪套分母为准?—— 定一次,全站遵守
  3. S12(评估型访问)要不要支持?这决定 tenant 模型要不要 guest 概念
  4. S19:SMS 自动触达现在开了吗?(决定 DNC person 层的优先级)

下一步(第 2 步预告)

场景清单收口后 → 从场景提炼 entity 表(名词 + 关系 + 会不会变),对齐 5 个 open decisions(D1-D5),产出目标概念模型。参考:entity-relationship-map.md(现状 + D1-D5)+ codex 审计(目标方向,.claude/specs/2026-07-02-codex-table-relationship-audit.md)+ postgres skill schema-design reference(第 3 步用)。