Skip to content

chore(setup): 移除飞书未开放的 chat-tag 权限申请,消除 setup 警告 - #1233

Merged
deepcoldy merged 1 commit into
masterfrom
wt/botmux-setup-warning-warnin
Sep 3, 2026
Merged

chore(setup): 移除飞书未开放的 chat-tag 权限申请,消除 setup 警告#1233
deepcoldy merged 1 commit into
masterfrom
wt/botmux-setup-warning-warnin

Conversation

@deepcoldy

Copy link
Copy Markdown
Owner

改了什么

src/setup/lark-scopes.json 的 tenant 清单删除两条无法映射的权限:im:tag:writeim:biz_entity_tag_relation:write(171 → 169)。同步更正 6 处把它们描述成「部分租户权限目录没有」的注释与用户文案。

为什么

botmux setup / 启动期权限自愈每次都打印:

Warning: 2 scopes are not present in the Open Platform catalog and will be skipped: im:biz_entity_tag_relation:write, im:tag:write

不是「多申请了权限」,而是这两个名字在开放平台权限目录里根本不存在,连申请都申请不上。它们是 chat-tag(企业自定义群标签)模式用的,而 im/v2/tags + im/v2/biz_entity_tag_relation 是飞书尚未开放的能力(API Explorer 标注 not available yet)。#895 已因此把默认标签模式从 chat-tag 改回 feed-group,但权限清单里这两行没跟着删。

留着零收益(目录里没有,setup 也申请不上),却有三处成本:

  1. 每次 setup / 自愈刷一条 warning;
  2. skippedScopeCount 恒为 2,把 bot-registry.ts 里「0 项权限已导入」诊断的第三条分支——真的「所有必需权限已在应用清单中」——永久遮蔽
  3. 缺权限时给 owner 私信一个「点此一键开通」链接,而那个权限在后台搜都搜不到

原文案说「部分租户权限目录无该权限」,实测比这更强也更该讲清:能力本身没开放。Dashboard 下拉仍保留 chat-tag 选项,只是文案如实说明现状;飞书哪天开放该能力,把两行加回来即可(已在 feed-group-tagger.ts 头注写明触发条件)。

第二处收益:解除对诊断分支的遮蔽

bot-registry.ts 那段三分支 ternary 的真实取值复算:

场景 BEFORE (skipped=2) AFTER (skipped=0)
配置本就齐全 0 项权限已导入——这 2 项不在当前租户的开放平台权限目录中 所有必需权限已在应用清单中
正常补权限 3 项权限已导入(2 项跳过) 3 项权限已导入

第一行原本结构上不可达,现在能如实报出。

影响面

  • 不影响任何现有功能:这两个 scope 不在 BOTMUX_REQUIRED_SCOPES / DOC_FEATURE_SCOPES / VC_MEETING_*(共 22 项)任何校验清单里;运行时代码不读它们(仅出现在注释),缺失不会触发「缺权限」告警。
  • 跨会话类型:只涉及 p2pMode=group 的会话群打标签路径;话题会话 / 群会话 / adopt / restore 均不受影响。chat-tag 模式此前在本租户就必然失败,删清单项不改变这一点(失败路径与 nudge 节流逻辑原样保留)。
  • 跨 CLI / 跨后端:无——纯开放平台权限清单 + 文案,不碰 adapter、PTY、tmux 或任何 CLI 共用层;PtyBackend / TmuxBackend 均不涉及。
  • 跨平台:无平台相关分支。
  • 与在飞 PR 的关系feat(lark): 支持原生 Slash 命令注册 #842 也改 lark-scopes.json,但加的是文件开头 application: 区的 application:app_slash_command:*,与本 PR 删除的 im: 区两行不重叠,不会冲突。

验证

构建 / 类型bun run build 绿;npx tsc --noEmit exit 0。

测试:目标测试 816/816 通过setup-verify-permissionssetup-open-platform-automationsession-groups-storefeed-group-tagger-self-healsetup-app-icondashboard-i18ndashboard-i18n-c5bot-registry)。其中两个核心文件核对过 it() 声明数 26+35=61 与实跑 61 一致,排除「静默不跑」。

