diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 8d336ec1..802bc14a 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -58,6 +58,7 @@ graph TD subgraph "Infrastructure Layer 基础设施层" PROV["Provider"] TOOL["Tool"] + SEC["Security"] end subgraph "Support Layer 支撑层" @@ -76,6 +77,7 @@ graph TD LOOP <--> SESS LOOP ==> PROV LOOP ==> TOOL + TOOL <--> SEC CTX -. "依赖" .-> UTIL TOOL -. "依赖" .-> UTIL @@ -92,6 +94,7 @@ graph TD - Runtime MUST 作为唯一编排中心,负责链路生命周期与终态收敛。 - Provider MUST 吸收模型厂商差异,向上游输出统一协议。 - Tools MUST 作为工具执行边界,负责权限与结果归一。 +- Security MUST 作为统一权限治理边界,负责策略命中、审批事件与会话级记忆。 - Utils MUST 通过 `utils.Registry` 契约提供统一辅助能力入口。 ## 5. 模块职责矩阵(逻辑依赖 + 契约关系) @@ -103,6 +106,7 @@ graph TD | Context | Prompt 组装、上下文压缩、作用域隔离 | Runtime | Config / Utils | `context.BuildInput`、`context.BuildResult` | | Provider | 模型协议抹平、流式事件归一、能力判定 | Runtime | 模型供应商 API | `provider.GenerateRequest`、`provider.StreamEvent` | | Tools | 工具执行、审批拦截、输出归一 | Runtime | 本地/远端执行器 | `tools.ToolCallInput`、`tools.ToolResult` | +| Security | 权限判定、审批事件、session 记忆、工作区边界复核 | Tools / Runtime | 策略规则与审批交互 | `security.Action`、`security.CheckResult` | | Session | 会话持久化、摘要视图、状态恢复 | Runtime | 存储介质 | `session.Store`、`session.Session`、`session.SessionSummary` | | Config | 配置加载、校验、更新、快照提供 | Runtime / Gateway | 配置文件与环境变量 | `config.Registry` | | Utils | 通用辅助能力(Token/路径/解析/序列化) | Gateway / Runtime / Context / Tools | 基础库 | `utils.Registry` | @@ -126,6 +130,7 @@ graph TD | `Runtime -> Context` | `context.BuildInput`、`context.AdvancedBuildInput` | `context.BuildResult` | 编排层请求上下文构建 | | `Runtime -> Provider` | `provider.GenerateRequest` | `provider.StreamEvent` | 模型生成调用与流式事件回传 | | `Runtime -> Tools` | `tools.ToolCallInput` | `tools.ToolResult` | 工具执行与结果回灌 | +| `Tools / Runtime -> Security` | `security.Action` / `runtime.PermissionResolutionInput` | `security.CheckResult` / 审批事件 | 权限判定、审批闭环、session 记忆 | | `Runtime <-> Session` | `session.Store` | `session.Session`、`session.SessionSummary` | 会话读写与摘要查询 | | `Runtime <-> Config` | `config.Registry` | `config.Config` | 配置读取与更新事务 | | `Runtime/Context/Tools/Gateway -> Utils` | `utils.Registry` | 各子能力接口返回值 | 统一辅助能力调用入口 | @@ -148,11 +153,10 @@ graph TD 1. 先读本文档:系统边界、单入口链路、契约映射。 2. 再读核心编排:`runtime`、`session`。 -3. 再读协议与执行:`context`、`provider`、`tools`、`config`。 +3. 再读协议与执行:`context`、`provider`、`tools`、`security`、`config`。 4. 最后读入口与支撑:`gateway`、`tui`、`cli`、`utils`。 --- 本文档仅承载系统级架构定义。模块级实现细节请查看对应模块文档。 - diff --git a/docs/architecture/security/README.md b/docs/architecture/security/README.md new file mode 100644 index 00000000..cf167179 --- /dev/null +++ b/docs/architecture/security/README.md @@ -0,0 +1,195 @@ +# Security 模块设计与接口文档 + +> 文档版本:v1.0 +> 文档定位:详细设计文档(LLD)+ 接口文档(API/Contract) + +## 规范词约定 + +- `MUST`:必须满足的架构契约,违反会破坏权限治理闭环与执行安全。 +- `SHOULD`:强烈建议遵循,若例外必须记录原因。 +- `MAY`:可选增强能力。 + +## 1. 详细设计(LLD) + +### 1.1 目的与范围 + +Security 模块是 Tools / Runtime 之间的统一安全治理边界,负责权限策略命中、审批事件透传、session 级记忆与工作区边界复核。 + +Security 模块 MUST 覆盖: + +- 动作抽象与统一权限输入。 +- allow / ask / deny 策略命中。 +- session 级 `once / always_session / reject_session` 记忆。 +- `PermissionRequest / PermissionResolved` 事件发布。 +- 工作区与 sandbox 复核。 + +Security 模块 MUST NOT 覆盖: + +- 具体工具执行(由 Tools 负责)。 +- 主循环控制(由 Runtime 负责)。 +- TUI 审批交互界面实现(由 TUI / Gateway 负责)。 + +### 1.2 架构链路定位 + +- Security 的直接上游 SHOULD 是 Tools,Runtime 在 ask 闭环中参与审批回传。 +- Client 不得直接调用 Security 判定能力。 +- 单入口链路中关键路径为 `Runtime -> Tools -> Security -> Tools -> Runtime`。 + +### 1.3 模块边界 + +- 上游:Tools、Runtime。 +- 下游:静态策略规则、session 记忆存储、工作区边界校验。 +- 边界约束:Security 仅返回 `CheckResult` 与审批事件,不负责直接执行工具。 +- 边界约束:Security 不得感知 Provider 协议细节。 + +### 1.4 权限判定流程(当前/目标共性) + +```mermaid +sequenceDiagram + participant TL as Tools + participant SG as Security Gateway + participant PM as PolicyMatcher + participant MEM as PermissionMemoryStore + participant SB as Workspace Check + + TL->>SG: Evaluate(Action) + SG->>PM: Match(Action) + PM-->>SG: allow / ask / deny + SG->>MEM: Resolve(sessionID, action) + MEM-->>SG: remembered / miss + SG->>SB: validate workspace / sandbox + SB-->>SG: pass / fail + SG-->>TL: CheckResult +``` + +### 1.5 ask 审批闭环(目标态) + +```mermaid +sequenceDiagram + participant TL as Tools + participant SG as Security Gateway + participant EV as PermissionEventPublisher + participant RT as Runtime + participant UI as TUI/Gateway + + TL->>SG: Evaluate(Action) + SG-->>TL: CheckResult(decision=ask) + SG->>EV: PublishPermissionRequest + EV-->>RT: permission_request + RT-->>UI: permission_request + UI-->>RT: user decision + RT->>SG: Remember(sessionID, action, resolution) + SG->>EV: PublishPermissionResolved + EV-->>RT: permission_resolved +``` + +### 1.6 核心语义 + +- `allow`:允许直接执行。 +- `deny`:阻断执行,并返回稳定错误语义。 +- `ask`:要求上游发起显式审批闭环。 +- `once`:仅当前一次请求生效。 +- `always_session`:当前 session 内同范围请求持续放行。 +- `reject_session`:当前 session 内同范围请求持续拒绝。 + +### 1.7 非功能约束 + +- 安全性:硬性 deny 规则 MUST 不被宽泛的 session allow 记忆绕过。 +- 一致性:审批事件字段 SHOULD 可观测、可回放、可用于 UI 展示。 +- 可替换性:策略命中、session 存储、事件发布 SHOULD 通过接口解耦。 +- 可扩展性:未来 bash / filesystem / webfetch / MCP 的命中策略 SHOULD 共享统一 Action 模型。 + +## 2. 接口文档(API/Contract) + +### 2.1 公共规范 + +- 所有判定方法 MUST 接收 `context.Context`。 +- Security 对外 SHOULD 通过 `Action -> CheckResult` 建模。 +- ask 场景 MUST 可序列化为稳定事件与审批决议结构。 + +### 2.2 接口目录 + +| 接口 | 职责 | +|---|---| +| `PolicyMatcher` | 命中策略层 | +| `PermissionMemoryStore` | session 级记忆层 | +| `PermissionEventPublisher` | 审批事件透传层 | +| `ToolSecurityGateway` | 统一安全网关 | + +### 2.3 关键类型目录 + +| 类型 | 说明 | +|---|---| +| `Action` | 统一安全输入 | +| `ActionPayload` | 权限检查上下文 | +| `Rule` | 静态策略规则 | +| `Decision` | allow / ask / deny | +| `CheckResult` | 判定结果 | +| `PermissionRequest` | 审批请求事件负载 | +| `PermissionResolved` | 审批完成事件负载 | +| `PermissionResolution` | 上游回写的审批决议 | + +### 2.4 跨层契约绑定 + +| 链路 | 输入契约 | 输出契约 | 说明 | +|---|---|---|---| +| `Tools -> Security` | `security.Action` | `security.CheckResult` | 工具执行前权限判定 | +| `Runtime -> Security` | `security.PermissionResolution` | `PermissionResolved` 事件 | 审批结果回写与记忆更新 | +| `Security -> Runtime/TUI` | `PermissionRequest` / `PermissionResolved` | 运行时事件 | ask 闭环可观测化 | + +### 2.5 JSON 示例 + +#### 2.5.1 Action 示例 + +```json +{ + "type": "read", + "payload": { + "tool_name": "read_file", + "resource": "filesystem_read", + "operation": "read", + "session_id": "sess_123", + "workdir": "C:/workspace/demo", + "target_type": "path", + "target": "README.md" + } +} +``` + +#### 2.5.2 CheckResult 示例 + +```json +{ + "decision": "ask", + "reason": "reading target outside current trusted scope", + "rule": { + "id": "ask-filesystem-outside-workspace", + "resource": "filesystem_read" + } +} +``` + +#### 2.5.3 PermissionResolution 示例 + +```json +{ + "request_id": "perm_001", + "allowed": true, + "reason": "user approved in tui", + "scope": "always_session" +} +``` + +### 2.6 变更规则 + +- 新增策略字段 MUST 向后兼容。 +- 记忆范围新增 SHOULD 通过扩展枚举,不复用已有语义。 +- ask 相关事件字段调整 MUST 保持上游可判定性。 + +## 3. 评审检查清单 + +- 是否把权限判定、审批事件、session 记忆拆成独立职责。 +- 是否明确 Security 不直接执行工具。 +- 是否明确 ask 闭环与 session remember 的目标语义。 +- 是否为 Tools / Runtime 提供稳定契约,而不是暴露内部规则实现。 +- 是否与 `security/interface.go` 类型名一致。 diff --git a/docs/architecture/security/interface.go b/docs/architecture/security/interface.go new file mode 100644 index 00000000..3b959038 --- /dev/null +++ b/docs/architecture/security/interface.go @@ -0,0 +1,207 @@ +//go:build ignore +// +build ignore +// 说明:本文件为架构契约定义,仅用于文档与校验,不参与生产编译。 + +package security + +import "context" + +// Decision 表示权限判定结果。 +type Decision string + +const ( + // DecisionAllow 表示允许继续执行。 + DecisionAllow Decision = "allow" + // DecisionDeny 表示拒绝执行。 + DecisionDeny Decision = "deny" + // DecisionAsk 表示需要显式审批。 + DecisionAsk Decision = "ask" +) + +// ActionType 表示统一动作类型。 +type ActionType string + +const ( + // ActionTypeBash 表示命令执行类动作。 + ActionTypeBash ActionType = "bash" + // ActionTypeRead 表示读取类动作。 + ActionTypeRead ActionType = "read" + // ActionTypeWrite 表示写入类动作。 + ActionTypeWrite ActionType = "write" + // ActionTypeMCP 表示 MCP 工具调用类动作。 + ActionTypeMCP ActionType = "mcp" +) + +// TargetType 表示被访问目标的类型。 +type TargetType string + +const ( + // TargetTypePath 表示文件路径。 + TargetTypePath TargetType = "path" + // TargetTypeDirectory 表示目录。 + TargetTypeDirectory TargetType = "directory" + // TargetTypeCommand 表示命令文本。 + TargetTypeCommand TargetType = "command" + // TargetTypeURL 表示 URL。 + TargetTypeURL TargetType = "url" + // TargetTypeMCP 表示 MCP server/tool。 + TargetTypeMCP TargetType = "mcp" +) + +// ActionPayload 表示权限检查上下文。 +type ActionPayload struct { + // ToolName 是发起本次动作的工具名。 + ToolName string + // Resource 是资源类别,例如 filesystem_read / webfetch / bash。 + Resource string + // Operation 是操作名,例如 read / write / exec。 + Operation string + // SessionID 是当前会话标识。 + SessionID string + // Workdir 是当前工作目录。 + Workdir string + // TargetType 是目标类型。 + TargetType TargetType + // Target 是原始目标值。 + Target string + // SandboxTargetType 是复核后的工作区目标类型。 + SandboxTargetType TargetType + // SandboxTarget 是复核后的工作区目标。 + SandboxTarget string +} + +// Action 表示统一安全输入。 +type Action struct { + // Type 是动作类型。 + Type ActionType + // Payload 是动作上下文。 + Payload ActionPayload +} + +// Rule 表示静态策略规则。 +type Rule struct { + // ID 是规则标识。 + ID string + // Type 是动作类型。 + Type ActionType + // Resource 是资源类别。 + Resource string + // TargetPrefix 是命中的目标前缀。 + TargetPrefix string + // Decision 是命中后的决策。 + Decision Decision + // Reason 是规则说明。 + Reason string +} + +// CheckResult 表示权限引擎输出。 +type CheckResult struct { + // Decision 是最终决策。 + Decision Decision + // Action 是参与判定的动作。 + Action Action + // Rule 是命中的规则。 + Rule *Rule + // Reason 是最终说明。 + Reason string +} + +// PermissionRememberScope 表示 session 级记忆范围。 +type PermissionRememberScope string + +const ( + // PermissionRememberNone 表示不记忆。 + PermissionRememberNone PermissionRememberScope = "none" + // PermissionRememberOnce 表示仅一次。 + PermissionRememberOnce PermissionRememberScope = "once" + // PermissionRememberAlways 表示当前 session 内持续放行。 + PermissionRememberAlways PermissionRememberScope = "always_session" + // PermissionRememberReject 表示当前 session 内持续拒绝。 + PermissionRememberReject PermissionRememberScope = "reject_session" +) + +// PermissionResolution 表示上游回写的审批决议。 +type PermissionResolution struct { + // RequestID 是审批请求标识。 + RequestID string + // Allowed 表示是否放行。 + Allowed bool + // Reason 是审批理由。 + Reason string + // Scope 是 session 级记忆范围。 + Scope PermissionRememberScope +} + +// PermissionEventType 表示审批事件类型。 +type PermissionEventType string + +const ( + // PermissionEventRequest 表示审批请求事件。 + PermissionEventRequest PermissionEventType = "PermissionRequest" + // PermissionEventResolved 表示审批完成事件。 + PermissionEventResolved PermissionEventType = "PermissionResolved" +) + +// PermissionRequest 表示审批请求事件负载。 +type PermissionRequest struct { + // RequestID 是审批请求标识。 + RequestID string + // SessionID 是会话标识。 + SessionID string + // Action 是触发审批的动作。 + Action Action + // Decision 是当前引擎给出的决策。 + Decision Decision + // RuleID 是命中规则标识。 + RuleID string + // Reason 是审批原因。 + Reason string +} + +// PermissionResolved 表示审批完成事件负载。 +type PermissionResolved struct { + // RequestID 是审批请求标识。 + RequestID string + // SessionID 是会话标识。 + SessionID string + // Action 是触发审批的动作。 + Action Action + // Allowed 表示是否允许。 + Allowed bool + // Scope 是记忆范围。 + Scope PermissionRememberScope + // Reason 是结果说明。 + Reason string +} + +// PolicyMatcher 定义策略命中层。 +type PolicyMatcher interface { + // Match 根据 action 命中静态策略并返回判定结果。 + Match(ctx context.Context, action Action) (CheckResult, error) +} + +// PermissionMemoryStore 定义会话级记忆存储抽象。 +type PermissionMemoryStore interface { + // Remember 写入 session 级审批记忆。 + Remember(sessionID string, action Action, scope PermissionRememberScope, allowed bool) error + // Resolve 返回 session 级命中结果。 + Resolve(sessionID string, action Action) (allowed bool, scope PermissionRememberScope, ok bool) + // Clear 清理指定 session 下的所有记忆。 + Clear(sessionID string) error +} + +// PermissionEventPublisher 定义审批事件透传层。 +type PermissionEventPublisher interface { + // PublishPermissionRequest 发布审批请求事件。 + PublishPermissionRequest(ctx context.Context, event PermissionRequest) error + // PublishPermissionResolved 发布审批完成事件。 + PublishPermissionResolved(ctx context.Context, event PermissionResolved) error +} + +// ToolSecurityGateway 定义 Tools 层统一安全入口。 +type ToolSecurityGateway interface { + // Evaluate 执行动作判定,综合策略、记忆与工作区复核输出结果。 + Evaluate(ctx context.Context, action Action) (CheckResult, error) + // Remember 接收上游审批决议并写入 session 记忆。 + Remember(ctx context.Context, sessionID string, action Action, resolution PermissionResolution) error +} diff --git a/docs/architecture/tools/README.md b/docs/architecture/tools/README.md index 83d9fdb1..84152b5d 100644 --- a/docs/architecture/tools/README.md +++ b/docs/architecture/tools/README.md @@ -1,6 +1,6 @@ # Tools 模块设计与接口文档 -> 文档版本:v3.0 +> 文档版本:v3.1 > 文档定位:详细设计文档(LLD)+ 接口文档(API/Contract) ## 规范词约定 @@ -13,34 +13,38 @@ ### 1.1 目的与范围 -Tools 模块是 Runtime 的统一工具执行边界,负责工具能力暴露、参数承载、安全校验、执行管线与结果归一。 +Tools 模块是 Runtime 的统一工具执行边界,负责工具能力暴露、参数承载、安全协作、执行管线与结果归一。 Tools 模块 MUST 覆盖: - 工具清单暴露。 - 工具参数与执行上下文承载。 -- 权限与工作区沙箱校验。 -- 工具输出收敛与错误归一。 +- 与 Security 协作完成权限判定、审批回写、工作区约束。 +- 工具执行分发、输出收敛与错误归一。 +- 对 MCP 工具与内置工具提供统一接入门面。 Tools 模块 MUST NOT 覆盖: - 模型请求发送(由 Provider 负责)。 - 会话持久化(由 Session 负责)。 - 主循环编排决策(由 Runtime 负责)。 +- 安全策略命中规则定义本身(由 Security 负责)。 ### 1.2 架构链路定位 - Tools 的直接调用方 MUST 是 Runtime。 - Client 不得直接调用工具执行。 - 单入口链路中路径为 `Client -> Gateway -> Runtime -> Tools`。 +- Security MUST 作为 Tools 的下游协作模块参与审批与边界复核。 ### 1.3 模块边界 - 上游:Runtime。 -- 下游:具体工具实现、权限组件、沙箱组件。 +- 下游:具体工具实现、Security、MCP 适配层、沙箱组件。 - 边界约束:Tools 仅输出 `ToolResult` 与执行错误,不输出模型协议字段。 +- 边界约束:具体工具实现不得自行维护审批状态,审批记忆 MUST 通过统一门面收敛。 -### 1.4 工具执行管线 +### 1.4 工具执行管线(当前实现) ```mermaid sequenceDiagram @@ -51,23 +55,72 @@ sequenceDiagram RT->>TL: Execute(ToolCallInput) TL->>SEC: validate permission + workspace - SEC-->>TL: allow/deny - TL->>IMPL: run tool - IMPL-->>TL: raw output/error - TL-->>RT: ToolResult / error + SEC-->>TL: allow / ask / deny + alt allow + TL->>IMPL: run tool + IMPL-->>TL: raw output/error + TL-->>RT: ToolResult / error + else deny + TL-->>RT: ToolResult(is_error=true) / error + else ask + TL-->>RT: PermissionDecisionError + end ``` -### 1.5 审批闭环语义 +### 1.5 Tool / Security 协作分层(目标态) + +```mermaid +flowchart TD + RT["Runtime"] --> MGR["ToolManagerV2"] + MGR --> GATE["ToolSecurityGateway"] + GATE --> MATCH["PolicyMatcher"] + GATE --> MEM["PermissionMemoryStore"] + GATE --> SANDBOX["Workspace Sandbox"] + MGR --> EXEC["Builtin Executor / MCP Adapter"] + EXEC --> TOOL["Tool Impl"] +``` + +- Tools 层负责统一入口、执行分发、结果归一。 +- Security 层负责策略命中、审批事件、session 记忆、工作区复核。 +- MCP 接入 SHOULD 在 Tools 层完成统一注册与能力映射,不向 Runtime 暴露额外分支逻辑。 + +### 1.6 审批闭环语义 - 审批流程 MUST 具备请求、决策、结果三段语义。 - 审批相关事件 SHOULD 包含可观测字段:`tool_name`、`session_id`、`decision`、`reason`。 - 未通过审批的执行 MUST 被阻断并返回可判定错误语义。 +- ask 场景 SHOULD 形成 `permission_request -> 用户决策 -> resolve -> continue` 完整闭环。 +- session 级授权 SHOULD 支持 `once / always_session / reject_session` 三种记忆范围。 + +#### 1.6.1 ask 闭环时序(目标态) + +```mermaid +sequenceDiagram + participant RT as Runtime + participant TL as ToolManagerV2 + participant SG as ToolSecurityGateway + participant UI as TUI/Gateway + participant IMPL as Tool Impl -### 1.6 非功能约束 + RT->>TL: Execute(ToolCallInput) + TL->>SG: Evaluate(Action) + SG-->>TL: CheckResult(decision=ask) + TL-->>RT: PermissionRequest / PermissionDecisionError + RT-->>UI: permission_request + UI-->>RT: ResolvePermission + RT->>TL: ResolvePermission(PermissionResolution) + TL->>SG: Remember(sessionID, action, resolution) + TL->>IMPL: Execute(...) + IMPL-->>TL: ToolResult + TL-->>RT: ToolResult +``` + +### 1.7 非功能约束 - 安全性:执行 MUST 受工作区限制与权限策略约束。 - 稳定性:工具输出 SHOULD 做长度控制与结构收敛,避免上下文爆炸。 - 可观测性:关键执行阶段 SHOULD 可追踪。 +- 可扩展性:内置工具与 MCP 工具 SHOULD 通过统一 `ToolSpec / ToolCallInput / ToolResult` 收敛。 ## 2. 接口文档(API/Contract) @@ -76,12 +129,16 @@ sequenceDiagram - 所有方法 MUST 接收 `context.Context`。 - `Execute` MUST 使用 `ToolCallInput` 作为统一输入。 - 业务失败 SHOULD 通过 `ToolResult.IsError` 表达,系统失败通过 `error` 返回。 +- 流式工具 SHOULD 通过 `ChunkEmitter` 向上游发送 chunk,并允许回调显式中止执行。 ### 2.2 接口目录 | 接口 | 职责 | |---|---| -| `Manager` | 工具能力列举与工具执行 | +| `Manager` | 当前工具能力列举与工具执行门面 | +| `ToolSecurityGateway` | 统一安全入口(目标态) | +| `PermissionMemoryStore` | session 级权限记忆(目标态) | +| `MCPRegistryAdapter` | MCP server 注册与工具发现(目标态) | | `SubAgentOrchestrator` | 子任务隔离执行扩展 | ### 2.3 关键类型目录 @@ -93,6 +150,8 @@ sequenceDiagram | `ToolCallInput` | 工具执行输入 | | `ToolResult` | 工具执行结果 | | `WorkspaceExecutionPlan` | 工作区约束计划 | +| `PermissionResolution` | 审批决议(目标态) | +| `PermissionRememberScope` | session 级审批记忆范围(目标态) | ### 2.4 跨层契约绑定 @@ -100,6 +159,8 @@ sequenceDiagram |---|---|---|---| | `Runtime -> Tools`(能力列举) | `tools.SpecListInput` | `[]tools.ToolSpec` | 模型调用前注入工具清单 | | `Runtime -> Tools`(执行) | `tools.ToolCallInput` | `tools.ToolResult` | 工具执行并回灌结果 | +| `Tools -> Security`(当前/目标) | `security.Action` / `PermissionResolution` | `security.CheckResult` | 权限判定、审批回写、session 记忆 | +| `Tools -> MCP`(目标) | `server_id + source` | `[]tools.ToolSpec` | 动态注册远端工具并统一暴露 | ### 2.5 JSON 示例 @@ -136,7 +197,18 @@ sequenceDiagram {"type":"permission_resolved","payload":{"tool_name":"bash","session_id":"sess_123","decision":"approved"}} ``` -#### 2.5.4 失败示例 +#### 2.5.4 PermissionResolution 示例(目标态) + +```json +{ + "request_id": "perm_001", + "allowed": true, + "reason": "user approved in tui", + "scope": "always_session" +} +``` + +#### 2.5.5 失败示例 ```json { @@ -150,6 +222,7 @@ sequenceDiagram - 新增字段 MUST 保持向后兼容。 - 字段改名/删除 MUST 经过版本化流程并提供迁移窗口。 - 扩展能力 SHOULD 通过新增字段或新增接口演进,不破坏 `Manager` 稳定签名。 +- Security 相关增强 SHOULD 优先新增辅助接口,不直接把策略细节泄漏到具体 Tool 实现。 ## 3. 评审检查清单 @@ -158,3 +231,4 @@ sequenceDiagram - 是否包含审批语义与失败示例。 - 是否定义安全约束与输出收敛约束。 - 是否与 `tools/interface.go` 类型名一致。 +- 是否明确 Tools 与 Security 的边界,而不是把权限策略写死在具体工具实现中。 diff --git a/docs/architecture/tools/interface.go b/docs/architecture/tools/interface.go index 3ceec5c4..a3a62c53 100644 --- a/docs/architecture/tools/interface.go +++ b/docs/architecture/tools/interface.go @@ -33,7 +33,12 @@ type WorkspaceExecutionPlan struct { } // ChunkEmitter 是工具流式输出回调。 -type ChunkEmitter func(chunk []byte) +// 并发语义: +// - 单次 Execute 内按顺序调用; +// - 回调返回非 nil error 时,工具应停止继续发送分片并尽快中止执行。 +// 内存语义: +// - 回调返回后不得继续持有传入的 chunk 引用。 +type ChunkEmitter func(chunk []byte) error // ToolCallInput 是一次工具调用输入。 type ToolCallInput struct { @@ -67,45 +72,78 @@ type ToolResult struct { Metadata map[string]any } -// Manager 定义 runtime 侧工具边界。 +// PermissionRememberScope 表示审批结果在 session 中的记忆范围。 +type PermissionRememberScope string + +const ( + // PermissionRememberNone 表示不记录。 + PermissionRememberNone PermissionRememberScope = "none" + // PermissionRememberOnce 表示仅本次有效。 + PermissionRememberOnce PermissionRememberScope = "once" + // PermissionRememberAlways 表示当前会话内持续放行。 + PermissionRememberAlways PermissionRememberScope = "always_session" + // PermissionRememberReject 表示当前会话内持续拒绝。 + PermissionRememberReject PermissionRememberScope = "reject_session" +) + +// PermissionResolution 表示一次审批决议。 +type PermissionResolution struct { + // RequestID 是审批请求标识。 + RequestID string + // Allowed 表示是否允许继续执行。 + Allowed bool + // Reason 是审批理由或来源说明。 + Reason string + // Scope 表示 session 记忆范围。 + Scope PermissionRememberScope +} + +// Manager 定义 runtime 侧当前工具边界。 type Manager interface { // ListAvailableSpecs 返回当前上下文可见工具列表。 - // 职责:向模型暴露可调用工具能力。 - // 输入语义:input 提供会话与代理上下文。 - // 并发约束:应支持并发读取且保证返回结果一致语义。 - // 生命周期:每轮 provider 调用前调用。 - // 错误语义:返回注册表读取失败、权限过滤失败或策略计算失败。 ListAvailableSpecs(ctx context.Context, input SpecListInput) ([]ToolSpec, error) // Execute 执行一次工具调用。 - // 职责:执行权限校验、沙箱校验并调用具体工具。 - // 输入语义:input 为模型发起的工具调用,包含执行上下文与约束计划。 - // 并发约束:执行链路线程安全,同名工具可并发,不同会话互不影响。 - // 生命周期:每个工具调用返回一次结果或错误。 - // 错误语义:系统错误通过 error 返回,业务失败通过 ToolResult.IsError 表达。 Execute(ctx context.Context, input ToolCallInput) (ToolResult, error) } +// ToolManagerV2 定义 #98 收口后的目标工具门面。 +type ToolManagerV2 interface { + // ListAvailableSpecs 返回当前上下文可见工具列表。 + ListAvailableSpecs(ctx context.Context, input SpecListInput) ([]ToolSpec, error) + // Execute 执行一次工具调用。 + Execute(ctx context.Context, input ToolCallInput) (ToolResult, error) + // ResolvePermission 接收 UI/Runtime 回传的审批结果。 + ResolvePermission(ctx context.Context, resolution PermissionResolution) error +} + +// PermissionMemoryStore 定义工具侧可替换的 session 记忆存储。 +type PermissionMemoryStore interface { + // Remember 记录一次审批记忆。 + Remember(sessionID string, actionKey string, scope PermissionRememberScope, allowed bool) error + // Resolve 读取已命中的 session 记忆。 + Resolve(sessionID string, actionKey string) (allowed bool, scope PermissionRememberScope, ok bool) + // Clear 清理会话下全部记忆。 + Clear(sessionID string) error +} + +// MCPRegistryAdapter 定义 MCP server 生命周期与工具发现契约。 +type MCPRegistryAdapter interface { + // RegisterServer 注册一个 MCP server。 + RegisterServer(ctx context.Context, serverID string, source string, version string) error + // UnregisterServer 注销一个 MCP server。 + UnregisterServer(ctx context.Context, serverID string) error + // RefreshServerTools 刷新指定 server 的工具列表。 + RefreshServerTools(ctx context.Context, serverID string) error + // ListServerTools 返回所有已注册 server 暴露的工具能力。 + ListServerTools(ctx context.Context) ([]ToolSpec, error) +} + // SubAgentOrchestrator 定义子任务隔离执行扩展契约。 type SubAgentOrchestrator interface { // Spawn 创建子任务。 - // 职责:创建隔离子代理执行任务。 - // 输入语义:task 为任务文本,scope 为隔离范围标识。 - // 并发约束:支持并发创建多个子任务。 - // 生命周期:返回的 agentID 用于后续等待或取消。 - // 错误语义:返回调度失败、参数非法或资源不足错误。 Spawn(ctx context.Context, task string, scope string) (agentID string, err error) // Wait 等待子任务结束。 - // 职责:阻塞直到子任务完成或超时。 - // 输入语义:agentID 为子任务标识。 - // 并发约束:支持并发等待不同子任务。 - // 生命周期:通常在主循环需要结果时调用。 - // 错误语义:返回超时、取消、任务不存在或子任务失败错误。 Wait(ctx context.Context, agentID string) (result ToolResult, err error) // Cancel 取消子任务。 - // 职责:中止指定子任务执行。 - // 输入语义:agentID 为子任务标识。 - // 并发约束:应幂等且线程安全。 - // 生命周期:用户取消或门禁触发时调用。 - // 错误语义:返回取消失败或任务不存在错误。 Cancel(ctx context.Context, agentID string) error -} \ No newline at end of file +}