# 插件注册与管理

注册稳定插件身份和 Bundle 执行声明，再发布显式授权的 Bundle 绑定。

插件注册记录是服务目录。`pluginId` 全局唯一且不可变，Bundle 绑定只引用该身份、协议、配置及资源授权。
执行地址不进入 Bundle，平台安装用户不需要重复注册插件。

管理入口为 `baijimu lifecycle-plugin create/list/get/update/delete`。执行前查看目标子命令的 `--help`，
确认支持 `--bundle-execution`。以下地址为结构示例，实际值来自插件提供方的服务登记。

## Bundle 执行声明

将声明保存为 `bundle-execution.json`：

```json
{
  "protocolVersion": "6.0.0",
  "executeUrl": "https://plugin.example/plugin/bundle/lifecycle",
  "supportedStages": ["BEFORE_RESOURCES", "AFTER_RESOURCES"]
}
```

`bundleExecution.protocolVersion` 决定 Bundle 执行请求协议；必须实现两个资源阶段。
创建目录记录必须显式提交 `--bundle-execution`，执行地址与协议都在这个声明中提供。

```bash
baijimu lifecycle-plugin create \
  --plugin-id "$PLUGIN_ID" \
  --name "$PLUGIN_NAME" \
  --bundle-execution @bundle-execution.json \
  --default-config '{}'

baijimu lifecycle-plugin get "$PLUGIN_ID"
```

已有目录记录的所有者可更新并回读：

```bash
baijimu lifecycle-plugin update "$PLUGIN_ID" --bundle-execution @bundle-execution.json
baijimu lifecycle-plugin get "$PLUGIN_ID"
```

核对 `pluginId`、`bundleExecution` 中的 `executeUrl`、`protocolVersion` 与支持阶段。
注册不会自动完成双向调用凭据配置，也不会安装 Bundle。先完成下列认证接入，再按
[Bundle 注册与绑定](/development/bundle-development/advanced/lifecycle-plugins/)声明资源授权并发布安装。

## 双向调用凭据

使用 CLI 0.65.0 或后继兼容版本，由插件注册者自行管理两个方向的独立凭据。
平台校验当前用户是否为 `pluginId` 的注册所有者；使用该插件的 Bundle 作者或安装用户不能修改其凭据。

| 调用方向   | 凭据来源与管理                   | 保存与验证                              |
| ------ | ------------------------- | ---------------------------------- |
| 平台调用插件 | 注册者提供插件服务接受的 Bearer Token | 平台加密保存，生命周期调用时读取当前有效值；插件服务验证       |
| 插件调用平台 | 注册者自助申请，平台按注册身份签发         | 平台保存哈希并验证；注册者将 Token 保存在插件服务端受控配置中 |

### 设置平台调用插件的凭据

先让插件服务接受所提供的 Token。通过状态读取取得 `data.revision`，首次配置为 `0`：

```bash
baijimu lifecycle-plugin credential status "$PLUGIN_ID"
baijimu lifecycle-plugin credential set "$PLUGIN_ID" \
  --expected-revision "$CREDENTIAL_REVISION" \
  --token-file "$PLUGIN_TOKEN_FILE"
```

`--token-file -` 从标准输入读取。不要把 Token 直接写进命令参数、源码、Bundle、`defaultConfig` 或执行地址。
状态只返回是否已配置、凭据版本和更新时间，不返回 Token。更新提交后新发起的调用使用新值，
不需要修改平台组件配置或重启服务；已发出的请求不会被追回。并发版本不匹配时重新读取状态并确认变更。
未配置或已撤销的外部插件不能通过安装预检。

轮换时，先让插件接受新旧 Token，再使用当前 revision 更新平台凭据并验证生命周期请求，
最后在插件服务端停用旧 Token。需要立即禁止后续平台调用时：

```bash
baijimu lifecycle-plugin credential revoke "$PLUGIN_ID" \
  --expected-revision "$CREDENTIAL_REVISION" --yes
```

### 签发插件调用平台的凭据

```bash
baijimu lifecycle-plugin credential issue "$PLUGIN_ID" \
  --name "$CREDENTIAL_NAME" \
  --expires-at "$EXPIRES_AT" \
  --token-output "$NEW_TOKEN_FILE"
baijimu lifecycle-plugin credential list "$PLUGIN_ID"
```

`EXPIRES_AT` 使用未来的 RFC3339 时间。输出文件必须不存在；Unix 下创建权限为 `0600`。
CLI 将仅交付一次的 Token 写入文件，终端只显示元数据。注册者将其配置到插件服务端，
用于解析当前引用。请求中的 `pluginId` 字段不能代替认证。

轮换时申请新凭据、更新插件服务并验证解析引用，再撤销旧凭据：

```bash
baijimu lifecycle-plugin credential revoke-access "$PLUGIN_ID" \
  --credential-id "$OLD_CREDENTIAL_ID" --yes
```

这两种凭据不能相互代用，也不能复用 Hosted Service 管理 Token、用户登录凭据或引用解析返回的临时访问材料。
插件停用后两个方向均不再获得有效插件权限；撤销不能取消已经发出的 HTTP 请求。

## 管理与敏感信息

目录查询和列表提供有效注册记录；创建、更新、停用经过平台身份及所有者权限验证。
停用后的标识不能由另一个插件复用。`defaultConfig` 只保存非敏感业务默认配置，不能保存 Token、密码或访问密钥。
查询不进行字段脱敏；`executeUrl` 不得带 userinfo、query token 或临时签名。
执行凭据保留在插件服务的受控配置边界内。

管理响应使用完整 CModel envelope：

```json
{
  "contractVersion": "1.0.0",
  "errorCode": "0",
  "data": {}
}
```

业务失败使用 HTTP 200 与稳定非零 `errorCode`，data 为 null 或标准公开错误详情。
更新插件目录不改变已发布 Bundle 的不可变绑定；变更资源授权或配置后应创建后继 Bundle 版本再升级安装。
