# 可复用凭据

让 Bot 使用密钥或密码连接某个 API。它会调用 `request_secret`，传入一个引用名称和一个 HTTPS 服务源。受保护的卡片会在你保存之前显示该源。Web、Electron 和移动端使用相同的后端；提交开始时输入框中的值会被清除，并且不会出现在消息、事件和模型输入中。

例如，Bot 可以请求：

```json
{
  "label": "API key",
  "purpose": "api_key",
  "credential": {
    "name": "example_api",
    "origin": "https://api.example.test",
    "auth": { "type": "bearer" }
  }
}
```

该值在 Postgres 的 `vault_credentials` 中使用部署的 `ENCRYPTION_KEY` 加密（AES-256-GCM，带记录绑定认证）。只有本次运行的用户才能提交可复用凭据。它属于该用户，并在后续运行中持续存在。默认情况下，它位于用户的账户保险库中，每个空间都会使用该保险库；如果用户在某个空间中保留自己的凭据，该空间有一个独立的保险库，初始为空，因此需要在该空间中重新保存，其他空间无法读取它。当所有者被删除时，该凭据会被删除；空间自己的保险库也会随其空间一并删除。名称、目标地址和认证配置属于元数据；`list_secrets` 只返回这些字段，不返回值。无需托管凭据服务或预构建连接器。

Bot 使用 `secret_request` 请求后端解密并注入凭据：

```json
{
  "name": "example_api",
  "url": "https://api.example.test/v1/items",
  "method": "GET"
}
```

认证支持 Bearer 令牌、命名请求头（`{"type":"header","name":"X-Api-Key"}`）和 Basic 认证（`{"type":"basic","username":"api-user"}`）。Basic 使用受保护的值作为密码。请求可以发送 JSON、表单编码或纯文本正文。保存的源必须完全匹配，包括端口。重定向和不安全的网络目标会通过共享的远程请求策略被拒绝。请求遵循现有的操作审批规则，有 30 秒期限和 1 MB 响应限制，并最多返回 20,000 个字符的已脱敏响应内容，不含响应头。

自托管部署可以设置 `RAKAZO_SECRETS_ALLOW_PRIVATE_HTTP=1`，以额外允许在私有或回环地址上使用纯 `http://` 源（例如 `http://nas.local:8123` 或 `http://localhost:3000`）。默认关闭。以这种方式发送的凭据不加密：该网络上的任何内容，或该端口上的任何本地服务，都可以读取它们。仅在你信任的网络上启用。链路本地和云元数据地址仍然被阻止，公共源仍然要求 HTTPS。

使用相同名称和配置再次调用 `request_secret` 会返回已保存的引用。添加 `"replace": true` 可显示另一张受保护卡片并替换其值。使用 `{"name":"example_api"}` 调用 `forget_secret` 会删除已存储的值并阻止将来使用；已开始的请求可能仍会完成。在更改凭据的源或认证配置之前，请先移除该凭据。每个用户在每个 Bot 中最多可保存 100 个凭据，值长度限制为 16,384 个字符。

模型没有读取这些值的工具，后端会从 API 响应中移除直接的和常见的编码回显。经批准的服务仍然会收到凭据：脱敏无法防御恶意服务故意对其进行转换。请选择你信任的服务，并使用适当限定范围的凭据。

此边界支持经过认证的 HTTP 请求。将站点凭据注入 AI 控制的 shell 命令、文件或任意环境变量会让这些命令能够读取它，因此不会暴露这些路径。你刻意希望放入 Bot 自己 shell 的值属于命令变量，见下文。需要请求签名、OAuth 刷新、多个凭据或自定义协议的 API 应使用连接器适配器。现有的带 `connectionId` 的 `request_secret` 调用保留其一次性连接器代码流程。

## 命令变量

当某个值应属于 Bot 自己的 shell 而不是 HTTP 请求头时，将它保存为命令凭据。Bot 调用 `request_secret` 时使用 `"auth": {"type":"command"}` 且不提供源：

