Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help


id: ADR-017 title: 入站认证在授权前解析规范主体 date: 2026-08-14 status: 提议中 relates-to:

  • ADR-010
  • https://github.com/zeroclaw-labs/zeroclaw/issues/7141
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8289
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8290
  • https://github.com/zeroclaw-labs/zeroclaw/issues/8076
  • https://github.com/zeroclaw-labs/zeroclaw/issues/7142
  • https://github.com/zeroclaw-labs/zeroclaw/issues/6996
  • https://github.com/zeroclaw-labs/zeroclaw/pull/8063
  • https://github.com/zeroclaw-labs/zeroclaw/pull/8272
  • crates/zeroclaw-api/src/principal.rs
  • crates/zeroclaw-api/src/grants.rs
  • crates/zeroclaw-runtime/src/security/auth_provider.rs
  • crates/zeroclaw-runtime/src/security/principal_resolver.rs
  • crates/zeroclaw-runtime/src/rpc/dispatch.rs
  • crates/zeroclaw-runtime/src/rpc/wss.rs
  • crates/zeroclaw-memory/src/sqlite_permissions.rs

ADR-017:入站认证在授权之前解析规范主体

上下文

ZeroClaw 有多种方式让外部参与者与守护进程交互:本地 RPC、远程 WSS、Web 网关、CLI 和 Zerocode 客户端、频道,以及未来的智能体间通信路径。在 RFC #7141 被接受之前,这些交互面并未共享一套强制执行的答案,来回答“谁在执行操作?”以及“该参与者可以做什么?”的问题。

TLS 和重连令牌还不够。TLS 可以保护连接,但无法证明已连接的客户端具备 ZeroClaw 权限;现有的 tui_id / tui_sig 机制用于重连连续性,而不是独立的身份证明。远程 WSS 客户端、浏览器用户、本地进程、频道发送者和服务客户端,都需要在特权运行时工作开始之前,统一到同一套授权模型上。

风险不仅在于某一条路由缺少身份验证,更大的风险在于存在多套并行的安全体系:原生配对令牌、对等方凭据、SSH 密钥、密码、OIDC subject、渠道发送者和服务凭据,各自都在定义自己的用户身份、角色词汇、所有权键和回退行为。一旦如此,某个提供方的 admin 声明、某个本地用户名或某个被复用的 subject 字符串,就可能在无意中绕过另一个表面所依赖的策略。

已接受的 RFC #7141 确定了架构方向。它要求提供方验证凭据,要求共享解析器将已验证的身份映射为规范的 ZeroClaw 主体及权限配置文件授权,并要求运行时界面使用这些已解析的主体,而不是自行解释凭据。实施排期由 #8289 负责,会话、记忆及按发送者授权的详细工作则在 #8290 中跟踪。本 ADR 记录的是长期有效的决策,并不表示推进已经完成。

决策

将入站身份拆分为验证、解析和执行三个阶段

入站认证分为三个独立阶段:

  1. AuthProvider 用于验证一个凭据,并返回已认证的身份信息,其中包括提供方来源、主体(subject)、参与者类型(actor kind)、声明(claims)或本地名册绑定(local roster binding)、过期时间以及重新验证(revalidation)元数据。
  2. 一个共享的 ZeroClaw 解析器会将该已认证身份映射为规范的 PrincipalId,并获取当前的权限配置文件授权。
  3. 调度、网关处理程序、会话、内存、工具、配置以及其他特权运行时表面均会强制执行已解析的主体及其授权。

Rust 实现可以在内部合并类型,但权限边界保持分离。提供方负责验证身份,它们不会签发 ZeroClaw 运行时授权,不会将 IdP 角色重新解释为权限,也不会绕过共享解析器。

使用规范化的主体标识,确保它们不会因字符串偶然相同而发生冲突

ZeroClaw 中的 principal 是身份验证成功后,该参与者在系统中的持久身份。在同一部署范围内,principal 身份是全局唯一、无歧义的。

OIDC 人类身份以经过验证的 issuer 和 sub 作为键,而不是仅以 sub 作为键。提供方别名可以出现在审计输出中,但它不能使来自不同 issuer 的相同 subject 字符串代表同一个actor。

Wait, correction: “actor” should be separated properly.

OIDC 人类身份以经过验证的 issuer 和 sub 作为键,而不是仅以 sub 作为键。提供方别名可以出现在审计输出中,但它不能使来自不同 issuer 的相同 sub 字符串代表同一个 actor。

