← 返回文章列表

为什么 memory:admin 不能成为平台超级管理员:一次 Registration 权限模型纠偏

从一个真实 403 反例追到最早失真层,说明 Agent Foundation 如何把 Registration 从 Memory-shaped handoff 修正为 capability-neutral 的角色权限上限。

在一个同时启用 Evidence、Memory、Graph Proposal 和 ReviewDecision 的平台里,memory:admin 应不应该顺便管理 Registration?

直觉上可能会说“可以,反正它是管理员”。但这句话把一个领域权限偷换成了平台超级权限。Memory 管理员可以管理 Memory,不代表它能够创建产品身份、授予 Graph executor、读取 Evidence authority,或改变 Registration。

Agent Foundation 的 AF-RA01 corrective 就来自这个反例:公共 Product Runtime 已经采用 capability-neutral 的 V2 request 和 binding,但响应与 credential handoff 仍继承早期 Memory-shaped ExternalProjectRegistrationV1。表面看是某个 HTTP 403“不方便”,真正的问题却是 Registration 权限模型没有跟上平台能力模型。

查看 Agent Foundation 项目总览 · 打开本文交互图

最小反例不是“管理员为什么被拒绝”

正确的最小反例是:

  1. 使用仅拥有 memory:admin 的 credential;
  2. 尝试创建或修改 Product Runtime Registration;
  3. 期望结果必须是 403;
  4. Registration、Evidence、Graph Proposal 与 Graph 均不得发生写入。

如果这个请求成功,说明平台把 Memory 领域管理员错误提升成了 Foundation 超级管理员。若只在 HTTP route 上加一个特殊判断,底层 authorization lattice 仍可能在 SDK、内部 facade 或新 route 中再次泄漏。

所以修复不能是“再加一条 deny rule”,而要找到 invariant 最早变假的位置。

最早失真层:Registration 仍在说 Memory 的语言

V2 Product Recipe 可以声明不同能力,Runtime assembly 也能找到不同 component owner。但旧 handoff 仍以 Memory namespace、Memory scopes 和 Memory admin 解释注册后的权限。

这会产生三个后果:

  • memory:admin 被过度提升;
  • reviewer/executor 的 scopes 可能由共享 ReviewDecision 反向推导,而不是目标 authority 授予;
  • 产品得到的像是一组可直接使用的凭据,而不是待 provisioning 的角色上限。

修复发生在 Registration 公共合同,而不是各 adopter 的 adapter。

ProductRegistrationReceiptV2 只描述“最多可以有什么”

新的 public receipt 返回 actor_scope_requirements。每个启用角色——agent、reviewer、executor、revalidator——都有独立的 namespace 与 maximum scopes。

Receipt 不包含 secret,不是 credential,也不表示调用者已经拥有这些权限。部署方仍需为实际 principal 配置独立 credential;每次 open 或调用时,再计算三个集合的交集:

  1. actor role 允许的 scopes;
  2. sealed binding set 为该角色冻结的 scopes;
  3. 实际 credential 持有的 scopes。

只有交集中的能力可以被调用。

Capability-neutral Registration 权限边界

Compiled plan、accepted claims、唯一 Runtime owner 与 sealed binding 共同派生 Registration;receipt 只把角色上限交给部署方。

谁授予 reviewer 和 executor 权限

共享 ReviewDecision 负责记录不可变审批,但它不是所有目标对象的权限来源。

Memory review scope 应由 Memory authority 授予;Graph Proposal review scope 应由 Graph Proposal authority 授予。ReviewDecision 只消费已经被授权的 target-specific review 请求。

同样,proposal_only 模式没有 reviewer 或 executor,就不应在 receipt 中生成这两个角色。Graph-only Recipe 也不能获得 Memory 或 Relation scope。

这个规则避免了一个常见错误:因为多个领域共用审核基础设施,就把基础设施误当作业务授权中心。

管理权限必须按域存在

AF-RA01 引入 registration:readregistration:write,并保留 Evidence、Memory、Graph Proposal 等各自的 admin/review/effect scopes。

这并不是把权限名称拆得越细越好,而是保证每项高风险动作都有明确 owner:

  • Memory 管理员不能创建 Registration;
  • Registration 管理员不能自动写 Graph;
  • reviewer 不能执行 outbox;
  • executor 不能自行批准 proposal;
  • revalidator 只能处理已经授权的 dependency convergence。

平台不存在一个由领域 scope 隐式获得的超级管理员。

为什么没有新建 V3 或数据库迁移

纠偏过程中,一个诱人的方案是新增 RegistrationV3、新表和迁移,借版本号把旧问题隔离出去。但持久化记录已经能够表达 sealed binding;失真发生在公共响应、handoff 和 authorization interpretation。

在没有持久化形状变化时增加 migration,只会扩大升级成本而不修复核心 invariant。因此 AF-RA01 保留 V1 兼容 carrier,为新的 V2 注册使用新的 public receipt,并让服务端每次重新读取 Registration。

这也是 first-principles repair 的一个例子:修最早拥有 invariant 的层,不用新版本号掩盖旧抽象。

验收关注的是越权与零写

这一批验证不是只看 happy path。关键证据包括:

  • memory:admin 调用 Registration route 得到 HTTP 403;
  • 失败前后 Registration 和语义 authority 无写入;
  • Graph proposal 在 submit/reviewer 阶段保持 Graph 零写;
  • 独立 executor 才能消费 outbox;
  • public installed workflow 能返回并校验 receipt;
  • 完整 backend/SDK 与现有 adopter 回归通过。

这证明 capability-neutral Registration 合同已经在本地已版本化基线中成立。它不证明生产 IAM、secret rotation、跨租户隔离或组织级 RBAC 已经完成。

这次故障带来的判断

如果一个平台已经支持多种能力组合,它的 Registration 就不能继续以某个最早 adopter 的领域模型为中心。否则每增加一个 adopter,都会出现新的“特殊管理员”“兼容 handoff”和隐式 scope。

我的结论是:Registration receipt 应当是能力编译结果的受限公开投影,而不是凭据包;管理员应按 authority domain 存在,而不是由最早出现的 admin scope 继承整个系统。 这次纠偏没有增加业务功能,却让以后新增能力时不必继续打权限补丁。

← 返回文章列表