百积木文档
开发指南平台应用、模块与 Bundle 开发模块开发

模块事件与发布机制

区分事件声明、发布和订阅,并通过当前 Runtime 安全发布模块事件。

协议状态(2026-10-21):资源凭据领取与生命周期通知是已确认、尚未实现和定版的目标设计。插件在 AFTER_RESOURCES 按安装与资源主动领取自己的入口和凭据,回调不携带秘密;配置变化仍走生命周期通知,业务请求不解析引用。Backend 保留插件身份关联,轮换只撤销自己的旧凭据;ACS 不改,不做多插件协调。下文版本化示例保留用于现有协议维护,不能把新 API 字段发送给旧接收端。

事件参数的类型、必填与可空规则统一见类型系统。

模块事件是安装到 Runtime 的类型化业务能力。事件名和载荷由 Module 版本声明;发布方调用当前 Runtime 物化出的事件方法;订阅、触发和投递由独立资源管理。三者不是同一个动作:

module.json events 声明
  -> 创建不可变 Module 版本并随 Bundle 发布
  -> 安装到目标 Runtime,物化事件方法和发布能力
  -> 工作流或模块后端发布事件
  -> 已安装的 Event Trigger / 订阅消费事件

事件声明、事件发布和事件订阅是三份独立合同。因此,新增 events 不会自动发送事件,也不会自动创建 工作流、Webhook 或 Event Trigger。事件生产方必须 显式发布;需要自动触发后续动作时,还要把相应触发资源纳入 Bundle。

订阅端的配置和命令见 Event Trigger 绑定工作流与输入映射: 选择来源与工作流、用 =event.data... 映射启动输入、创建触发器版本并随 Bundle 安装。

地址从哪里来

事件发布地址不写死,也不由 Bundle 作者填写。Runtime 会根据目标环境和当前安装实例生成可调用的事件方法, 并同时生成作用于该 Runtime 的授权。应用代码和工作流都不能保存或推断内部主机、端口、服务地址、Runtime businessId 或事件平台凭据。

对调用方而言,事件方法与普通 Runtime 方法使用同一调用入口和授权边界;不存在需要开发者选择的“事件 专用网关”或额外协议。地址在环境迁移、重新安装或授权轮换后可以变化,所以必须使用当前 Runtime 物化并 交付的值。

从工作流发布

工作流使用 emit_event 节点。module 必须填写从目录选择的 {bundleId, moduleId}, eventName 必须是该 Module 当前版本声明的事件名,payload 必须符合其 paramDefinitions:

{
  "type": "emit_event",
  "id": "emit_order_status_changed",
  "name": "发布订单状态变更",
  "eventName": "orderStatusChanged",
  "payload": {
    "orderId": "{{input.orderId}}",
    "status": "{{context.order.status}}",
    "occurredAt": "{{context.order.occurredAt}}"
  },
  "idempotencyKey": "order-status:{{input.orderId}}:{{context.order.status}}",
  "timeoutSecs": 30,
  "module": {
    "bundleId": "example-orders",
    "moduleId": "orders"
  }
}

安装物化时,平台根据目标 Runtime 的资源 Owner 当前库存、精确资源版本及授权解析本包模块领域引用,并生成执行授权。Workflow 定义中不得出现 Runtime businessId、原始 URL 或 Authorization。通用 http 节点不能替代 emit_event:它不提供 模块领域引用解析、事件合同校验和 Runtime 作用域授权。

完整节点字段见工作流与 历史 Workflow Definition JSON Schema 5.0.0。

从独立模块后端发布

模块方法调用 Hosted Service 或其他独立后端,并由后端在业务事务成功后发布事件时,应让 Runtime 把发布 目标作为一对只读能力交付给后端:

  • <eventName>_event_url:当前 Runtime 生成的事件方法 URL。
  • <eventName>_event_authorization:只允许调用该 Runtime 能力的完整 Authorization 值。

