跳转至

ADR-S-014:进程内 ACL 访问控制

  • 状态:Accepted
  • 决策:S6 在 Agent Runtime Service 应用端口外包裹一个 fail-closed ACL wrapper。Principal 由 composition root 在进入 service 前完成身份验证;它 只携带不含凭据的 subject。ACL 使用 capability 与 project/thread scope 的 精确匹配,多条 grant 采用 OR,不支持 wildcard、前缀、路径或大小写折叠。 service 核心不导入 UI、ACP、transport、settings、projects 或 deepagents。
  • 决策:wrapper 先验证最小 DTO shape,再从合法 SessionRef 提取 project 与 thread,随后授权,最后才触达 delegate。拒绝统一为固定的 permission_denied,不回显 subject、project、thread、capability、path 或 其他资源信息,从而避免存在性 oracle。malformed DTO 使用既有 invalid_request;authorizer 的 malformed context 使用 invalid_access_context。
  • 决策:AclGrant.capabilities 不允许为空;空 grant 没有可授权语义,构造时 立即以不回显配置值的 ValueError 失败。AccessControlledAgentRuntimeService 构造时要求 exact Principal/AclAuthorizer 类型,并对 delegate 做不调用方法 的结构检查;非法绑定尽早以安全 TypeError 失败。AccessRequest 的 malformed context 继续以不回显值的 ValueError 失败。
  • 决策:授权成功的 watch_events 返回 delegate lease,并采用 capability snapshot:之后替换外部 authorizer 不撤销正在消费的 stream;每次新 watch 重新授权。lease 退出只关闭 subscription,不取消 turn、不关闭 session。
  • 分层:S6 只保护应用端口,不读取 settings.readonly、 require_approval、deny_fs_paths,也不调用 runtime.safety 或 ACP PermissionCoordinator。Agent tool safety 负责工具执行安全,ACP permission 负责 ACP/HITL 协议层权限,两者与本进程 ACL 各自保持边界。
  • 影响:本阶段仍是进程内授权;S7 才传输身份,S8 才引入 daemon 生命周期, S10 才迁移 CLI/TUI/ACP 消费者。
  • 替代方案:在 manager/session 内分散检查会复制业务逻辑并产生资源枚举差异; 传输层授权在 S6 范围外且不能保护本地应用调用。
  • 重审条件:S7 定义远程身份、重放保护和 wire error 映射时,重新审视 Principal 的边界,但不得让凭据进入 runtime service DTO。