本地身份通过显式的名册配置进行映射。不同的本地凭据只有在配置将其关联时,才可能解析为同一主体。名册中的显示名称重命名必须保留稳定的主体标识符,或原子性地迁移其所属的会话、记忆、审批和审计记录。

client_credentials 解析为服务主体,而不是人类用户。服务主体不得因声明名称相似而继承浏览器会话、交互式用户假设或私有的人类记忆。

原生配对仍作为一种兼容路径保留。除非之后显式配置了令牌到主体的映射,否则共享的配对令牌会解析为共享操作员,而非某个具名的人。

跨提供商的字符串比较从不会关联账户。跨提供商的账户关联需要显式配置,并提供可审计的迁移路径。

将权限配置文件设为运行时授权的唯一词汇

权限配置文件是唯一的运行时授权术语。原始提供方声明、IdP 组、本地用户名、渠道发送者或服务客户端名称在共享解析器将其映射到 ZeroClaw 权限配置文件之前,不授予任何权限。

当一个身份映射到多个权限配置文件时,初始解析器通过确定性并集合并显式授权。细粒度选择器与相关资源授权取交集进行组合。空的选择器列表不授予任何实例,广泛访问则需要显式的通配符、全选选择器或管理员授权。

所有特权 RPC、网关、工具、配置、会话和记忆操作均经过分类,并默认拒绝。未经分类的路由或方法不会被隐式允许。管理员访问权限不会消除所有权;跨主体访问需要明确的管理员授权,并会生成审计事件。

显式拒绝语义、特定于提供方的策略语言、更广泛的策略管理 API,以及不同的优先级规则,都是各自独立的决策。它们不会作为本 ADR 的附带结果而产生。

保持身份验证和授权有效,以便能够随时撤销。

initialize 是 RPC 认证握手。在绑定主体(principal)之前,只运行完成认证所需的最少方法。每个特权方法都会拒绝未认证的调用方。

凭证路由是显式的。当凭证格式无法安全地标识其提供方时,握手过程会指明预期的提供方别名。不透明的 bearer 令牌不会被广播到所有内省端点,并且在所选方法或提供方下失败时,不能回退到共享运营方访问权限或更宽泛的权限。

已建立的连接不会保留无限期的授权快照。在授权策略代次发生变化后的下一次特权操作之前,运行时会根据当前的权限配置文件和声明映射配置,重新解析有效授权。移除或收窄权限配置文件、映射、名册条目、提供方或配对令牌,必须在文档规定的代次或重新验证边界处影响已建立的授权,而不是等到重新连接或守护进程重启。

凭证过期和提供方撤销适用于已建立的连接,但以提供方的实际保证为限。规范的 Principal、所有权记录、日志和审计记录均不包含机密信息。如果实时重新验证需要承载凭证(bearer material)或同等的机密句柄,提供方只会通过受支持的机密存储边界,在提供方拥有、限定于连接范围的重新验证上下文中保留该最少量的材料。普通运行时使用方无法读取该材料,并且在断开连接、凭证过期、提供方被移除或被撤销时,该材料会被销毁。

OIDC 令牌的用途是明确的。浏览器端的带 PKCE 的授权码流程会验证 ID 令牌,将其作为认证事件的证据,并建立 ZeroClaw 会话。API 和 RPC 的 Bearer 令牌路径只接受专为 ZeroClaw 签发的访问令牌。设备授权授权(Device Authorization Grant)适用于无浏览器的人工客户端,client_credentials 适用于服务主体。离线 JWT 验证受令牌过期时间和已配置的最长认证有效期限制;需要更快撤销的部署必须使用令牌内省、后向通道撤销或其他实时权威机构。

在会话和记忆存储边界强制执行主体所有权

每个已通过身份验证的会话都归属于一个规范主体。会话查找、批准、挂载、恢复、变更和删除操作在成功之前,必须就该归属达成一致。对于受限范围的主体,未知、冲突或未归属的遗留记录将以失败关闭方式处理,除非某项已记录的迁移将其映射到共享操作员主体。

私有记忆按主体(principal)和代理(agent)进行区分,仅对该主体可见,除非显式的管理授权允许访问。共享代理记忆是独立的作用域,只有在启用并获得授权后才可见。

Principal 归属是额外的存储维度,它不替代 agent、session、namespace 和 tenant 维度。私有记忆的读取、写入、upsert 和删除操作,都会在原子存储谓词中包含 principal 归属条件。仅先做预检查再执行范围更大的变更,或先读取再做后过滤,都是不够的。

内部发起的工作不得通过意外方式选定所有者。定时运行、SOP 发起的运行或其他非交互式运行,若会写入带有所有者的会话或记忆状态,则在第一个实现切片依赖默认值之前,必须先明确主体规则。

