百积木文档
开发指南Bundle 管理器开发

Bundle 生命周期与资源交付协议

使用来源 Bundle 管理器关系和完整安装身份,在生命周期中接收、保存并更新调用凭据,供业务运行使用。

本页使用公开 SDK 25.2.0、生命周期 15.0.0 和网关资源凭据 API 6.0.0。首次签发原文随 AFTER_RESOURCES 下发;已有凭据不再下发原文,丢失时显式申请新 token。各环境须完成对应服务和登记切换后使用,源码或文档发布不代表环境已经激活。

本页记录 SDK baijimu-bundle-plugin =25.2.0 的单向生命周期交付。安装、升级、配置和卸载不依赖管理器反向完成回调;同步响应仍须校验实际业务结果。

协议选择与环境边界

协议版本来自已认证管理器的注册声明 bundleExecution.protocols,公共生命周期和管理凭据会话的请求及响应 data 不携带 contractVersion;资源操作凭据的独立合同 1.0.0 则显式携带版本,见资源凭据交付与补签。 CModel 外层仍使用 contractVersion: "1.0.0"。Adapter 到业务后端的自有业务合同仍保留自己的 contractVersion,不能与公共管理器载荷混用。当前 BundleDefinition 不包含管理器声明;通信格式只由管理器当前登记决定。旧 Bundle 中的历史协议字段不参与选择,也不要求旧 Bundle 升级。

本页生命周期示例仍使用已发布的 SDK 25.2.0。独立引用解析接口已经退役,reference 不再是一项需要实现的管理器协议。有效协议分别为:

注册字段本页示例所选协议
lifecycle15.0.0
credentials1.0.0
propertyWrite2.0.0

SDK 25.2.0 已实现生命周期 15。bundle_plugin_lifecycle_version() 固定表示历史生命周期 11, 不是“当前最新版本”查询。生命周期 15 使用 bundle_plugin::resource_operations_lifecycle_version(), 请求和响应类型使用 resource_operations::lifecycle::{Request, Response}; 引用值使用 resource_reference::canonical::ReferenceDescriptor。不得把旧 Request 类型强转为新版,或只修改登记数字。 SDK 26.x 的 Manager 命名迁移独立进行;本组示例使用 25.2.0 已发布的 Plugin 字段及路径,不声明运行服务已经切换命名。

Owner 按登记的准确版本选择一次 Codec,不从业务字段猜测版本,不在失败后尝试另一个版本。 独立引用解析接口已经删除,不能根据旧 SDK 中的 reference 字段实现、调用或恢复解析服务。 生命周期里的 references 仍是引用配置数据,随生命周期 15 交付;资源凭据 issue/rotate 和平台内部绑定、路由保持独立职责。

SDK 27.0.0 已删除 protocols.reference 和独立解析请求、响应及 Codec,登记类型只保留上述三项。 SDK 25/26 的登记 DTO 仍保留历史 reference 元数据;旧格式示例携带该值仅为满足其既有传输类型, 不表示存在引用解析能力。三字段登记须在目标环境的登记 Owner、读取方和 CLI 完成对应切换后使用; SDK 发布不代表平台已经完成清理,也不能只从旧 JSON 删除字段后交给尚未升级的接收方。 注册格式与凭据会话分别见注册与管理和 首次握手与凭据轮换。这两个页面各自拥有管理操作和凭据交付细节,其他教程只引用规范。

开发按本页合同实现。正式执行时,由平台解析方和管理器校验注册协议;缺少注册声明或协议不匹配应明确失败,不自动退回旧请求格式。 发布验收仍须验证部署与实际业务结果,SDK、CLI、源码或文档发布不能替代上线证据。

业务实例所有权

Bundle 管理器负责自己业务实例的创建、查询、升级、幂等和失败残留清理。平台调用生命周期操作并处理真实结果,不枚举业务实例,也不要求管理器提供库存查询接口。删除库存查询不免除卸载清理责任,失败或结果未知必须如实返回。平台原生资源由各自 Runtime Owner 管理。

安装身份与执行语义

installation 包含安装环境 environmentKey、applicationRuntimeId、workspaceId、 bundleInstallId、安装人 installedBy 和 Bundle 来源 bundle.environmentKey + bundle.bundleId。 安装环境与 Bundle 来源可以不同,所有定位均由 Runtime 提供。

