Skip to content

feat(lark): 允许已验证的 sibling bot 选择仓库 - #738

Merged
deepcoldy merged 8 commits into
deepcoldy:masterfrom
darylchen97:fix/peer-bot-repo-permission
Aug 5, 2026
Merged

feat(lark): 允许已验证的 sibling bot 选择仓库#738
deepcoldy merged 8 commits into
deepcoldy:masterfrom
darylchen97:fix/peer-bot-repo-permission

Conversation

@darylchen97

@darylchen97 darylchen97 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

改了什么

  • 允许同一 Botmux 配置中经过验证的 sibling bot 在新话题和线程回复里执行 /repo <path>,使委派机器人可以先选择目标仓库再启动会话
  • 将 sibling 身份校验收紧为多源证据:飞书 sender_type 机器人盖章、接收方 cross-reference、fresh bots 配置中的 union_id 精确且唯一匹配;缺失、过期、重复、损坏或不一致时全部 fail closed
  • 排除当前机器人自身和 apiOnly 配置;旧 registry 记录不能替代 fresh config
  • 修复飞书回复卡片页脚污染命令正文:兼容 split-font 页脚和 schema 2.0 中缺少 text_size 的独立 footer element,并用保留 marker 的严格签名识别避免误删普通链接
  • 增加权限 gate、真实 daemon handler 路由和 message parser 回归用例

为什么

多机器人委派时,sibling bot 需要在目标机器人上先执行 /repo 选择仓库,但原权限模型只允许 owner / allowedUsers,导致可信 peer 也无法完成仓库选择。另一方面,不能仅依赖显示名、缓存 registry 或消息里自带的 union_id 放权,否则真人或陈旧配置可能伪装成 peer。

真实飞书消息还会把 Botmux 回复卡片页脚带回 user_card_content;若页脚残留在 /repo 后面,整条消息会被当作普通 worker prompt,而不是 daemon 命令。因此本次同时补齐严格身份校验和页脚剥离,保证只有可信 sibling 的纯净 /repo 能进入仓库路由。

影响面

  • 权限扩展仅限 /repo/cd 及其他 owner-only daemon 命令语义不变
  • 新话题与线程回复共用同一套 fail-closed 身份约束;cross-reference 认识但没有飞书 bot 盖章的发送方不能借此执行 /repo
  • sibling 配置必须来自 fresh bots.json,且 union_id 只能唯一命中一个非自身、非 apiOnly bot
  • footer 处理只跳过带精确 element ID、markdown tag、允许的 text_size 和保留 marker 的独立 element;marker 文本、URL 或 text_size 任一不符时保留原正文
  • 未改变普通用户授权、session owner、worker prompt 或其他消息处理路径

验证

  • corepack pnpm test -- test/message-parser.test.ts:129 条通过
  • corepack pnpm test -- test/daemon-rename-route.test.ts:22 条通过
  • corepack pnpm test -- test/can-talk-daemon-commands.test.ts:23 条通过
  • corepack pnpm exec tsc --noEmit:通过
  • pnpm build:通过(含 domain audit、dashboard bundle 和 dist audit)
  • git diff --check:通过
  • 真实飞书线程 smoke:可信 sibling /repo 成功创建目标仓库会话且没有 footer prompt 污染;同一 sibling /cd /tmp 被拒绝,cwd 未变化
  • pnpm test 曾得到 12,520 passed / 27 failed / 6 skipped;27 个失败均为宿主环境问题(26 个来自旧 Git 不支持 git init -b,1 个来自 tmux wrapper shell)。最终 footer 增量未重新跑全量,因此本 PR 不宣称全量 suite green

darylchen97 and others added 7 commits August 4, 2026 20:30
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <noreply@bytedance.com>
Use the exact Botmux footer marker on botmux_reply_footer markdown elements so Lark user_card_content without text_size no longer leaks reply-card chrome into slash-command routing.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@darylchen97
darylchen97 requested a review from deepcoldy as a code owner August 5, 2026 01:40
@darylchen97 darylchen97 changed the title Allow verified sibling bots to select repositories feat(lark): 允许已验证的 sibling bot 选择仓库 Aug 5, 2026

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex 复审:请求修改