```json
{
  "label": "NetBird setup key",
  "purpose": "api_key",
  "credential": {
    "name": "netbird-setup-key",
    "auth": { "type": "command" }
  }
}
```

该名称会作为环境变量导出到该 Bot 的 shell 命令中：大写并将连字符替换为下划线，因此 `netbird-setup-key` 会变成 `$NETBIRD_SETUP_KEY`。环境会在每条命令执行前重新加载，因此在运行中途添加、替换或删除的变量会应用于下一条命令。

命令变量会覆盖以相同名称导出的空间变量。这是被接受且由所有者控制的：你决定 Bot 的命令在哪个环境中运行，而针对单个 Bot 的值是更窄的选择，因此它会胜过它遮蔽的空间级值。如果你想要空间值，请移除空间变量，或重命名命令变量。

如果无法加载已保存的 Bot 命令变量，该变量会在此命令中被取消设置，即使存在同名的空间变量也是如此。其他变量仍然可用；不会暴露任何凭据值或加载错误。

命令变量会以其明文、base64 和 URL 编码形式从命令输出中被脱敏，且不能与 `secret_request` 或 `browser_act` 登录填充一起使用。会改变 shell 或常见运行时启动方式、信任 TLS、或运行 git 或 ssh 助手的名称是保留的，以 `LD_`、`DYLD_`、`RAKAZO_`、`GIT_CONFIG_` 或 `NPM_CONFIG_` 开头的名称也是保留的。保留列表并非详尽无遗：它涵盖众所周知的变量，保存保留名称会被拒绝并给出原因。

**Bot 的 shell 会读取此值。** 命令变量是给 Bot 提供便利的，而不是对 Bot 的边界：Bot 运行的 shell 命令以及该命令启动的代码都可以打印、编码或发送该值。脱敏会阻止它出现在模型读取的结果中；它不能阻止获得许可的 Bot 或 Bot 运行的任何内容使用它。对于被授予该凭据的 Bot 而言没有保密性，因此请将命令变量视为与该 Bot 共享，并且只保存你愿意让它在无人值守时使用的值，并限定为其所需的范围。

命令变量与其他可复用凭据在同一“凭据”部分管理：Web 和 Electron 托管的 Web UI 可以添加、替换和删除命令变量。移动端没有凭据设置界面，但 Bot 在线程中打开的请求卡片会显示命令变量的变量名而不是站点，因此 Bot 可以在手机上获取命令变量的值；列出、添加、替换和删除命令变量仅在 Web 和桌面端可用。

## 已保存的网站登录

当你希望 Bot 自行登录某个网站时，让它保存该登录信息。它会调用 `request_secret`，传入 `"auth": {"type": "login"}`、登录页面的源，以及该站点用于登录的值的标签：

```json
{
  "label": "Example sign-in",
  "purpose": "password",
  "credential": {
    "name": "example_login",
    "origin": "https://login.example.test",
    "auth": { "type": "login" }
  },
  "fields": ["ID number", "Phone number"]
}
```

没有 `fields` 时，卡片会要求填写用户名（初始可见）和密码（初始隐藏），正如登录一贯如此。一次登录有 1 到 8 个字段，每个字段都有自己的标签。卡片为每个字段要求一个值；Bot 命名的字段只有在标签的每个词都是标识词（ID、phone、email、account、username）或普通填充词（number、name、address、last、digits）时才初始可见，支持英文或希伯来文，例如 “ID number” 或 “Phone number”；任何其他词（例如 password、PIN 或 code）或拼写错误都会保持隐藏，所有无法识别的标签也是如此。你可以在保存前切换任何字段的隐藏/可见状态，保存的结果即为最终结果：Bot 命名字段但不能发送可见标志，因此标签是它唯一能影响的内容，服务器只接受与卡片所要求字段完全一致的答案。所有值都以与其他可复用凭据相同的方式加密存储。