installedBy 是安装目标环境中的正整数用户 ID,由 Runtime 从安装记录读取。 平台新建请求的所有操作和阶段均携带该字段;升级、配置和重试保持原安装人,DETACH 清理使用原安装快照。 它不是发布方 ownerUserId、当前操作人 requestedBy,也不是资源物化的 executionSubjectUserId。 SDK 使用 Option<i64> 兼容旧消息和历史快照中缺少安装人的情况,缺失时不得用其他用户替代。 业务管理器需要以安装人创建初始管理员时,必须先确认该值存在;后续调用不能重复覆盖成员权限。 响应关联始终校验稳定安装身份,双方都提供安装人时必须一致。

生命周期 15 的 Request 按公开 SDK 接受附加字段;附加字段不参与协议选择或授权。Response 及嵌套类型各自遵循 SDK 的解析规则。 示例不在生命周期业务体增加 contractVersion。已知字段类型、必填字段、枚举、登记协议、授权范围和响应身份关联仍必须校验。 operation.requestedBy 是本次操作的正整数用户 ID,与原安装人 installation.installedBy 分别提供,不能互相代填。

operationType + stage 表达操作与资源执行时机:

字段允许值
operation.operationTypeINSTALL、UPGRADE、CONFIGURE、DETACH
stageBEFORE_RESOURCES、AFTER_RESOURCES

operation.operationId、安装身份、管理器身份和阶段由平台关联。管理器按这些身份协调自己的业务状态, 不能另造安装记录或改变平台的操作结果。调用结果不确定时,Runtime 使用相同的操作身份和阶段 重复调用同一生命周期请求。管理器必须安全处理重复执行并返回相应属性;已完成的业务变更不得重复创建资源。

executionSequence 是 Runtime 的正整数操作顺序,同一操作重试保持不变。 失败只保留当前 Bundle 安装实例的冲突保护,不占用其他 Bundle;DETACH 可以接管该安装已停止的失败操作。所有者的顺序校验必须覆盖实际业务写入。 详见失败与重试。

配置变更的参与范围

Module 属性、完整配置、网关域名和 Bundle 内 Agent/Timer 配置统一进入 CONFIGURE。 Runtime 先比较实际变化,再依据完整 Locator 和资源 Owner 的当前实际库存确定参与的 Bundle,随后由来源 Owner 解析这些 Bundle 的当前管理器关系。 没有管理器的已安装 Module 仍有真实 CONFIGURE 所有者;无变化不生成操作,也不会扫描无关 Bundle 的历史管理器声明。 Module 或管理器资源缺少合法安装归属时明确报错。没有 Module 身份和来源 Bundle 归属的 Runtime 本地服务按原本地配置合同保存,不伪造 Bundle 安装。 业务实例标识由业务 Owner 按完整安装归属管理。旧 instanceRefProperty 不再是作者授权声明,不能通过恢复该字段建立权限或推导管理器关系。

未绑定引用与失败策略

credentialProperties 是引用配置投影范围,不是必填绑定清单,也不授予 token。资源调用凭据由当前来源关系及目标安装、本包资源归属确定,不以该通信字段授予权限。Interface 属性的 required: true 和省略 defaultValue 都不要求安装前绑定。Runtime 允许定义在引用为空或部分绑定时安装,管理器必须接受 相应的合法请求;普通业务数据、身份、归属、授权和协议格式仍分别校验。

当前获准引用配置生命周期行为相关业务调用
首次安装未绑定,references: {}初始化本管理器业务实例,保存未绑定配置,正常确认阶段使用该引用的功能明确失败
仅部分属性已绑定保存已绑定部分,不要求授权清单中的其他属性同时存在已绑定功能按其合同执行,缺失引用的功能明确失败
换绑或清空单值引用完整替换该资源的获准引用配置;移除不再存在的旧目标及本地访问配置使用新绑定;清空的属性明确失败
显式空 Map/List保留合法空集合及其选择关系,不伪造目标选择不存在的成员时明确失败
重复通知按安装、操作、阶段和执行顺序幂等确认不重复创建业务实例,不在业务重试中解析引用
身份错误、越权资源、非法引用格式或真实执行失败返回明确错误,保留 FAIL_FAST不得把失败配置报告为可用