生产逻辑复核未发现新的阻塞:/repo 例外同时要求飞书 sender_type=app|bot 盖章、接收方 cross-ref 命中,以及当前 bots.json 中唯一的非自身/非 apiOnly sibling union_id 命中;缺配置、坏配置、旧 registry、重复 union 均 fail-closed。新话题和 thread 两个生产调用点也都只把飞书盖章结果传给这条例外,其他 daemon 命令没有被放宽。页脚 parser 的精确 marker 约束及 schema 2.0 text_size 缺失兼容也合理。

但有一个合并前必须修复的 P2 测试问题:test/daemon-rename-route.test.ts:177:205/repo 目标写死为作者机器上的 /data00/home/chenjihong.daryl/.../peer-bot-repo-permissionresolveRepoSelection() 会对显式路径执行 statSync(...).isDirectory();换一台机器路径不存在就进入 path_not_found,因此 pendingRepo 保持 trueforkWorker 不会调用。这是测试夹具问题,不是 production 路由回归,但会让 PR body 的「22 条通过」只在作者环境成立。

我在 PR 当前 head 8d65bc61f 上实际验证:

  • pnpm exec vitest run --project unit test/daemon-rename-route.test.ts test/message-parser.test.ts test/can-talk-daemon-commands.test.ts172 passed / 2 failed;其中 parser 129/129、权限闸 23/23,路由 20/22,失败正是上述两例。
  • pnpm build:通过(domain audit、tsc、dashboard bundle、dist audit 均绿)。
  • git diff --check origin/master...HEAD:通过。

请把这两个路由用例改为环境无关夹具:推荐 mkdtempSync 创建真实目录后拼进 /repo <tempDir>;若只想验证 footer→命令路由,也可以改成 bare /repo。修后请在非作者目录环境复跑并更新 PR 验证结果。申晗确认前仍不合码。

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@darylchen97

darylchen97 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

已按本次 review 修复测试夹具的环境依赖:

  • 两个 handler-level /repo <path> + footer 用例改为使用测试生命周期内创建并清理的真实临时目录;仍保留显式路径、repo launch/fork 与 forkWorker 空 prompt 断言。
  • 修复提交:67f65b5928841a9dc5b172b493988211b6083f04
  • RED:不存在路径下两个目标用例均失败(pendingRepo=true,2 failed / 20 skipped);GREEN:目标用例 2/2、完整 route 22/22、parser 129/129、permission gate 23/23 通过,tsc --noEmitpnpm buildgit diff --check 均通过。
  • 本次仅修改 test/daemon-rename-route.test.ts,未改生产权限或 parser 逻辑。

麻烦基于新 head 再复审一下,谢谢。

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex 复审通过

已在新 head 67f65b592 独立复核:相对原审阅 head 8d65bc61f 的增量只修改 test/daemon-rename-route.test.ts,使用 mkdtempSync 创建真实 repo 目录,并在 afterEach 清理;production 代码未变。该修复准确消除了此前唯一的 P2(作者机器绝对路径夹具),未发现新问题。

实际验证:

  • 三个相关测试文件合跑:174 passed / 174
  • daemon-rename-route.test.ts22/22
  • pnpm build:通过
  • git diff --check origin/master...HEAD:通过

原 Changes Requested 已由本次 Approve 收口。代码审阅无 blocking;仍遵守约定,申晗最终确认前不合码。

@deepcoldy

Copy link
Copy Markdown
Owner

合并前最终验证记录(head 67f65b5928841a9dc5b172b493988211b6083f04):

  • Claude 二次独立 review:通过,可合并;无 blocking / 无新问题。
  • Codex review:APPROVED;合并前再次确认 live PR head 未漂移。
  • pnpm test:787 files passed、1 skipped;12,555 tests passed、6 skipped。
  • pnpm build:通过。
  • PR:APPROVED + MERGEABLE;fork 无 CI,因此 mergeStateStatus=UNSTABLE。

申晗已明确授权“Claude 二次 review 没问题就合并”,现按固定 head SHA 执行 admin merge。

@deepcoldy
deepcoldy merged commit 1854ee3 into deepcoldy:master Aug 5, 2026
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.

2 participants