对真实开放平台目录做 A/B(复用缓存 web session 调 /developers/v1/scope/all/<appId>,走生产的 extractOpenPlatformScopeEntries + mapManifestScopesToOpenPlatformIds,而不是构造 mock):

=== cli_a93efb8ec6619cce (catalog 1076) ===
BEFORE (master): tenantIds=169 userIds=130 missing=2 [...] -> WARNING PRINTED
AFTER  (this PR): tenantIds=169 userIds=130 missing=0 []   -> WARNING silent

=== cli_aa1b834eca781bcd (catalog 1076) ===
BEFORE (master): tenantIds=169 userIds=130 missing=2 [...] -> WARNING PRINTED
AFTER  (this PR): tenantIds=169 userIds=130 missing=0 []   -> WARNING silent

关键点:mapped id 数前后都是 169,证明删掉的两条本就贡献 0 个 ID,没有丢任何真实权限

阴性对照(排除「探测链路坏了导致什么都找不到」):同一次探测里 im:message → id 20001im:feed_group_v1:write → id 1015252 均正常解析。

目录全量核查:1076 条里 im: 权限 67 条,无一条名字含 "tag";全目录匹配 /tag|label|biz_entity/i 的只有 drive:file.meta.sec_label.read_onlydocs:secure_label:readonlydocs:secure_label:write_only,与本能力无关。

⚠️ 上述测量在单一租户(一份 web session 下的两个 app)完成。因此注释与文案统一表述为「权限目录里搜不到」,断言「所有租户都没有」——能力未开放是从 API Explorer 标注与 #895 的既有结论得出,不是我这次测出来的。

先例

🤖 Generated with Claude Code

## 改了什么

从 `src/setup/lark-scopes.json` 的 tenant 清单删除两条无法映射的权限:
`im:tag:write`、`im:biz_entity_tag_relation:write`(171 → 169)。
同步更正 6 处把它们描述成「部分租户权限目录没有」的注释与文案。

## 为什么

`botmux setup` / 启动期权限自愈每次都打印:

    Warning: 2 scopes are not present in the Open Platform catalog and
    will be skipped: im:biz_entity_tag_relation:write, im:tag:write

不是「多申请了权限」,而是这两个名字在开放平台权限目录里**根本不存在**,
连申请都申请不上。它们是 chat-tag(企业自定义群标签)模式用的,而
`im/v2/tags` + `im/v2/biz_entity_tag_relation` 是飞书**尚未开放**的能力
(API Explorer 标注 not available yet)。#895 已因此把默认标签模式从
chat-tag 改回 feed-group,但权限清单里这两行没跟着删。

留着它们零收益(目录里没有,setup 申请不上)却有三处成本:

1. 每次 setup / 自愈刷一条 warning;
2. `skippedScopeCount` 恒为 2,把 `bot-registry.ts` 里「0 项权限已导入」
   诊断的第三条分支(真的「所有必需权限已在应用清单中」)**永久遮蔽**;
3. 缺权限时给 owner 私信一个「点此一键开通」的链接,而该权限搜都搜不到。

原文案说「部分租户权限目录无该权限」,实测比这更强也更该讲清:能力本身
没开放。Dashboard 下拉仍保留 chat-tag 选项,只是文案如实说明现状;飞书
哪天开放该能力,把两行加回来即可(已在 feed-group-tagger.ts 头注写明)。

## 影响面

- **不影响任何现有功能**:这两个 scope 不在 `BOTMUX_REQUIRED_SCOPES` /
  `DOC_FEATURE_SCOPES` / `VC_MEETING_*`(共 22 项)任何校验清单里,运行时
  代码不读它们,缺失不会触发「缺权限」告警。
- **跨会话类型**:只影响 p2pMode=group 的会话群打标签路径;话题会话、群
  会话、adopt/restore 均不涉及。chat-tag 模式此前在本租户就必然失败,删除
  清单项不改变这一点(失败路径与 nudge 逻辑保持原样)。
- **跨 CLI / 跨后端**:无——纯开放平台权限清单 + 文案,不碰 adapter、PTY、
  tmux 或任何 CLI 共用层。
- **跨平台**:无平台相关分支。

## 验证

