Skip to main content

补充评审:Slack 每 Specialist 独立 App — 可行性结论与关键修订建议

性质PRD 可行性评审补充(工程视角),非替代 PRD
评审对象slack-per-specialist-app-prd.zh.md(rev 2)
作者工程
日期2026-07-13
用途与产品(Franky)对齐范围、术语、以及一个必须先拍板的架构决策
依据代码api/src/channels/slack/api/src/organizations/organizations.service.tsapi/src/onboarding/onboarding.entities.tsapi/src/specialists/specialist.entity.tsfrontend/src/app/ops/frontend/src/app/client/settings/channels/
依据 ADRADR-030(Draft)+ Slack 子文档(Draft)、ADR-036

1. 一句话结论

需求方向成立、数据模型撑得住,但 PRD 把它写成了"UI + 埋点为主"的产品需求;实际上它的底座(一张核心表 + 一整套凭证/路由改造)尚未落地,本质是一个后端地基工程。范围被 PRD 低估。可以推进,但需先拍板一个关键决策(§4)。


2. 可行性拆解

✅ 已经就绪的

  • N:M 基数天然支持"N 个 Specialist = N 个 bot"。OSA(OrgSpecialistAssignment)唯一约束只有 (orgId, specialistId)onboarding.entities.ts:61):一个 org 可挂多个 Specialist,一个 Specialist 可服务多个 org。
  • 已有可对标的先例:雇用 Specialist 时会自动生成 per-OSA 的 email 身份(alias + Gsuite 开通),发生在 organizations.service.ts_enqueueWorkspaceProvisioning。Slack 的 per-Specialist bot 可以照抄这条 provisioning 链路。

🔨 必须从零新建的(PRD 默认它们已存在,实际没有)

  • osa_channel_endpoints 这张表根本不存在:全仓无 entity、无 migration,仅在 ADR-030(状态 Draft)和两处 CLAUDE.md 里以 "in-flight" 规划形态出现。PRD 的 R1–R6 全部压在这张表 + Secrets Manager(per-app / per-install)之上。
  • 入站路由要"回滚"一个刚做过的决定:今天故意只按 team_id 解析 org、刻意不用 api_app_idslack.service.ts:798,#2403);PRD 要改成 (api_app_id, team_id) → OSA,即把刚移除的维度重新引入,并且要每 app 各自 signing_secret 验签。
  • App 自动生成子系统:调 Slack App Manifest API 建 app、存密钥、并发幂等 —— 全新。

⚠️ 会拖垮 PRD 目标、但被当"非阻塞"处理的两个坑

  • App 图标无法纯 API 设置(PRD O1)→ 需要人工 pending_ops 步骤。
  • Slack 免费版 ~10 app 上限(PRD O2)→ 多 Specialist 客户会中途撞墙。付费版(Pro / Business+ / Enterprise Grid)无此上限,问题只存在于免费 workspace;因此本坑的影响面取决于目标客户的 Slack 套餐,属于"部分客户会撞、非全量"。处置:安装前检测 workspace 套餐并提示(PRD O2 待确认能否在安装前得知套餐),而非硬性限制。
  • 两者都会直接冲击 G2 的"≤5 分钟、80% 无工单",见 §4 的处置建议。

范围判断

PRD 的 v1 实际等于"先把 ADR-030 Phase 1–3 从零建出来,再叠 UI"。重头在后端;前端面板改造反而是最轻的一块。建议 PRD 显式承认这个依赖,并把 ADR-030 Slack 子文档评审通过列为硬前置。


3. 术语澄清(PRD 混用,需在文档层统一)

PRD 通篇用"Specialist"指代两个不同层级的实体,是后续设计歧义的根源。应区分:

概念定义层级
Specialist catalog archetype(目录原型)is_catalog=true, org_id=NULL 的平台模板,可被多个 org 反复雇用平台级、唯一catalog_slug
live clone / OSA(org 克隆实例)某 org 雇用时由 _materializeCatalogSpecialist 克隆出的 is_catalog=false, org_id=<org> 行 + 一条 OSAper-(org×specialist)(org_id, specialist_id)
  • 一个 archetype 被 N 个 org 雇用 → 产生 N 个 clone/OSA。
  • 现库里约 360~370 个 archetypeseed-specialist-catalog.ts 有 371 条)——规模是"几百",不是几十。这个数量级直接决定 §4 的最佳实践。
  • 另需澄清 Expert ≠ Specialist:一个 org 有几个人类 Expertexpert_access 授权的审核员)与 app bot 数量完全正交,不产生冲突。PRD 语境下"多个专家"= 多个 Specialist(AI 人格 / 多条 OSA)。

4. 关键决策(需产品先拍板):App 身份在"什么时刻"生成?

这是本需求最该先定、且 PRD 当前选择偏差最大的一点。

4.1 前提:bot 必须分成两层,分别挂在不同实体上

