第11章 任务、审批与治理:安全执行的边界
能力越大越需要缰绳——权限矩阵、审批链路与状态机
11.1 本章导读
到第10章,我们的 Agent 已经能读文件、执行 Shell、调插件、接 MCP——能力越强,失控的代价越大。本章讲系统的"刹车系统":任务如何在执行前经过权限评估与人工审批,状态机如何保证"没批准就不能跑",以及当前治理体系的边界在哪。
11.2 治理的整体图景:提交期 vs 运行期
治理有两个时机,本项目目前主要做第一个:
任务提交时,在执行前统一评估权限、决策审批。PermissionCheckNode 把关。优点:一次决策覆盖整个任务;缺点:对话链路(/api/agent/stream)不经过这里。
每次工具调用时实时拦截。RuntimeApprovalGate + IRuntimeApprovalBroker 端口已就绪,但 AgentFactory 默认构造时 approvalBroker=null,工具执行器走 allowAll。这是当前最重要的治理缺口(见 11.6)。
11.3 提交期链路:五节点再走一遍
第6章已经画过任务提交链,本章聚焦治理两个节点:
PermissionPolicyService.assess 拿着任务需要的工具清单去权限矩阵里查:哪些工具在这个 Profile 下是高风险的。ApprovalPolicyService.decide 再结合 Profile 配置做最终决策。默认配置(application.yml):
harness:
approval:
required-profiles: [web] # web profile 整体需审批
required-tools: [shell_execute, fs_write, plugin.run, subprocess.spawn] # 高风险工具
runtime-timeout-ms: 600000 # 运行期审批等待 10 分钟11.4 任务状态机:没批准就不能跑
关键防御点:执行入口对 PENDING_APPROVAL 状态直接抛异常兜底。即使有人绕过审批 API 直接调 executeSession,状态机也会在最后一刻拦住——这是第3章说的"聚合根保护不变量"的体现。
11.4.1 审批 API 流转
# 查看待审批
GET /api/harness/approvals/pending
# 批准(→ QUEUED → 落库 → 恢复执行)
POST /api/harness/approvals/{sessionId}/approve
# 拒绝
POST /api/harness/approvals/{sessionId}/reject审批通过后:approve(sessionId) → 状态置 QUEUED 落库 → HarnessExecutionService.executeSession → RUNNING → COMPLETED/FAILED。执行阶段复用第4章的 ReactLoopAgent 链路。
11.5 沙箱三档模式
审批之外,sandbox 域提供执行边界的粗粒度控制:
| 模式 | 约束 | 适用 |
|---|---|---|
READ_ONLY | 禁止一切写操作 | 只读分析、代码审查 |
WORKSPACE_WRITE(本地默认) | 写操作限制在工作区内,shell cwd 不得越界 | 本地开发 |
DANGER_FULL_ACCESS | 不限制 | 受信环境,慎用 |
11.6 当前治理的边界与对策
| 风险 | 现状 | 对策 |
|---|---|---|
| 对话链路绕过审批 | 运行期 gate 默认未启用,对话里的 shell_execute 不被拦截 | 生产环境启用 MatrixRuntimeApprovalGate 并接入 approvalBroker;或前置网关拦截 |
| shell_execute 零沙箱 | LocalShellExecutor 直接 /bin/sh -c,无命令白名单 | 务必开审批 + 容器隔离 + 限制 OS 用户权限 |
| 鉴权过简 | harness.auth.api-keys 为空则全放行,非多租户 | 生产必须配置 API Key;前置统一认证网关 |
11.7 小结与下一章预告
本章要点:治理分提交期(已实现,五节点链 + 权限矩阵 + 审批决策)与运行期(端口就绪但默认关闭);任务状态机 CREATED→PENDING_APPROVAL→QUEUED→RUNNING→COMPLETED/FAILED,执行入口对未审批状态抛异常兜底;沙箱三档控制执行边界;生产前必须补运行期拦截与鉴权。
下一章:治理讲完,该上线了。第12章讲部署与生产化——MySQL/H2 怎么选、Docker 怎么编排、上线前的检查清单。