first commit

This commit is contained in:
H
2026-04-03 13:01:19 +08:00
commit 538eced414
2575 changed files with 645911 additions and 0 deletions

View 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` | 权限类型定义 |