Skip to content

fix(plugins): 加固插件更新、服务与 MCP Gateway 生命周期#462

Merged
deepcoldy merged 11 commits into
masterfrom
fix/plugin-runtime-update-lifecycle
Jul 20, 2026
Merged

fix(plugins): 加固插件更新、服务与 MCP Gateway 生命周期#462
deepcoldy merged 11 commits into
masterfrom
fix/plugin-runtime-update-lifecycle

Conversation

@TGGgbone

@TGGgbone TGGgbone commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

一句话总结

收口插件运行时替换、PM2 服务、link 开发模式和 MCP Gateway 的生命周期,并把 #459 的会话识别修复合入本 PR。

关键变更

1. 安装、更新、卸载使用同一条受锁生命周期

  • 安装/更新前检查插件 PM2 service;service 仍运行时提示用户先显式执行 botmux plugin service stop <id>
  • runtime 替换、registry 更新和 MCP 私有描述符写入支持失败回滚。
  • 卸载在同一把跨进程锁内完成 service 状态检查、PM2 delete、materialized/skills/registry/binding/runtime 清理。
  • PM2 delete 报错或删除后记录仍存在时立即终止,插件文件、配置、绑定和 registry 保持不变。
  • PM2 删除按稳定的 plugin id 执行,即使插件 service 入口文件损坏也不会遗留孤儿进程。

2. PM2 与 link 开发模式

  • 清除宿主 PM2 环境中误传给插件 service 的小写 kill_timeout
  • link 插件由 PM2 watch dist/botmux-build,缺失时回退 dist
  • service 配置生成稳定 hash,定义变化时重建 PM2 app。

3. MCP Gateway 生命周期与会话身份

  • credential-bearing Gateway 运行在受信 worker 内;CLI 侧的 botmux mcp serve 只作为 stdio ↔ Unix socket relay,不读取 runtime snapshot 或插件密钥。
  • Gateway 随 CLI/worker 生命周期关闭所有下游 transport;持久后端恢复时若存在插件 MCP,会冷恢复 CLI 并创建新的 worker host/socket。
  • Gateway 统一通过 resolveSessionContext 恢复 Botmux session;Codex/Claude 显式转发 BOTMUX_SESSION_IDSESSION_DATA_DIR 和 Gateway socket 环境。
  • 默认与自定义 SESSION_DATA_DIR 均可解析;diagnostics 写入失败不会中断 MCP 服务。
  • 不同 bot/session 只聚合各自启用插件的 tools。

4. MCP 私密配置与隔离

  • 公共 plugins-registry.json 只保存 MCP 的 nametransportprivateRef
  • command/env/url/headers 写入 ~/.botmux/plugins/<id>/private/mcp.json,目录 0700、文件 0600
  • 旧 registry 内嵌定义在锁内原子迁移;迁移失败回滚且 fail-closed,畸形或泄漏字段不会继续被接受。
  • 每个 CLI generation 生成当前 session 的完整 plugin-mcp-runtime.json,但该 snapshot、private descriptor 和安装源 dist/mcp/index.json 均保持 host-only,不向 CLI 开放。
  • worker 为每个 session Gateway 创建独立 Unix socket 和 256-bit 随机 token;MCP 流量进入前执行带超时、长度限制和 timingSafeEqual 的认证握手。
  • Linux bwrap 仅绑定当前 Gateway socket 目录到私有 /run,同时隐藏 snapshot/private/install source。
  • macOS Seatbelt 先拒绝同 UID 的全部 bmcp-* Gateway 目录,再只读放行当前 session socket/token,并拒绝写入。
  • isolation marker 升级到 v5,旧持久 CLI 会冷启动一次,确保新的 snapshot/socket 安全规则生效。
  • 插件协议不变,dist/mcp/index.json 仍由插件作者按原约定提供。

影响面

  • 平台:Linux bwrap 与 macOS Seatbelt 的 MCP/read-isolation 路径均有调整。
  • CLI:带原生 MCP Gateway 配置的 Codex/Claude 家族受影响;其它 CLI 的插件 skills/service 路径保持不变。
  • 后端/会话:PTY、tmux、herdr、zellij 的新建、恢复和重启生命周期均经过 worker Gateway host;有插件 MCP 的持久会话在 worker/daemon 更换后冷恢复,避免复用失效 socket。
  • 插件运行时:插件安装、更新、卸载、PM2 service、link watch 以及 MCP snapshot/private store 均纳入此次回归。

验证

  • BOTMUX_NO_CLAIM=1 pnpm build:TypeScript、Dashboard bundle、dist audit 通过。
  • pnpm exec tsc --noEmit:通过。
  • 插件/MCP/隔离专项回归:12 files / 248 tests passed。
  • 真实 Linux bwrap E2E:默认和自定义 data dir 均完成 initialize -> tools/list -> tools/call;snapshot、private descriptor、其它 session snapshot 和安装源均不可读。
  • 同 UID socket 扫描攻击回归:scanned=1, accepted=0
  • 全量 unit:610 files passed,9598 / 9601 tests passed;3 个失败均为当前环境已有的本地时区 scheduler 用例,上一 head 可同样复现,本 PR 未修改该模块。
  • git diff --check:通过。
  • 与最新 origin/master 的本地 merge-tree:无冲突。
  • GitHub CI:通过。

PR 关系

@TGGgbone
TGGgbone requested a review from deepcoldy as a code owner July 14, 2026 09:25
@TGGgbone TGGgbone changed the title fix: block plugin updates while services run fix: harden plugin service and MCP lifecycles Jul 15, 2026
@deepcoldy deepcoldy changed the title fix: harden plugin service and MCP lifecycles fix(plugins): 加固插件服务与 MCP 生命周期——运行中禁止替换/卸载、宿主退出自动关网关、link 模式自动重启 Jul 18, 2026
@TGGgbone
TGGgbone force-pushed the fix/plugin-runtime-update-lifecycle branch from 702cd58 to 53b0049 Compare July 19, 2026 08:35
@TGGgbone TGGgbone changed the title fix(plugins): 加固插件服务与 MCP 生命周期——运行中禁止替换/卸载、宿主退出自动关网关、link 模式自动重启 fix(plugins): 加固插件更新、服务与 MCP Gateway 生命周期 Jul 19, 2026
@TGGgbone
TGGgbone force-pushed the fix/plugin-runtime-update-lifecycle branch from 53b0049 to 61698c5 Compare July 19, 2026 14:50
@TGGgbone
TGGgbone force-pushed the fix/plugin-runtime-update-lifecycle branch from 61698c5 to 8aeb043 Compare July 20, 2026 04:47
@deepcoldy
deepcoldy merged commit 6580a63 into master Jul 20, 2026
1 check passed
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