每个请求中已投影资源的 references 是该资源当前完整的获准引用配置,不是新增项补丁。 同一资源此前存在、本次已不在投影中的引用必须移除,不能与旧本地配置做只增不减的合并。 未授权或未投影的其他资源不在本次处理范围内,不能因某个资源为空就清空其他资源。

BEFORE_RESOURCES 完成本管理器在资源提交前的必要业务初始化,不以外部引用全部绑定为前提; AFTER_RESOURCES 按当前已提交配置确认本地引用状态。没有绑定的属性不需要伪造调用地址或凭据。 当前引用为空时按未绑定处理;实际鉴权或 Owner 查询失败不能伪装为未绑定。

FAIL_FAST 处理真实失败,不定义哪些业务状态属于失败。禁止仅因合法未绑定而抛出 logical reference is required、要求先绑定再安装,或建议安装者放宽失败策略。 完整 CLI 流程见服务引用完整操作示例, 管理器实现和测试见直接实现 Bundle 管理器协议。

Bundle 管理器通信边界的版本化视图

来源 Bundle 关系确定唯一管理器,直接覆盖该安装的全部本包资源及属性;平台仍校验完整管理器身份、当前关系、目标安装及本包归属。 下面仅展示 SDK25.2 生命周期15使用的视图,由平台按本包资源与当前登记构造。readProperties、writeProperties、credentialProperties 等通信字段不是作者配置,也不是独立权限来源;不得要求作者维护名单。 其中的 protocolVersion、order 和 failurePolicy 同样不能复制到 BundleDefinition,不能用这些字段恢复旧插件数组执行链。正式通信版本与 BundleDefinition 内容协议分别演进。

{
  "pluginId": "tenant-provider",
  "protocolVersion": "15.0.0",
  "order": 0,
  "failurePolicy": "FAIL_FAST",
  "configuration": {
    "schemaVersion": "1.0.0",
    "values": {}
  },
  "resources": [
    {
      "resource": "publisher/sales/MODULE/customer",
      "readProperties": [
        "region"
      ],
      "writeProperties": [
        "tenantId"
      ],
      "credentialProperties": [
        "inventory"
      ]
    }
  ]
}

生命周期请求

{
  "pluginId": "tenant-provider",
  "executionSequence": 1,
  "installation": {
    "environmentKey": "consumer",
    "applicationRuntimeId": "runtime-a",
    "workspaceId": 42,
    "bundleInstallId": "installation-a",
    "installedBy": 25,
    "bundle": {
      "environmentKey": "publisher",
      "bundleId": "sales"
    }
  },
  "operation": {
    "operationId": "operation-a",
    "operationType": "INSTALL",
    "currentVersion": null,
    "targetVersion": "1.0.0",
    "requestedBy": 42
  },
  "stage": "BEFORE_RESOURCES",
  "configuration": {
    "schemaVersion": "1.0.0",
    "values": {}
  },
  "resources": {
    "publisher/sales/MODULE/customer": {
      "action": "INSTALL",
      "currentVersion": null,
      "targetVersion": "1.0.0",
      "properties": {
        "region": {
          "@type": "Data",
          "value": "north"
        }
      },
      "references": {
        "inventory": {
          "@type": "ServiceReference",
          "resourceLocator": "publisher/inventory/MODULE/catalog"
        }
      }
    }
  }
}

configuration.schemaVersion 属于管理器自己的业务配置合同,不等于生命周期版本。 resources 的键为 ResourceLocator,范围由当前来源关系及该安装的本包资源确定,新增本包资源自动纳入。 properties 的每项输入和输出都必须是 {"@type":"Data","value":...},不接受裸值。 Runtime 按 Module 的属性定义校验 value,再写回一次 Data 包装,不递归猜测业务对象内的 @type。 SDK 的 decode_data() 用于读取业务值,from_data_values() 用于把业务值编码为输出; decode() 与 from_properties() 保留完整的类型包装。 引用始终是逻辑 ServiceReference、Map 或 List,不附带调用地址或密钥。

响应

成功响应使用完整 CModel envelope:外层 contractVersion: "1.0.0"、errorCode: "0" 和 data。 data 原样关联请求的 pluginId、installation、operation、stage、executionSequence, 并返回 outcome 与 resources。