- `bun run build` 绿;`npx tsc --noEmit` exit 0。
- 目标测试 816/816 通过(setup-verify-permissions、
  setup-open-platform-automation、session-groups-store、
  feed-group-tagger-self-heal、setup-app-icon、dashboard-i18n、
  dashboard-i18n-c5、bot-registry)。其中 61 条的两个文件已核对
  `it()` 声明数 26+35=61,与实跑数一致(非静默跳过)。
- **对真实开放平台目录做 A/B**(复用缓存 web session 调
  `/developers/v1/scope/all/<appId>`,走生产的 `extractOpenPlatformScopeEntries`
  + `mapManifestScopesToOpenPlatformIds`):

      catalog 1076 条
      BEFORE: tenantIds=169 userIds=130 missing=2 -> WARNING PRINTED
      AFTER : tenantIds=169 userIds=130 missing=0 -> WARNING silent

  两个 app 结果一致。关键点:**mapped id 数前后都是 169**,证明删掉的两条
  本就贡献 0 个 ID,没有丢任何真实权限。
- 阴性对照:同一次探测里 `im:message` → id 20001、`im:feed_group_v1:write`
  → id 1015252 均正常解析,排除「探测链路坏了导致全部 ABSENT」。
- 目录全量核查:1076 条里 `im:` 权限 67 条,无一条名字含 "tag";全目录匹配
  /tag|label|biz_entity/i 的只有 docs/drive 的密级标签,与本能力无关。

⚠️ 上述测量在单一租户(一份 web session 下的两个 app)上完成,故注释与文案
统一表述为「权限目录里搜不到」,未断言「所有租户都没有」。
@deepcoldy

Copy link
Copy Markdown
Owner Author

独立 Review 结论:✅ 可合

我是被拉来独立复审的 pi(非作者)。在与 origin/master(81433a720)的真实合并树上做了完整验证,不是只看 diff。

独立验证(合并树,非 mock)

  • 合并git merge origin/master → 0 冲突(GitHub 也报 MERGEABLE)
  • 类型tsc --noEmit exit 0
  • 相关测试 816/816setup-verify-permissionssetup-open-platform-automationsession-groups-storefeed-group-tagger-self-healsetup-app-icondashboard-i18ndashboard-i18n-c5bot-registry 全绿
  • 全量测试对照:PR 合并树 10 failed / 4 files,干净 master 11 failed / 5 files——失败集同构且全部是环境性(root 下 EACCES 被绕过、bwrap 不可用、tmux/fifo、进程组 flaky),两棵树在 scope/setup/i18n/dashboard 相关测试上零失败
  • 清单计数:tenant 171→169、user 130 不变,diff 只删 tenant 桶两行,无夹带

对作者三个问题的回答

1. 删权限的完整性:论证充分,我补查了所有字面名依赖路径,均无:

  • BOTMUX_REQUIRED_SCOPES / DOC_FEATURE_SCOPES / DOC_WATCH_SCOPES / VC_MEETING_* 共 22 项逐条核对,不含这两个名字
  • manifest 一致性测试方向是「required ⊆ manifest」,删 manifest 项不可能打破它
  • buildScopeUpdatePayload 只发映射后的 ID(appScopeIDs/userScopeIDs),不发名字
  • ~/.botmux/lark-scopes.json只写的(writeScopesJsonToConfigDir 写出供人手动导入),全仓没有任何代码读回它 → 存量 bot 的旧副本零行为差异,下次 setup 自动覆盖
  • nudge 链接(scopeEnableLink)的 scope 名来自运行时 99991672 错误体,与 manifest 无关,chat-tag 失败路径原样保留

2. 措辞:收得够。 没有「所有租户都没有」式残留全称判断。普遍性表述(「飞书尚未开放」)都挂在 API Explorer 标注 / #895 既有结论上,用户可见文案全部带对冲(「多半」「most likely」「若你的租户已能搜到该权限」)。

3. nudge 文案与 Dashboard 选项:认可。 链接保留是对的——它是 console 搜索 URL,权限不存在时搜索结果为空、无害,却给飞书未来静默开放留了逃生舱;文案把「多半开通不了,建议切 feed-group」提到前面、链接降为兜底,优先级正确。Dashboard 保留 chat-tag 选项也正确:模式在代码和存量配置里都还在,删选项只会孤儿化已有配置,标注「尚未开放」如实反映现状。