保持提供方与传输层实现和授权机构相互分离

所有入站接口都使用同一套主体(principal)与权限配置(permission-profile)模型,但它们不需要相同的传输实现。本地 RPC 可以使用对端凭据(peer credentials),远程 WSS 可以使用原生配对或 OIDC,Web 网关在路由边界进行身份验证,而 CLI 或 Zerocode 客户端则提供与服务商相适配的登录流程。

为首次强制执行上线而言,原生配对和本地对等凭证是必需的兼容路径,这样远程 WSS 身份验证就不会以“已强制执行但不可用”的状态发布。OIDC 是首个必需的外部提供方。本地密码浏览器登录、SSH 密钥挑战-响应、mTLS 身份、类 SCIM 的预配、通道身份和代理到代理身份属于兼容扩展,除非后续决策将其提升为要求,否则不属于首次 OIDC 交付的收尾要求。

验收关卡

此 ADR 在满足以下所有条件之前仍处于提议状态:

  • 规范的提供方注册表、已认证身份契约、主体身份模型、权限配置文件词汇表、共享解析器、显式凭据路由和感知代际的授权重新解析已一并交付,并附有以下测试:命名空间隔离、未映射身份、选择器默认拒绝行为以及提供方回退拒绝。
  • 原生配对、本地对等凭据、RPC 分发、WSS 启动校验和重连连续性通过构造方式强制实施身份验证,且不会产生已强制实施但无法使用的远程时间段;
  • OIDC JWT/JWKS、令牌内省、浏览器授权码 + PKCE、无浏览器的设备授权流程、服务 client_credentials 模式、令牌用途隔离、有界重新验证和网关主体传递均通过同一解析器工作,并在凭据、提供方状态或重新验证上下文不可用时失败即关闭(fail closed);
  • 会话、审批、附件、恢复、删除、私有记忆读取和私有记忆修改均在存储边界强制执行主体所有权,包括对旧版记录的文档化处理,以及针对定时任务或 SOP 发起工作的明确内部来源所有者规则;
  • 现有的远程 WSS 和 Nevis 用户已有经过文档记录和测试的迁移路径,而仅限本地的恢复方式可以在不恢复未经身份验证的远程访问的情况下修复锁定问题;
  • 文档说明了身份、参与者类型、声明映射、权限配置文件、授权、私有记忆与共享记忆、提供方保证、迁移、恢复,以及适用时与标准对齐的握手术语;并
  • 这次发布将拆分为可独立评审、可独立回滚的安全边界,分别由 #8289 和 #8290 跟踪,而不是合并为一个包含提供方、分发器、网关、存储、迁移和文档的整体分支。

Principal / AuthProvider 行为中立的接缝和契约测试的前期铺垫已通过 #8063 和 #8272 合并。这些切片只是基础工作,并不代表本 ADR 的全部门禁已经完成。

后果

积极后果:

  • 新增的入站提供方无需各自创建独立的授权系统。
  • 在每一个特权边界处,未来的审查者都可以问同一个问题:这里正在执行的是哪个已解析的主体(principal)以及哪些授权(grants)?
  • OIDC、本地凭据、原生配对和服务凭据不能仅因为共享同一字符串就发生冲突。
  • 撤销操作和权限配置文件的变更均有明确记载的实时生效边界,无需无限期等待重新连接或重启。
  • 会话与私有记忆的隔离成为存储层属性,而不再是存储之上的尽力而为过滤。

负面后果:

  • 这是一项针对未认证远程 WSS 行为的安全破坏性变更,因此原生兼容性和恢复机制必须与强制执行路径同步发布。

  • 共享解析器、profile 词汇表以及感知代次的重新校验,比仅在提供方内部进行的角色检查增加了更多基础设施。

  • OIDC 实现必须保持令牌用途、发现(discovery)、JWKS 刷新、令牌内省(introspection)以及符合标准的元数据边界,而不能接受每个看似有效的令牌。

  • Principal 所有权涉及会话和记忆存储,因此迁移与回滚需要比仅在边缘进行的身份验证检查更加谨慎。

  • Some useful extensions, including password login, SSH-key authentication, mTLS, SCIM, channel identity, and agent-to-agent identity, remain separate follow-up work.

    Wait, I need to correct my response: the above is not a translation. Here is the actual translation:

    一些有用的扩展功能,包括密码登录、SSH 密钥认证、mTLS、SCIM、频道身份和智能体间身份,仍需作为独立的后续工作推进。

参考文献