outcome 为 NOT_APPLIED、APPLIED、VERIFIED、FAILED 或 UNKNOWN。 resources 按 ResourceLocator 返回获准写入的业务 Data 属性,例如业务租户编号,以及管理器自己签发、 按安装隔离的业务服务 Token。敏感业务属性必须声明 isSensitive: true,并满足本包资源属性定义及字段类型合同;不要求作者为管理器配置 writeProperties 权限名单。通信视图中的 credentialProperties 仅用于引用投影。 不能回写引用属性、平台引用解析返回的 access 地址与 Token,或其他身份的共享管理凭据。 业务凭据的签发、轮换、撤销和保存边界见Bundle 管理器自有业务凭据。 Runtime 校验输出范围并决定安装进度。UNKNOWN 不能当成功处理。不得只返回裸 data。

{
  "contractVersion": "1.0.0",
  "errorCode": "0",
  "data": {
    "pluginId": "tenant-provider",
    "executionSequence": 1,
    "installation": {
      "environmentKey": "consumer",
      "applicationRuntimeId": "runtime-a",
      "workspaceId": 42,
      "bundleInstallId": "installation-a",
      "installedBy": 25,
      "bundle": {
        "environmentKey": "publisher",
        "bundleId": "sales"
      }
    },
    "operation": {
      "operationId": "operation-a",
      "operationType": "INSTALL",
      "currentVersion": null,
      "targetVersion": "1.0.0",
      "requestedBy": 42
    },
    "stage": "BEFORE_RESOURCES",
    "outcome": "APPLIED",
    "resources": {
      "publisher/sales/MODULE/customer": {
        "tenantId": {
          "@type": "Data",
          "value": "tenant-a"
        }
      }
    }
  }
}

日常属性更新

修改已安装 Module 的属性会由所属 Bundle 执行 CONFIGURE,currentVersion 与 targetVersion 相同。 Runtime 在同一事务中保存目标配置并冻结现有 Bundle 操作和两阶段授权;失败的事务不会留下半份操作。 同一 Bundle 保留完整资源与管理器范围,继续使用现有操作认领、派发和 Runtime 内部提交流程。 执行期间,其他用户配置写入会被拒绝;过期的配置快照不能覆盖新值。 网络中断后的重试保持 operationId + stage,管理器返回同一业务结果及获准写入的 Data 属性。

生命周期更新访问凭据

AFTER_RESOURCES 的获准资源携带 delivery。首次签发时包含 credential,已有资源升级或配置通知只包含当前 tokenId 和入口配置;升级新增资源正常首次签发。BEFORE_RESOURCES、DETACH 和 REMOVE 不携带资源调用秘密。

凭据作用域为 Runtime、完整 ResourceLocator 和 installation.bundleInstallId;顶层 pluginId 用于校验已认证管理器身份,不另划凭据命名空间。本地已有秘密只能在这些字段及 tokenId 全部一致时保留。其他身份的旧秘密不能拼接到新配置上。

下面是与前述安装对应的首次交付请求。地址和 businessId 来自 Owner,示例值不能作为运行时默认值。生命周期 15 的 RUNTIME_GATEWAY 交付不包含历史 runtimeCalls。

{
  "pluginId": "tenant-provider",
  "executionSequence": 1,
  "installation": {
    "environmentKey": "consumer",
    "applicationRuntimeId": "runtime-a",
    "workspaceId": 42,
    "bundleInstallId": "installation-a",
    "installedBy": 25,
    "bundle": {
      "environmentKey": "publisher",
      "bundleId": "sales"
    }
  },
  "operation": {
    "operationId": "operation-a",
    "operationType": "INSTALL",
    "currentVersion": null,
    "targetVersion": "1.0.0",
    "requestedBy": 42
  },
  "stage": "AFTER_RESOURCES",
  "configuration": {
    "schemaVersion": "1.0.0",
    "values": {}
  },
  "resources": {
    "publisher/sales/MODULE/customer": {
      "action": "INSTALL",
      "currentVersion": null,
      "targetVersion": "1.0.0",
      "properties": {
        "region": {
          "@type": "Data",
          "value": "north"
        }
      },
      "references": {
        "inventory": {
          "@type": "ServiceReference",
          "resourceLocator": "publisher/inventory/MODULE/catalog"
        }
      },
      "delivery": {
        "kind": "RUNTIME_GATEWAY",
        "apiGatewayUrl": "https://runtime.example/service",
        "businessId": "customer-source",
        "tokenId": "token-a",
        "credential": {
          "tokenId": "token-a",
          "token": "example-once-issued-token"
        }
      }
    }
  }
}