bot 的层内容挂在哪跨 org
App / personaapi_app_id、bot 名=firstName、头像、manifest、signing_secretarchetype 级(全平台一个,键 catalog_slug✅ 共享
Install / endpointOAuth access_tokenteam_id、会话历史OSA 级(每雇用一次)❌ 各自独立

由此得出一个必须写进 PRD 的事实纠正:不同 org 是共享同一个 app 的(同 api_app_id、同 bot 身份),各自独立的只是 install(token/workspace/历史)。隔离靠"安装隔离",不靠"app 隔离"。

4.2 App 身份的生成时机——三个选项

方案触发时机几百 archetype 规模下的后果
A. 建 archetype 时全量生成createSpecialist/seed❌ 360 个 app 一次性建出、绝大多数从未被雇用 → 浪费 Slack app 舰队配额,放大 §8.3 unlisted 舰队政策风险
B. 首次被任一 org 物化时生成一次(推荐)_materializeCatalogSpecialist 首次命中该 archetype✅ 只为真正被雇的 archetype 建 app;后续 org 复用;由平台侧异步跑;人工图标/审批步骤在客户安装之前完成
C. 客户 admin 在渠道面板开开关时生成(PRD 现 R1客户点开关❌ 生成延迟 + O1 人工图标 + O3 审批全落在客户关键路径上,直接打脸 G2

4.3 建议:采用 B

App 身份按 archetype 生成一次,时机为"首次被任一 org 物化/雇用",由平台异步 provisioning 完成,与客户的安装动作解耦。 三点理由:

  1. 粒度对:app ↔ archetype(键 catalog_slug),非 per-org、非 per-clone。per-org 差异(如显示名 override)放 install/endpoint 层。顺带解决 archetype-vs-clone 的键歧义。
  2. 不浪费:360 个里真正被雇的可能只有几十个,B 只为这几十个建 app,避开舰队配额/政策风险。
  3. 把人工步骤挪出客户关键路径:图标上传、可能的 SuperAdmin 审批(O3)在"首次被雇用"这个平台侧环节由 ops 兜底;客户 admin 到渠道面板时,面对的是"已就绪、只差 OAuth"的 app,自助那步才可能真正 ≤5 分钟。

4.4 落点(代码位置已核实)

  • App 生成挂在 _materializeCatalogSpecialistorganizations.service.ts:2737),由 assignSpecialist(:2315)触发;做成幂等 per archetype(分布式锁 / 唯一约束,仅首次物化真正建 app,后续复用)。旁边已有一批同类 fire-and-forget provisioning(Gsuite、Vercel domain),并入即可,与 email alias 生成对称。
  • 注意:archetype 层没有 draft/published 生命周期(status 恒为 available),没有干净的"上架/发布"钩子——物化是最接近"投入使用前"的天然节点。
  • Install 层仍留客户 client/settings/channels 面板自助 OAuth,写 osa_channel_endpoints(待建)。客户面板只保留"安装/卸载"。

4.5 对 PRD 的具体改动

  • R1:把触发从"首个 org 打开开关时生成"改为"首次被任一 org 雇用/物化时、平台侧异步生成一次"。
  • §5.1:客户渠道面板的状态机去掉 "Generating",客户侧起点即 "Ready to install"(app 已由平台备好);生成态与失败态移到 ops 侧可见。
  • O3(是否需 SuperAdmin 审批):在 B 方案下自然归属 ops/平台侧,不再阻塞客户流程。

5. 仍需产品拍板的开放项(承接 PRD §12)

#问题建议倾向
O8跨 org 共享同一 workspace(新唯一键 (api_app_id, team_id) 使之技术可行,今天被 uq_integration_slack_team 禁止)需明确:放开(靠 per-app 隔离)还是保留 org↔workspace 排他。影响 R2 校验。
O6同 org 内两个 Specialist 同名(如两个 "Kai")→ 两个都叫 "Kai" 的 bot,授权页/@提及无法区分建议同 org 内做后缀消歧("Kai (KYC)"),不要留到上架才管;PRD 把它列为"不阻塞"偏乐观
app persona 的身份字段(名/头像/bio)以 archetype 还是 clone 为准(影响 R7 同步语义)采用 B 后以 archetype 为准,per-org override 落 endpoint 层

6. 给产品的三句话总结

  1. 能做,但它是后端地基工程:核心表 osa_channel_endpoints 和一整套 app 生成/路由改造尚未存在,需先让 ADR-030 Slack 子文档评审通过。
  2. 一个关键决策要先定:app 身份的生成时机——建议从"客户开开关时"前移到"首次被任一 org 雇用时、平台异步一次"(方案 B),这是几百 archetype 规模下唯一不撞 Slack 舰队配额、又不把人工步骤堆到客户面前的做法。
  3. 两处术语/事实要在 PRD 里纠正:区分 archetype 与 clone/OSA;明确不同 org 共享同一 app、各自独立的只是 install。