# 能力与安全边界

理解插件运行时默认拒绝的文件、网络、命令执行和文件修改边界。

Source: https://semifold.noctisynth.org/zh/docs/plugins/capabilities/
Language: zh



Semifold 把生态插件视为“仓库中负责解析不可信项目数据的代码”。因此，运行时使用明确且限定在单次操作内的能力，不允许插件继承整台机器的环境权限。

## 边界速览 [#边界速览]

| 能力       | 默认状态   | 怎样授权                                        | 重要限制                            |
| -------- | ------ | ------------------------------------------- | ------------------------------- |
| 列出文件     | 拒绝     | `metadata.readPatterns`                     | 请求和返回路径都必须匹配已授权的仓库相对 glob。      |
| 读取文本     | 拒绝     | 同一项读取模式                                     | 读取不能离开项目根目录，并受单文件和单次操作预算限制。     |
| HTTPS 请求 | 拒绝     | `.changes/config.toml` 中的 `allowed-origins` | 只接受精确 HTTPS 来源，不接受通配符、凭据或按路径授权。 |
| `URL`    | 提供受限子集 | Boa 宿主内置                                    | 只支持 SDK 已声明的接口。                 |
| 写文件      | 不提供    | 无法授权                                        | 插件返回候选修改，由宿主验证并应用。              |
| 启动命令     | 不提供    | 无法授权                                        | 发布与钩子命令保留在解析器配置中。               |
| 宿主凭据     | 不提供    | 无法授权                                        | 软件包仓库与代码托管平台凭据不会进入插件输入。         |

## 文件访问 [#文件访问]

插件在元数据中声明尽可能小的 glob 集合：

```ts
export const metadata = definePluginMetadata({
  ecosystem: 'com.example.game',
  pluginVersion: '1.0.0',
  readPatterns: [
    'packages/*/manifest.json',
    'workspace.lock',
  ],
});
```

`host.listFiles(pattern)` 不能扩大权限：请求的 glob 必须与 `readPatterns` 中的某一项完全相同，每条返回路径也会再次检查。不能用一个看似更窄的不同 glob 代替已声明值。`host.readText(path)` 会执行相同的项目根目录、glob、路径编码、文件大小和单次操作累计预算检查。

协议数据应统一使用正斜杠和仓库相对路径，不要依赖调用者的当前工作目录。

## 网络访问 [#网络访问]

在配置中授权精确来源：

```toml
[plugins."com.example.game"]
path = "plugins/game.js"
allowed-origins = [
  "https://api.example.com",
  "https://metadata.example.net:8443",
]
```

运行时会拒绝非 HTTPS URL、内嵌凭据、未授权端口和只是看起来相似的来源。请求与响应正文、请求次数、重定向、并发和累计耗时都有限制。网络传输不会继承系统代理。

`fetch` 和 `URL` 有意小于浏览器 API。请把 `@semifold/plugin-sdk` 类型当作受支持的契约；熟悉的 Web API 名称并不意味着存在 DOM、Cookie、浏览器缓存或 Node.js 行为。

## 返回候选修改，而不是直接写文件 [#返回候选修改而不是直接写文件]

`plan-edits` 返回声明式文件修改。修改已有文件时，必须携带插件读取到的原始字节对应的 SHA-256。宿主随后会验证：

* 目标路径合法且没有离开仓库；
* 修改提到的软件包和依赖确实存在；
* 修改来源与发布计划一致；
* 当前文件内容仍与预期哈希匹配；
* 不存在重复目标或跨适配器冲突；
* 候选修改能被普通文件修改执行器接受。

插件永远不会得到可写文件句柄。

## 运行时与协议失败 [#运行时与协议失败]

可以预期的领域失败应由插件返回结构化诊断。Semifold 还会把运行时异常、错误协议版本、缺少操作、响应操作不匹配、非法路径、资源超限和无效修改转换成带插件范围的错误。

某个插件失败会停止需要它的当前操作；Semifold 不会因此开放备用权限，也不会悄悄接受一张不完整的工作区图。

## 仍由宿主负责的工作 [#仍由宿主负责的工作]

以下能力不会进入插件：

* 解析变更集并合并版本提升级别；
* 验证跨生态依赖图；
* 计算发布通道版本；
* 渲染变更日志；
* 执行软件包仓库检查与发布命令；
* 创建 GitHub Release 并上传附件；
* 最终应用文件修改并报告恢复状态。

这条边界让自定义软件包格式可以扩展，又不会把插件变成一段拥有整台机器权限的发布脚本。