生命周期 15 沿用生命周期 14/引用 8 的完整 Locator 引用,目标字段为 resourceLocator:单值使用 {"@type":"ServiceReference","resourceLocator":"来源环境/Bundle/资源类型/资源ID"}; InterfaceMap 使用 ServiceReferenceMap.valueMap,每个键必须等于该成员的完整目标 Locator,值为对应单值引用; List 使用 ServiceReferenceList.valueList。不再用物理 serviceId 选择目标,也不支持旧 Map 的任意业务键。

对于 Owner 提供资源操作能力的资源,生命周期 15 还支持以下 delivery。入口由 Owner 返回, 不能为所有资源虚构网关 businessId,也不能从 Locator 猜地址:

{
  "kind": "RESOURCE_OPERATIONS",
  "resourceOperationsUrl": "https://runtime.example/api/resource-operations",
  "tokenId": "event-token-a",
  "credential": {"tokenId": "event-token-a", "token": "example-once-issued-operation-token"}
}

RUNTIME_GATEWAY 与 RESOURCE_OPERATIONS 按 Owner 的实际能力交付;二者的秘密均只出现在 delivery.credential 中。ServiceReferenceList.valueList 的顺序、Map 键和清空操作都按本次完整配置保存,不能与旧本地配置做只增不减的合并。

业务调用及其重试不调用引用解析接口,直接使用受保护的本地配置。管理器可以加密保存自己的运行 token;平台 ACS 只存哈希,Backend 和 Manager 不存可恢复原文。秘密不得进入计划、操作快照、日志、错误、生命周期回执或普通配置。

首次交付响应丢失或管理器本地秘密丢失时,显式调用 issue 签发自己作用域的新 token;不会自动补签、刷新或恢复旧原文。显式 rotate 校验 expectedTokenId,只影响自己的 token。接口和完整请求见资源凭据交付与补签。

system-manage 向渠道转发时保留原始安装和管理器身份;channel-gateway 使用这份获准的资源凭据调用 Runtime,不创建自己的签发身份。撤销、资源移除、管理器解绑和卸载后不得继续使用或复活旧值。

异步发布事件

后台 Worker 使用已保存的来源资源入口和 token,通过资源 Owner 的当前事件合同发送事件,不调用旧引用解析接口。事件不是引用属性,不需要 eventPublisher 自引用或新增 publishEvents 开关。

事件名、参数和路径使用模块事件合同,地址不得替换成提供方入口。每次业务重试保持事件 ID 和业务幂等键;HTTP 与 CModel 业务结果都成功后确认 outbox。资源 token 证明来源身份,不代表执行用户,用户委托由独立授权链提供。

Bundle 管理器独立属性写入

POST /bundle-plugin-manager/api/bundle-plugin/properties/update 是独立写命令,不需要处于安装、升级或 CONFIGURE 回调中。当前登记须声明 propertyWrite: "2.0.0"。请求由公共库 baijimu-bundle-plugin =25.2.0 定义,提交安装身份、资源、requestId 和需要写入的 Data 属性;不再提交 expectedProperties,也不比较请求生成时的旧值。

平台校验管理器凭据并向目标安装环境转发;执行时校验当前管理器登记、安装与资源归属、字段写权限及撤销状态,再取得目标 Bundle 的独占修改权。原实例标识和平台管理的凭据属性不能通过此接口修改。

同一 Runtime、来源环境与 Bundle 的冲突修改不能同时执行。已有修改时返回明确冲突;调用方可在操作结束后重新提交。该请求不会取消正在执行的安装或配置,也不触发生命周期回调。结果只返回关联身份、属性名称和提交回执,不返回秘密属性值。

独立写入只记录自身执行结果,不新增管理器的生命周期类型,也不因写入失败将 Bundle 安装标记为失败;保存与应用结果按实际回执确认。其他 Bundle 的配置由保存事务保护。

仅声明 propertyWrite 1.0.0 的登记仍可用于其余已支持操作,但不能调用新版独立写入。采用此协议需要协调升级实际写入调用方、转发组件与目标后端,不能假定发布 SDK 就已完成环境切换。

本页内容