• 简体中文
  • 插件运行时与安全

    插件安全保护的是本地执行边界,不只是插件市场页面。Runner 可以持有第三方凭据、读取用户授权文件、启动二进制并产生外部写操作,因此每条远程指令都必须指向精确用户、设备 generation、不可变 release、connection、permission 和 payload。

    执行边界

    组件负责绝不负责
    Web/移动端 renderer展示目录、profile 名称、健康、配置和审批读取操作 secret、可执行路径或启动 provider
    API目录、安装、非秘密 connection 元数据、权限、设备公钥、challenge/ticket、签名 RPC、受控 GitHub ingress保存 device-local secret、执行插件或选择备用设备
    Worker运行生命周期状态机、解析当前授权、准备工具、经设备桥调度下载/启动 provider 或建立插件离线队列
    Redis 设备桥把有界短时请求路由到持有精确 WSS 的 API Pod持久化凭据或等待离线设备
    Electron Main隔离凭据窗口、系统安全加密、一次性本机 bootstrap把 secret 暴露给 renderer、API、日志或公开 DTO
    Runner校验授权、管理运行包缓存、托管 provider、记录入站 journal接受通用远程 shell 或复用其他渠道授权
    本地 Provider处理 provider API、MCP、Channel 或 Agent Runtime 协议访问 SciLaxy 数据库或成为服务器 sidecar
    sequenceDiagram
      participant Worker
      participant Authority as 当前授权
      participant Bridge as Redis 设备桥
      participant API as API / WSS
      participant Runner
      participant Desktop as Electron Main
      participant Provider
    
      Worker->>Authority: 解析 release、connection、permission、device
      Worker->>Bridge: 有界 provider 请求
      Bridge->>API: 路由到精确 connection
      API->>API: 签名 authority 与 body digest
      API->>Runner: plugin_rpc
      Runner->>Runner: 校验签名、revision、generation、过期时间
      Runner->>Desktop: 请求一次性本机 bootstrap
      Desktop-->>Runner: 解密后的本机 credential
      Runner->>Provider: tools/list 或 tools/call
      Provider-->>Runner: 闭合 result 或 error
      Runner-->>Worker: 与 request 绑定的响应

    指定设备离线、fenced、缺少已验证 runtime 或无法耐久保存入站事件时,插件不可用。系统不会选择其他设备、在服务器执行或把工作留到以后。

    设备信任链

    登记、租约、ticket 和 WSS 解决不同问题:

    机制生命周期证明内容
    设备登记长期,直到 fenced 或 revoked用户账户信任持有该 Ed25519 设备私钥的 Desktop;服务端只存公钥
    Lease challenge/renew短期并持续续租同一持钥进程在线,generation、channel、version、catalog 符合预期
    User-gesture ticket极短、单用途敏感设备动作来自近期显式用户操作
    WSS ticket极短、单连接指定设备可以建立 Runner 控制通道
    Signed RPC envelope单次请求一个 payload 只在精确授权集合和过期窗口内有效

    有效 Desktop 重连必须复用 enrollment。每次点击都重新登记会制造重复设备,无法修复租约或 readiness 问题。撤销会推进 generation,fence 旧 WSS、动作、Runtime Session 和调用。

    渠道信任资源

    每个 Desktop 发布渠道只读取一份渠道专属 trust resource。启动时必须验证:

    • 构建 channel 与信任资源 channel 一致;
    • 插件 WSS origin 与当前 backend origin 同源;
    • 路径精确为 /scilaxy/ws/v1/runner/device
    • 至少一把 Ed25519 公钥在当前时间有效且未撤销;
    • 服务端 signing key id 能映射到该渠道的可信公钥。

    Dev、Beta/Test、RC/UAT、Stable/Prod 不共享 runtime signing identity。跨渠道 fallback 会让较弱环境控制另一个渠道的本地 Runner;同源和精确路径校验则阻止代理漂移把本地执行通道指向无关 WebSocket。

    这些校验对执行边界是合理的,但产品必须区分 lease_failedtrust_config_invalidserver_signing_unavailable、transport、protocol 和普通 readiness blocker。安全严格不等于错误可以模糊。

    运行包

    可选第一方 provider runtime 不捆绑进 Desktop installer,也不在 API/Worker 容器执行。

    Desktop 构建携带与构建绑定的 plugin-runtime-manifest.json。首次使用时,指定 Runner:

    1. 解析 release 对应平台 archive;
    2. 下载到当前 channel 私有缓存;
    3. 校验 manifest、archive digest 和每个声明成员;
    4. 强制每个成员的 executable role;
    5. 原子发布已验证缓存项;
    6. 后续执行前继续复核缓存证据。

    下载失败、平台不支持、digest 不匹配或缓存缺失都会使能力不可用,不存在服务器 provider-host fallback。

    插件代码可以包含协议常量、schema version、规范 API path、闭合枚举和安全上限。产品目录项属于 builtin/catalog.json;环境 origin、channel、signing key 和部署 secret 来自 typed build/runtime configuration。Provider 协议 endpoint 只属于对应 adapter。

    凭据边界

    Device-local 配置使用 plugin_device_action,其中只有 provider key、profile label、目标 device/generation 和 request digest。动作未及时领取和完成会过期。

    飞书流程为:

    1. 用户选择 profile label 和在线 Desktop;
    2. Desktop 使用短期 user-gesture ticket 领取动作;
    3. Electron Main 打开隔离窗口,输入 cnglobal、App ID、App Secret;
    4. safeStorage 把记录加密到当前 channel 私有插件目录;
    5. Desktop 签名完成事实;服务端原子完成 action 并创建 ready connection;
    6. Runner 获得一次性本机 bootstrap,启动 provider 长连接。

    API、Worker、renderer 和公开 DTO 只获得 profile label、不透明 profile id、device id、connection/credential revision 和不可逆摘要。飞书与 GitHub device-local connection 的 plugin_connection.credential_id 保持为空,操作 secret 不进入 plugin_secret

    签名 Provider 调用

    内层 plugin-provider/1 当前只允许闭合 tools.listtools.call。外层签名信封绑定:

    • signing key id、owner、device、channel、app version;
    • device generation、connection id、nonce、request id;
    • installation、release、capability、authority digest;
    • connection/permission revision 与 credential version;
    • issued-at、expiry 与完整 body digest。

    Runner 在 provider I/O 前拒绝未知字段、重复 JSON key、过期请求、body 不匹配、revision 漂移、authority 漂移和 device-generation 漂移。

    外部效果

    潜在外部写操作表示为 plugin_effect_intent。不可变信封记录审批的精确内容:action、arguments、destination、release/tool/config 证据、connection/permission revision、device generation、runtime/workspace authority 和 provider idempotency key。

    状态会区分安全失败与结果不明:

    • failed_before_dispatch:没有跨过 provider 边界,可以安全重试。
    • uncertain:provider 可能已经接受写入,不得自动重放。
    • reconciled_succeeded / reconciled_failed:provider 证据已经解决歧义。

    外部写操作不能配置成永久允许,只能每次提示或拒绝。

    入站与 Webhook

    飞书通过本地 provider 的官方长连接工作。Runner 先记录事件 journal,再通过已认证设备通道发送并等待服务端耐久接收。服务端去重、校验当前 route authority,在一个事务中创建 inbound event/outbox 与 Turn,然后确认本地 digest。设备离线时,服务器不会代收或延迟投递。

    GitHub Webhook 是受控公网 ingress 例外:

    1. endpoint 绑定精确 installation/connection revision、device generation、release 和 authority digest;
    2. 服务端校验 X-Hub-Signature-256、event type、delivery id、大小和速率;
    3. 只有绑定设备在线才转发;
    4. Runner 耐久保存事件并返回 digest-bound ACK;
    5. 服务端收到 ACK 后才向 provider 返回成功;
    6. offline、fenced、timeout 或本地持久化失败返回可重试失败,不建立离线工作队列。

    服务器保存 webhook verifier material,因为公网 ingress 必须认证,但它不授予 GitHub API 权限。服务器不保存 GitHub Token 或原始 delivery body。

    安全不变量

    • 插件代码、操作凭据、进程、调用和访问的本地文件只存在于指定 Desktop/Runner。
    • 设备缺席必须明确不可用,绝不回退其他设备或云端执行。
    • Renderer、公开 DTO、API/Worker 日志和审计 metadata 不包含 device-local secret 或可执行路径。
    • Release、config、tool catalog、permission、connection、device generation 或 runtime 漂移时,旧异步工作在 provider I/O 前被 fence。
    • 入站成功要求耐久接收;外部写入歧义要求对账而非盲目重试。
    • 已删除 Session snapshot 表、旧 provider-host 执行、fallback wire format 和跨渠道 trust 均不受支持。