如果 methodBody 需要引用这两个值,先在 module.json 的 propertyDefinition 中声明同名属性。URL 必须 只读;Authorization 必须同时只读且敏感:

{
  "propertyDefinition": [
    {
      "name": "orderStatusChanged_event_url",
      "type": {
        "@type": "JsonSchema",
        "schema": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "description": "由当前 Runtime 生成的 orderStatusChanged 发布地址。",
      "isSensitive": false,
      "readOnly": true,
      "required": false
    },
    {
      "name": "orderStatusChanged_event_authorization",
      "type": {
        "@type": "JsonSchema",
        "schema": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "description": "由当前 Runtime 生成的 orderStatusChanged 发布授权。",
      "isSensitive": true,
      "readOnly": true,
      "required": false
    }
  ]
}

再在调用后端的 HTTP 方法中用 position: "property" 映射。下列 Header 名是模块与自身后端约定的示例, 不是平台保留 Header:

{
  "header": {
    "X-Module-Event-Url": {
      "required": true,
      "position": "property",
      "key": "orderStatusChanged_event_url"
    },
    "X-Module-Event-Authorization": {
      "required": true,
      "position": "property",
      "key": "orderStatusChanged_event_authorization"
    }
  }
}

后端从受信任的模块调用中读取这对值,向 URL 发送符合事件 paramDefinitions 的 JSON,并把 Authorization 值原样放入请求头。URL 已经是完整事件方法地址;不要追加内部路径,也不要把 Authorization 改造成另一种 token。

POST <orderStatusChanged_event_url>
Authorization: <orderStatusChanged_event_authorization>
Content-Type: application/json

{
  "orderId": "order-123",
  "status": "approved",
  "occurredAt": 1788537600000
}

从 Bundle 插件的异步 Worker 发布

跨请求运行的 outbox 或后台 Worker 使用插件身份 Token,按安装身份、Module Locator 和 eventName 主动查询当前事件调用能力。它与 interface 属性使用同一个凭据解析接口;无需事件自引用属性或额外授权开关。 生命周期中读取 access[eventName] = {url, token} 并保存为受保护的事件运行配置;每次投递和业务重试直接使用本地完整 URL 与 Token,不重新解析。

具体声明、Bundle 插件授权和重试规则见 Bundle 插件异步发布事件。

安全与生命周期规则

  • URL 与 Authorization 是当前 Runtime 颁发的一对能力,必须成对使用、成对更新;不得跨工作区或跨 Runtime 复用。
  • 不允许终端用户提交任意事件 URL 或 Authorization。浏览器、表单、工作流输入和普通业务 API 都不应包含 这两个字段。
  • Authorization 不进入日志、响应、事件载荷或任务参数。方法调用交付的能力只用于当前操作; 跨请求异步投递的事件凭据在 Bundle 生命周期中解析并保存到受保护的运行配置,后续生命周期负责更新或清理。
  • 后端不得按工作区 ID、项目 ID、域名规则或环境名称拼接发布地址,也不得直接调用内部事件服务。
  • 发布成功只证明事件已被接受;后续动作还取决于目标 Runtime 中是否安装并启用了匹配的 Event Trigger 或 订阅,以及其投递与重试状态。

发布前验证

  1. 从精确 ModuleVersion 回读事件名和 paramDefinitions,确认来自预期 Git commit。
  2. 检查 Bundle Manifest 精确引用该 ModuleVersion,并包含需要的 Event Trigger 资源。
  3. 安装或升级 Bundle 后,从目标 Runtime 回读事件方法;不要只检查项目工作区文件。
  4. 分别验证工作流 emit_event 和后端回调所需的入口;不使用生产凭据做本地硬编码测试。
  5. 发送一条带稳定业务幂等键的测试事件,再检查订阅触发、Webhook/动作结果和失败重试。

事件声明的 JSON 结构与版本演进规则见模块定义开发。

本页内容