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 不再是一项需要实现的管理器协议。有效协议分别为:
| 注册字段 | 本页示例所选协议 |
|---|---|
lifecycle | 15.0.0 |
credentials | 1.0.0 |
propertyWrite | 2.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.operationType | INSTALL、UPGRADE、CONFIGURE、DETACH |
stage | BEFORE_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 就已完成环境切换。