first commit
This commit is contained in:
655
claude-code-中文Wiki/07-权限系统.md
Normal file
655
claude-code-中文Wiki/07-权限系统.md
Normal file
@@ -0,0 +1,655 @@
|
||||
# Claude Code 权限系统详解
|
||||
|
||||
## 概述
|
||||
|
||||
Claude Code 的权限系统管理工具调用的授权流程。当 Claude 尝试执行危险操作(如运行 Bash 命令、写入文件)时,系统会请求用户确认。权限系统支持多种授权模式和来源,确保用户对工具执行有完全控制。
|
||||
|
||||
---
|
||||
|
||||
## 核心架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 权限请求入口 │
|
||||
│ │
|
||||
│ hasPermissionsToUseTool(tool, input, context, message, id) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 权限模式检查 (PermissionMode) │
|
||||
│ │
|
||||
│ default | plan | bypassPermissions | auto | localAssistant │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
▼ ▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ Coordinator │ │ Interactive │ │ Swarm Worker │
|
||||
│ Handler │ │ Handler │ │ Handler │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│ │ │
|
||||
└───────────────┼───────────────┘
|
||||
▼
|
||||
┌──────────────────────────────────────┐
|
||||
│ 权限决策结果 │
|
||||
│ │
|
||||
│ allow | deny | ask | skip │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 权限模式 (PermissionMode)
|
||||
|
||||
**文件位置**: `src/utils/permissions/PermissionMode.ts`
|
||||
|
||||
### 模式类型
|
||||
|
||||
```typescript
|
||||
type PermissionMode =
|
||||
| 'default' // 标准交互式权限确认
|
||||
| 'plan' // 计划模式,只读操作
|
||||
| 'bypassPermissions' // 跳过所有权限检查
|
||||
| 'auto' // 自动批准基于分类器
|
||||
| 'localAssistant' // 本地助手模式
|
||||
```
|
||||
|
||||
### 模式转换
|
||||
|
||||
```typescript
|
||||
export function transitionPermissionMode(
|
||||
from: PermissionMode,
|
||||
to: PermissionMode,
|
||||
options?: { skipAutoGate?: boolean }
|
||||
): { ok: true } | { ok: false; error: string }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. PermissionContext - 权限上下文
|
||||
|
||||
**文件位置**: `src/hooks/toolPermission/PermissionContext.ts`
|
||||
|
||||
### 创建权限上下文
|
||||
|
||||
```typescript
|
||||
function createPermissionContext(
|
||||
tool: ToolType,
|
||||
input: Record<string, unknown>,
|
||||
toolUseContext: ToolUseContext,
|
||||
assistantMessage: AssistantMessage,
|
||||
toolUseID: string,
|
||||
setToolPermissionContext: (context: ToolPermissionContext) => void,
|
||||
queueOps?: PermissionQueueOps,
|
||||
)
|
||||
```
|
||||
|
||||
### 上下文方法
|
||||
|
||||
```typescript
|
||||
type PermissionContext = {
|
||||
// 工具信息
|
||||
tool: ToolType
|
||||
input: Record<string, unknown>
|
||||
toolUseContext: ToolUseContext
|
||||
assistantMessage: AssistantMessage
|
||||
messageId: string
|
||||
toolUseID: string
|
||||
|
||||
// 日志记录
|
||||
logDecision(args: PermissionDecisionArgs, opts?: {...}): void
|
||||
logCancelled(): void
|
||||
|
||||
// 权限持久化
|
||||
async persistPermissions(updates: PermissionUpdate[]): Promise<boolean>
|
||||
|
||||
// 决策构建
|
||||
buildAllow(
|
||||
updatedInput: Record<string, unknown>,
|
||||
opts?: {...}
|
||||
): PermissionAllowDecision
|
||||
|
||||
buildDeny(
|
||||
message: string,
|
||||
decisionReason: PermissionDecisionReason
|
||||
): PermissionDenyDecision
|
||||
|
||||
// 用户处理
|
||||
async handleUserAllow(
|
||||
updatedInput: Record<string, unknown>,
|
||||
permissionUpdates: PermissionUpdate[],
|
||||
feedback?: string,
|
||||
...
|
||||
): Promise<PermissionAllowDecision>
|
||||
|
||||
// Hook 执行
|
||||
async runHooks(
|
||||
permissionMode: string | undefined,
|
||||
suggestions: PermissionUpdate[] | undefined,
|
||||
updatedInput?: Record<string, unknown>,
|
||||
...
|
||||
): Promise<PermissionDecision | null>
|
||||
|
||||
// 分类器尝试
|
||||
async tryClassifier(
|
||||
pendingClassifierCheck: PendingClassifierCheck | undefined,
|
||||
updatedInput: Record<string, unknown> | undefined
|
||||
): Promise<PermissionDecision | null>
|
||||
|
||||
// 队列操作
|
||||
pushToQueue(item: ToolUseConfirm): void
|
||||
removeFromQueue(): void
|
||||
updateQueueItem(patch: Partial<ToolUseConfirm>): void
|
||||
|
||||
// 中止处理
|
||||
resolveIfAbort(resolve: (decision: PermissionDecision) => void): boolean
|
||||
cancelAndAbort(
|
||||
feedback?: string,
|
||||
isAbort?: boolean,
|
||||
contentBlocks?: ContentBlockParam[]
|
||||
): PermissionDecision
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 权限决策类型
|
||||
|
||||
**文件位置**: `src/types/permissions.ts`
|
||||
|
||||
### 决策类型
|
||||
|
||||
```typescript
|
||||
type PermissionDecision =
|
||||
| { behavior: 'allow'; updatedInput?: Record<string, unknown>; ... }
|
||||
| { behavior: 'deny'; message: string; ... }
|
||||
| { behavior: 'ask' }
|
||||
| { behavior: 'skip' }
|
||||
```
|
||||
|
||||
### 决策来源
|
||||
|
||||
```typescript
|
||||
type PermissionDecisionSource =
|
||||
| { type: 'hook'; permanent?: boolean }
|
||||
| { type: 'user'; permanent: boolean }
|
||||
| { type: 'classifier' }
|
||||
| 'config' // 配置自动允许
|
||||
```
|
||||
|
||||
### 待处理分类器检查
|
||||
|
||||
```typescript
|
||||
type PendingClassifierCheck = {
|
||||
input: Record<string, unknown>
|
||||
command: string
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 权限处理器
|
||||
|
||||
### 4.1 Coordinator Handler
|
||||
|
||||
**文件位置**: `src/hooks/toolPermission/handlers/coordinatorHandler.ts`
|
||||
|
||||
用于协调者工作进程(coordinator worker)的权限处理流程。
|
||||
|
||||
```typescript
|
||||
async function handleCoordinatorPermission(
|
||||
params: CoordinatorPermissionParams
|
||||
): Promise<PermissionDecision | null>
|
||||
```
|
||||
|
||||
**处理流程**:
|
||||
|
||||
1. **尝试权限 Hooks**(快速,本地)
|
||||
```typescript
|
||||
const hookResult = await ctx.runHooks(
|
||||
permissionMode,
|
||||
suggestions,
|
||||
updatedInput
|
||||
)
|
||||
if (hookResult) return hookResult
|
||||
```
|
||||
|
||||
2. **尝试分类器**(慢速,推理)
|
||||
```typescript
|
||||
const classifierResult = feature('BASH_CLASSIFIER')
|
||||
? await ctx.tryClassifier?.(pendingClassifierCheck, updatedInput)
|
||||
: null
|
||||
if (classifierResult) return classifierResult
|
||||
```
|
||||
|
||||
3. **降级到交互式对话框**
|
||||
```typescript
|
||||
return null // 交给交互式处理
|
||||
```
|
||||
|
||||
### 4.2 Interactive Handler
|
||||
|
||||
**文件位置**: `src/hooks/toolPermission/handlers/interactiveHandler.ts`
|
||||
|
||||
用于主代理的交互式权限处理。
|
||||
|
||||
```typescript
|
||||
function handleInteractivePermission(
|
||||
params: InteractivePermissionParams,
|
||||
resolve: (decision: PermissionDecision) => void,
|
||||
): void
|
||||
```
|
||||
|
||||
**处理流程**:
|
||||
|
||||
1. **推送确认队列项**
|
||||
```typescript
|
||||
ctx.pushToQueue({
|
||||
assistantMessage,
|
||||
tool,
|
||||
description,
|
||||
input: displayInput,
|
||||
toolUseID,
|
||||
permissionResult: result,
|
||||
permissionPromptStartTimeMs,
|
||||
onUserInteraction: () => { ... },
|
||||
onAbort: () => { ... },
|
||||
onAllow: () => { ... },
|
||||
onReject: () => { ... },
|
||||
recheckPermission: () => { ... },
|
||||
})
|
||||
```
|
||||
|
||||
2. **桥接权限转发**(远程控制)
|
||||
```typescript
|
||||
if (bridgeCallbacks && bridgeRequestId) {
|
||||
bridgeCallbacks.sendRequest(
|
||||
bridgeRequestId,
|
||||
ctx.tool.name,
|
||||
displayInput,
|
||||
ctx.toolUseID,
|
||||
description,
|
||||
result.suggestions,
|
||||
result.blockedPath
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
3. **通道权限转发**(KAIROS)
|
||||
```typescript
|
||||
if (channelCallbacks && !ctx.tool.requiresUserInteraction?.()) {
|
||||
// 发送到通道(Telegram, iMessage 等)
|
||||
client.notification({
|
||||
method: CHANNEL_PERMISSION_REQUEST_METHOD,
|
||||
params
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
4. **异步 Hook 执行**
|
||||
```typescript
|
||||
void (async () => {
|
||||
const hookDecision = await ctx.runHooks(...)
|
||||
if (hookDecision && claim()) {
|
||||
resolveOnce(hookDecision)
|
||||
}
|
||||
})()
|
||||
```
|
||||
|
||||
5. **异步分类器执行**
|
||||
```typescript
|
||||
if (feature('BASH_CLASSIFIER') && result.pendingClassifierCheck) {
|
||||
setClassifierChecking(ctx.toolUseID)
|
||||
void executeAsyncClassifierCheck(...)
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Swarm Worker Handler
|
||||
|
||||
**文件位置**: `src/hooks/toolPermission/handlers/swarmWorkerHandler.ts`
|
||||
|
||||
用于 Swarm Worker 的权限处理(简化的仅拒绝处理)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 权限回调 (Bridge Permission Callbacks)
|
||||
|
||||
**文件位置**: `src/bridge/bridgePermissionCallbacks.ts`
|
||||
|
||||
### 回调接口
|
||||
|
||||
```typescript
|
||||
type BridgePermissionCallbacks = {
|
||||
sendRequest(
|
||||
requestId: string,
|
||||
toolName: string,
|
||||
input: Record<string, unknown>,
|
||||
toolUseId: string,
|
||||
description: string,
|
||||
permissionSuggestions?: PermissionUpdate[],
|
||||
blockedPath?: string,
|
||||
): void
|
||||
|
||||
sendResponse(requestId: string, response: BridgePermissionResponse): void
|
||||
|
||||
cancelRequest(requestId: string): void
|
||||
|
||||
onResponse(
|
||||
requestId: string,
|
||||
handler: (response: BridgePermissionResponse) => void,
|
||||
): () => void
|
||||
}
|
||||
```
|
||||
|
||||
### 权限响应
|
||||
|
||||
```typescript
|
||||
type BridgePermissionResponse = {
|
||||
behavior: 'allow' | 'deny'
|
||||
updatedInput?: Record<string, unknown>
|
||||
updatedPermissions?: PermissionUpdate[]
|
||||
message?: string
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 权限规则管理
|
||||
|
||||
### 6.1 PermissionUpdate
|
||||
|
||||
**文件位置**: `src/utils/permissions/PermissionUpdateSchema.ts`
|
||||
|
||||
```typescript
|
||||
type PermissionUpdate = {
|
||||
destination: 'alwaysAllowRules' | 'alwaysDenyRules' | 'command'
|
||||
rule: {
|
||||
tool: string
|
||||
input?: Record<string, unknown>
|
||||
matchers?: InputMatcher[]
|
||||
}
|
||||
Permanente: boolean
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 规则应用
|
||||
|
||||
```typescript
|
||||
export function applyPermissionUpdates(
|
||||
context: ToolPermissionContext,
|
||||
updates: PermissionUpdate[]
|
||||
): ToolPermissionContext
|
||||
```
|
||||
|
||||
### 6.3 规则持久化
|
||||
|
||||
```typescript
|
||||
export function persistPermissionUpdates(updates: PermissionUpdate[]): void
|
||||
export function supportsPersistence(
|
||||
destination: 'alwaysAllowRules' | 'alwaysDenyRules' | 'command'
|
||||
): boolean
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Bash 分类器
|
||||
|
||||
**文件位置**: `src/tools/BashTool/bashPermissions.ts`
|
||||
|
||||
### 分类器决策
|
||||
|
||||
```typescript
|
||||
type ClassifierDecision =
|
||||
| { type: 'classifier'; classifier: 'auto-mode'; reason: string }
|
||||
| { type: 'classifier'; classifier: 'pattern-match'; reason: string }
|
||||
| { type: 'user-defined'; reason: string }
|
||||
| { type: 'deny'; reason: string }
|
||||
```
|
||||
|
||||
### 分类器检查
|
||||
|
||||
```typescript
|
||||
export async function awaitClassifierAutoApproval(
|
||||
pendingClassifierCheck: PendingClassifierCheck,
|
||||
signal: AbortSignal,
|
||||
isNonInteractiveSession: boolean,
|
||||
): Promise<ClassifierDecision | null>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 权限日志
|
||||
|
||||
**文件位置**: `src/hooks/toolPermission/permissionLogging.ts`
|
||||
|
||||
### 日志函数
|
||||
|
||||
```typescript
|
||||
export function logPermissionDecision(
|
||||
args: PermissionDecisionArgs,
|
||||
decision: {
|
||||
decision: 'accept' | 'reject'
|
||||
source: PermissionApprovalSource | PermissionRejectionSource
|
||||
},
|
||||
permissionPromptStartTimeMs?: number
|
||||
): void
|
||||
```
|
||||
|
||||
### 事件类型
|
||||
|
||||
```typescript
|
||||
// 接受
|
||||
logEvent('tengu_tool_permission_accepted', {...})
|
||||
logEvent('tengu_tool_permission_auto_approved', {...})
|
||||
|
||||
// 拒绝
|
||||
logEvent('tengu_tool_permission_rejected', {...})
|
||||
logEvent('tengu_tool_use_cancelled', {...})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 权限检查入口
|
||||
|
||||
**文件位置**: `src/utils/permissions/permissions.ts`
|
||||
|
||||
### 主检查函数
|
||||
|
||||
```typescript
|
||||
export async function hasPermissionsToUseTool(
|
||||
tool: Tool,
|
||||
input: Record<string, unknown>,
|
||||
toolUseContext: ToolUseContext,
|
||||
assistantMessage: AssistantMessage,
|
||||
toolUseID: string,
|
||||
): Promise<PermissionDecision>
|
||||
```
|
||||
|
||||
**决策流程**:
|
||||
|
||||
1. **模式检查**
|
||||
- `bypassPermissions`: 直接允许
|
||||
- `plan`: 计划模式规则
|
||||
- `auto`: 分类器自动决策
|
||||
|
||||
2. **规则匹配**
|
||||
- `alwaysAllowRules`: 匹配则允许
|
||||
- `alwaysDenyRules`: 匹配则拒绝
|
||||
|
||||
3. **会话状态**
|
||||
- 非交互式会话可能有不同行为
|
||||
|
||||
4. **分类器检查**
|
||||
- 仅 Bash 工具支持
|
||||
- 异步执行
|
||||
|
||||
5. **Hook 检查**
|
||||
- 执行 PermissionRequest hooks
|
||||
|
||||
6. **降级到交互式**
|
||||
- 返回 `{ behavior: 'ask' }`
|
||||
|
||||
---
|
||||
|
||||
## 10. 权限队列
|
||||
|
||||
### ToolUseConfirm
|
||||
|
||||
```typescript
|
||||
type ToolUseConfirm = {
|
||||
assistantMessage: AssistantMessage
|
||||
tool: Tool
|
||||
description: string
|
||||
input: Record<string, unknown>
|
||||
toolUseContext: ToolUseContext
|
||||
toolUseID: string
|
||||
permissionResult: PermissionDecision & { behavior: 'ask' }
|
||||
permissionPromptStartTimeMs: number
|
||||
classifierCheckInProgress?: boolean
|
||||
classifierAutoApproved?: boolean
|
||||
classifierMatchedRule?: string
|
||||
|
||||
onUserInteraction(): void
|
||||
onDismissCheckmark(): void
|
||||
onAbort(): void
|
||||
onAllow(
|
||||
updatedInput: Record<string, unknown>,
|
||||
permissionUpdates: PermissionUpdate[],
|
||||
feedback?: string,
|
||||
contentBlocks?: ContentBlockParam[]
|
||||
): Promise<void>
|
||||
onReject(feedback?: string, contentBlocks?: ContentBlockParam[]): void
|
||||
recheckPermission(): Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 权限处理流程图
|
||||
|
||||
```
|
||||
用户执行工具
|
||||
│
|
||||
▼
|
||||
hasPermissionsToUseTool()
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 权限模式检查 │
|
||||
│ bypassPermissions? │ ───是──▶ 直接允许
|
||||
└─────────────────────┘
|
||||
│否
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 规则检查 │
|
||||
│ alwaysAllowRules? │ ───是──▶ 直接允许
|
||||
│ alwaysDenyRules? │ ───是──▶ 直接拒绝
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ 分类器检查 │
|
||||
│ BASH_CLASSIFIER? │ ───是──▶ 异步推理
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Hook 检查 │
|
||||
│ executePermission │ ───允许──▶ 返回允许
|
||||
│ RequestHooks │ ───拒绝──▶ 返回拒绝
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
交互式确认对话框
|
||||
│
|
||||
├─── 用户允许 ───▶ handleUserAllow()
|
||||
│ │
|
||||
│ ▼
|
||||
│ persistPermissions()
|
||||
│ │
|
||||
│ ▼
|
||||
│ logPermissionDecision()
|
||||
│ │
|
||||
│ ▼
|
||||
│ 返回 PermissionAllowDecision
|
||||
│
|
||||
├─── 用户拒绝 ───▶ onReject()
|
||||
│ │
|
||||
│ ▼
|
||||
│ cancelAndAbort()
|
||||
│ │
|
||||
│ ▼
|
||||
│ 返回 PermissionDenyDecision
|
||||
│
|
||||
└─── 用户中断 ───▶ Esc 按键
|
||||
│
|
||||
▼
|
||||
abortController.abort()
|
||||
│
|
||||
▼
|
||||
返回 PermissionDenyDecision
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 远程权限流程
|
||||
|
||||
```
|
||||
CLI 端 (handleInteractivePermission)
|
||||
│
|
||||
▼
|
||||
bridgeCallbacks.sendRequest(bridgeRequestId, ...)
|
||||
│
|
||||
│ WebSocket / HTTP
|
||||
▼
|
||||
IDE Extension / Web UI
|
||||
│
|
||||
▼
|
||||
显示权限对话框
|
||||
│
|
||||
▼
|
||||
用户允许/拒绝
|
||||
│
|
||||
▼
|
||||
bridgeCallbacks.sendResponse(bridgeRequestId, response)
|
||||
│
|
||||
│ WebSocket / HTTP
|
||||
▼
|
||||
CLI 端 (onResponse 回调)
|
||||
│
|
||||
▼
|
||||
resolveOnce(decision)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 13. 关键常量
|
||||
|
||||
```typescript
|
||||
// 200ms 宽限期后用户交互取消分类器
|
||||
const GRACE_PERIOD_MS = 200
|
||||
|
||||
// 分类器自动批准后显示 ✓ 的时间
|
||||
const CHECKMARK_DISPLAY_MS = 3000 // 终端聚焦时
|
||||
const CHECKMARK_DISPLAY_MS = 1000 // 终端未聚焦时
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关源码文件
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `PermissionContext.ts` | 权限上下文创建和管理 |
|
||||
| `handlers/coordinatorHandler.ts` | 协调者处理器 |
|
||||
| `handlers/interactiveHandler.ts` | 交互式处理器 |
|
||||
| `handlers/swarmWorkerHandler.ts` | Swarm Worker 处理器 |
|
||||
| `permissionLogging.ts` | 权限日志记录 |
|
||||
| `src/utils/permissions/permissions.ts` | 权限检查入口 |
|
||||
| `src/utils/permissions/PermissionUpdate.ts` | 权限更新管理 |
|
||||
| `src/utils/permissions/PermissionMode.ts` | 权限模式定义 |
|
||||
| `src/bridge/bridgePermissionCallbacks.ts` | 桥接权限回调 |
|
||||
| `src/tools/BashTool/bashPermissions.ts` | Bash 分类器 |
|
||||
| `src/types/permissions.ts` | 权限类型定义 |
|
||||
Reference in New Issue
Block a user