卡片还有一个 **保存到保险库** 开关，默认开启，只有你可以关闭它。关闭后，登录信息会为请求它的那次运行加密保存，永远不会进入保险库。只有该次运行才能在该卡片的 HTTPS 站点上填充它，并且它会像已保存的登录一样从工具输出中隐藏。无论运行如何结束，它都会在运行结束时删除，因此后续运行必须重新请求。站点的 Cookie 会保留，因此 Bot 可能仍处于登录状态。

要登录，Bot 使用 `browser_snapshot` 找到字段，并按标签逐一命名：

```json
{
  "actions": [
    { "kind": "fill_secret", "ref": "e3", "secret": "example_login", "field": "ID number" },
    { "kind": "fill_secret", "ref": "e4", "secret": "example_login", "field": "Phone number" },
    { "kind": "click", "ref": "e5" }
  ]
}
```

`"username"` 和 `"password"` 也可以指代登录的第一个可见字段和第一个隐藏字段，因此 Bot 无需知道标签即可填充在设置中保存的登录。

后端会解密该值，页面浏览器只有在那一刻页面仍位于已保存的源上时才会输入它，因此登录信息无法被输入到其他站点或已重定向的页面。源必须为 HTTPS：`RAKAZO_SECRETS_ALLOW_PRIVATE_HTTP` 不适用于网站登录。隐藏字段只会写入密码字段，可见字段只会写入 text、email 或 tel 输入框。可见字段可能会出现在页面和截图中。站点的“显示密码”控件仍正常工作；显示隐藏值可能会使其出现在截图中。值通过 stdin 传输到计算机，而不是命令行参数。快照永远不会报告保存登录的字段值。在每次运行中（不仅仅是填充它的那次运行），页面结果、命令输出和文件读取等工具结果都会以明文、URL 编码、表单编码和 base64 形式清除每个已保存登录的隐藏字段；短于 6 个字符的隐藏值只会在填充它们的那次运行中被清除。在填充登录的那次运行中，页面结果还会清除其 6 个或更多字符的可见字段，这涵盖在页面文本中回显它们的站点；较短的可见值不会被清除，因为脱敏会替换每一次出现。后续运行会保持可见字段可读，因为其中一个通常是用户自己的电子邮件地址。只有此 Bot 自己的运行会清除其隐藏字段：在团队计算机上，其他 Bot 的运行不会这样做，因此对于登录站点的 Bot，请使用私有计算机。登录不能与 `secret_request` 一起使用。填充无需审批：保存登录即为审批，且绑定到一个站点。使用 `forget_secret` 移除它。

在字段功能出现之前保存的登录会读取为可见的用户名和隐藏的密码，并完全像以前一样填充。

## 管理已保存的凭据

所有者无需询问 Bot 即可回读已保存的内容。在 Web 应用中，打开 Bot 的设置，展开 **高级**，然后使用 **凭据** 部分。它列出每个凭据的名称、源和认证类型，从不列出的值。你可以在那里添加凭据、在同一目标上替换其值，或在确认后移除一个凭据。移除会立即删除已保存的值。Electron 桌面应用托管相同的 Web UI，因此具有相同的部分。

移动端不托管该 Web 设置外壳，因此没有凭据管理界面。线程凭据卡片在手机上仍然可用，包括网站登录，Bot 就是这样在那里获取值的。列出、替换和移除已保存的凭据仍然在 Web 部分。要求 Bot 对某个名称执行 `forget_secret` 只会移除它；不会列出或替换。

无密码登录（例如 ID 号和电话号码）使用相同的登录卡片。短信或电子邮件发送的一次性验证码、CAPTCHA 和通行密钥仍使用 `request_takeover`，因此验证码会在实时屏幕上输入而不是被保存，任何你更愿意自己完成的登录也是如此。

该值会被输入到 Bot 计算机上的真实浏览器中。任何能读取该浏览器的东西，包括 Bot 通过页面或调试端口执行的自己的 shell 命令，都可能读取已填充的字段。将值排除在模型输入之外可以防止意外泄露，但不能阻止有意提取它的 Bot。仅为你愿意让 Bot 无人值守使用的账户保存登录信息。