发现的问题(均非阻断)

① PR 描述「第二处收益」不准确,建议更正描述(代码不用动):

  • 那段三分支 ternary 在 event-dispatcher.ts(L333-341),不在 bot-registry.ts——后者全文没有 skippedScopeCount 引用。
  • 更重要的是 BEFORE 状态不对:self-heal 路径在 L297 先用 filterScopeManifest(readDefaultScopeManifest(), wantedScopeNames) 把清单裁成「缺失的 required 项」,而这两个 scope 不在任何 required 清单里 → 它们根本到不了这条路径的 skippedScopeCount,分支③此前就可达(master 上 setup-open-platform-automation.test.ts 那条「配置本就齐全」用真实 manifest 的锁生产测试就是证据,它在 master 上也是绿的)。
  • 真正的第二收益描述里没写:Dashboard onboardingbot-onboarding.tsx:351permissionSkipped 指示)走的是完整 manifest,新建 bot 之前会显示「2 项跳过」,现在归 0。加上 botmux setup(cli.ts:682)的「另有 2 项…已跳过」,这两处才是 skipped=2 的真实消费点。

② Nit: test/setup-open-platform-automation.test.ts:3298 注释「默认 171+130 项」过时(应为 169+130)。纯注释,测试本身读真实 manifest 自动适配,不影响结果。


代码本身 LGTM,上述两点不阻断合并。

@deepcoldy
deepcoldy merged commit bcfa675 into master Sep 3, 2026
9 checks passed
@deepcoldy

Copy link
Copy Markdown
Owner Author

更正:本 PR 描述里「第二处收益」一节有误

复审指出,我原描述中的这段是错的,在此更正并留档(该 PR 已合入 bcfa67557,描述本身进了公开记录,不改会误导后来人):

① 文件归属写错了。 我写「bot-registry.ts 里那段三分支 ternary」——实际在 src/im/lark/event-dispatcher.ts:334-339bot-registry.tsskippedScopeCount 命中数为 0,是我张冠李戴。

② 「分支③此前结构上不可达」这个说法不成立。 启动期权限自愈路径在调用 automation 之前先用 filterScopeManifest 把 manifest 裁成「缺失的 required 项」(event-dispatcher.ts:296-297),而 BOTMUX_REQUIRED_SCOPES(13 项)不含这两个 scope——所以它们在自愈路径上根本到不了 skippedScopeCount,分支③此前就是可达的(master 上「配置本就齐全」的生产链路测试一直是绿的)。我把「走完整 manifest 的路径」的行为错误地套到了自愈路径上。

skipped=2 的真实消费点(都走完整 manifest,此前确实每次都被置位,现在归零):

消费点 影响
cli.ts:682 botmux setup 打印「另有 2 项当前租户目录中没有,已跳过」
bot-onboarding.tsx:351 Dashboard 新建 bot 的 onboarding 里显示「2 项跳过」
open-platform-outcome.ts:40 skippedScopeCount > 0 参与 hasWarnings ⟹ 结果状态恒为 ready_with_warnings 而非 ready

第二、三条是我原描述完全没提到的——尤其第三条,等于每次 setup 的最终状态都被打上 warning 标记。所以这个 PR 的实际收益比我写的更大,但不是我原来说的那个机制。

PR 的代码改动与验证结论不受影响:删除的两个 scope 确实无法映射(live 目录 A/B:tenantIds 前后都是 169,未丢任何权限),warning 确实消除。错的只是我对「第二处收益」的机制解释。

一个附带的 nit(注释里过时的 manifest 计数 171→169)已单独提 #1235 修。

deepcoldy added a commit that referenced this pull request Sep 3, 2026
#1233 删掉飞书未开放的 im:tag:write / im:biz_entity_tag_relation:write
后,tenant 桶从 171 降到 169,但 setup-open-platform-automation 里描述
「默认 manifest 有多少项」的注释没跟着改,读起来会让人以为清单里还有那
两条。纯注释,无行为变更。

复审发现(#1233 review 的非阻断 nit)。

验证:test/setup-open-platform-automation.test.ts 154/154 通过;
实测 manifest 现为 tenant 169 + user 130,与更正后的注释一致。
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

🚀 Released in v3.18.14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant