mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-21 21:03:38 +08:00
feat: consolidate course into 21 lessons
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21 → s22
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21
|
||||
> *"ツール実行前に権限を判断"* — 権限パイプラインは、どの操作に承認が必要かを決める。
|
||||
>
|
||||
> **Harness レイヤー**: 権限 — ツール実行前に一つのゲートを追加。
|
||||
@@ -39,7 +39,7 @@ s02 のループは完全に維持される。唯一の変更は、ツール実
|
||||
|
||||

|
||||
|
||||
**ゲート 1**:ハード拒否リスト。最初に確認し、一致すればブロックメッセージを返す。(教育デモ:単純な文字列マッチングは信頼できるセキュリティ機構ではない — コマンドの変種やシェル展開で回避される可能性がある。CC のアプローチは付録を参照。)
|
||||
**ゲート 1**:ハード拒否リスト。最初に確認し、一致すればブロックメッセージを返す。このリストは権限ゲートの位置を示すための単純な文字列照合であり、完全なセキュリティ境界ではない。
|
||||
|
||||
```python
|
||||
DENY_LIST = [
|
||||
@@ -153,80 +153,5 @@ python s03_permission/code.py
|
||||
|
||||
→ s04 Hooks:ループにフックを追加する。拡張ロジックはフックにぶら下げ、ループはクリーンに保つ。
|
||||
|
||||
<details>
|
||||
<summary>CC ソースコードを深掘り</summary>
|
||||
|
||||
> 以下は CC ソースコード `types/permissions.ts`、`utils/permissions/permissions.ts`、`toolExecution.ts`、`utils/permissions/yoloClassifier.ts`、`tools/AgentTool/forkSubagent.ts` の検証に基づく。
|
||||
|
||||
### 一、PermissionResult:3 種ではなく、4 種
|
||||
|
||||
教育版の 3 つのゲート(deny → ask → allow)は CC と完全には対応しない。CC の `PermissionResult` には 4 つの behavior がある(`types/permissions.ts:241-266`):
|
||||
|
||||
| behavior | 意味 | 教育版の対応 |
|
||||
|----------|------|-------------|
|
||||
| `allow` | 直接許可 | ゲート 3 通過 |
|
||||
| `deny` | 直接拒否 | ゲート 1 一致 |
|
||||
| `ask` | ユーザーにダイアログを表示 | ゲート 2 一致 |
|
||||
| `passthrough` | ツールが意見を表明せず、汎用パイプラインに委ねる | 教育版にはなし |
|
||||
|
||||
### 二、本番環境の検証段階
|
||||
|
||||
CC のツール呼び出しは 3 つのゲートを通るのではなく、`checkPermissionsAndCallTool()`(`toolExecution.ts:599-1745`)、hooks、`hasPermissionsToUseToolInner()`(`utils/permissions/permissions.ts:1158-1310`)、classifier ロジックに分散する複数の段階を経る:
|
||||
|
||||
1. **Zod schema 検証**(`toolExecution.ts:614-680`)— パラメータの型チェック
|
||||
2. **validateInput()**(`toolExecution.ts:682-733`)— ツールレベルの意味的検証
|
||||
3. **backfillObservableInput()**(`toolExecution.ts:784`)— レガシーフィールドの補完
|
||||
4. **PreToolUse hooks**(`toolExecution.ts:800-862`)— フックが allow/deny/ask を返す
|
||||
5. **resolveHookPermissionDecision()**(`toolExecution.ts:921-931`)— フック + パイプラインの決定を調整
|
||||
6. **hasPermissionsToUseToolInner()**(`permissions.ts:1158-1310`)— 多層ルールチェック:
|
||||
- ツール全体が deny rule で無効 → `deny`
|
||||
- ツール全体が ask rule でマーク → `ask`
|
||||
- `tool.checkPermissions()` ツール自身の判断
|
||||
- ツール自身が deny を返す → `deny`
|
||||
- `requiresUserInteraction()` → `ask`
|
||||
- コンテンツ関連の ask ルール → `ask`(バイパス不可)
|
||||
- セキュリティチェック違反 → `ask`(バイパス不可)
|
||||
- bypassPermissions モード → `allow`
|
||||
- ツール全体が allow rule で許可 → `allow`
|
||||
- passthrough → `ask` に変換
|
||||
|
||||
### 三、拒否リスト:1 つのファイルではなく、8 つのソース
|
||||
|
||||
CC には単一の deny list はない。権限ルールは 8 つのソースから来る(`types/permissions.ts:54-62`):
|
||||
|
||||
| ソース | 設定場所 |
|
||||
|--------|---------|
|
||||
| `userSettings` | `~/.claude/settings.json` |
|
||||
| `projectSettings` | `.claude/settings.json` |
|
||||
| `localSettings` | `settings.local.json` |
|
||||
| `flagSettings` | フィーチャーフラグ |
|
||||
| `policySettings` | 企業管理ポリシー |
|
||||
| `cliArg` | `--allowedTools` / `--deniedTools` |
|
||||
| `command` | インラインコマンド |
|
||||
| `session` | セッション内一時承認 |
|
||||
|
||||
各ルールの形式:`{ toolName: "Bash", ruleBehavior: "deny", ruleContent: "npm publish:*" }`。複数ソースのルールは統合され、高優先度ソースが低優先度を上書きする(低→高:user < project < local < flag < policy、さらに cliArg、command、session)。
|
||||
|
||||
### 四、isDestructive() とは
|
||||
|
||||
CC では `isDestructive`(`Tool.ts:405-406`)は**純粋に UI 表示用** — ツール一覧に `[destructive]` ラベルを表示するだけ。権限決定には参加しない。デフォルトではすべてのツールが `false` を返す。ExitWorktree(remove 時)と MCP ツール(`annotations.destructiveHint` に依存)のみがオーバーライドする。
|
||||
|
||||
### 五、YoloClassifier(自動承認)
|
||||
|
||||
CC の auto モードでは、毎回ダイアログを表示するわけではない。`classifyYoloAction`(`utils/permissions/yoloClassifier.ts:1012`)はツール呼び出し + 会話コンテキストを分類器 LLM に送って安全性を判断する。まず acceptEdits モードのシミュレーションを試み(`permissions.ts:620-656`、acceptEdits が許可すれば → 自動承認)、次にセーフツールホワイトリストを確認し(`permissions.ts:658-686`)、最後に分類器を呼び出す。分類器が連続して拒否しすぎた場合 → 手動承認にフォールバック。
|
||||
|
||||
### 六、権限バブリング
|
||||
|
||||
サブ Agent(AgentTool 経由でフォークされたもの)の `permissionMode` は `'bubble'` に設定される(`forkSubagent.ts:50`)。これは権限ダイアログが**親 Agent のターミナルにバブルアップ**することを意味する。サブ Agent で黙って拒否されるのではない。Bash 分類器はこの過程で引き続き実行され — 権限ダイアログを表示しつつ、バックグラウンドで自動承認可能か判断する。
|
||||
|
||||
### 教育版の単純化は意図的
|
||||
|
||||
- 多段階パイプライン → 3 ゲート:理解のハードルが大幅に下がる
|
||||
- 8 ルールソース → 1 つのローカル DENY_LIST:概念量を制御可能
|
||||
- isDestructive → 省略(教育版には UI レイヤーがなく、CC でも権限決定には参加しない)
|
||||
- YoloClassifier → 省略(追加の LLM 呼び出しとテレメトリに依存)
|
||||
- 権限バブリング → 省略(s15 でマルチ Agent を扱う)
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21 → s22
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21
|
||||
> *"Check permissions before executing"* — The permission pipeline decides which operations need approval.
|
||||
>
|
||||
> **Harness Layer**: Permission — a gate before tool execution.
|
||||
@@ -39,7 +39,7 @@ None of the three gates match → execute directly. Most routine operations take
|
||||
|
||||

|
||||
|
||||
**Gate 1**: A hard deny list. Check first; if matched, return a block message. (Teaching demo: simple string matching is not a reliable security mechanism — command variants and shell expansion can bypass it. CC's approach is in the appendix.)
|
||||
**Gate 1**: A hard deny list. Check first; if matched, return a block message. This list uses simple string matching to show where the permission gate sits; it is not a complete security boundary.
|
||||
|
||||
```python
|
||||
DENY_LIST = [
|
||||
@@ -153,80 +153,5 @@ Permission checks are in place — but every check is hardcoded as `check_permis
|
||||
|
||||
→ s04 Hooks: Add hooks to the loop. Extension logic hangs on hooks; the loop stays clean.
|
||||
|
||||
<details>
|
||||
<summary>Dive into CC Source Code</summary>
|
||||
|
||||
> The following is based on a review of CC source code `types/permissions.ts`, `utils/permissions/permissions.ts`, `toolExecution.ts`, `utils/permissions/yoloClassifier.ts`, `tools/AgentTool/forkSubagent.ts`.
|
||||
|
||||
### 1. PermissionResult: Not 3, but 4
|
||||
|
||||
The teaching version's three gates (deny → ask → allow) don't fully correspond to CC. CC's `PermissionResult` has 4 behaviors (`types/permissions.ts:241-266`):
|
||||
|
||||
| behavior | Meaning | Teaching Version Equivalent |
|
||||
|----------|---------|---------------------------|
|
||||
| `allow` | Allow directly | Gate 3 passes |
|
||||
| `deny` | Deny directly | Gate 1 matches |
|
||||
| `ask` | Show dialog to user | Gate 2 matches |
|
||||
| `passthrough` | Tool doesn't express opinion, passes to generic pipeline | Not in teaching version |
|
||||
|
||||
### 2. Production Verification Stages
|
||||
|
||||
CC's tool calls don't go through three gates — they go through multiple stages distributed across `checkPermissionsAndCallTool()` (`toolExecution.ts:599-1745`), hooks, `hasPermissionsToUseToolInner()` (`utils/permissions/permissions.ts:1158-1310`), and classifier logic:
|
||||
|
||||
1. **Zod schema validation** (`toolExecution.ts:614-680`) — parameter type checking
|
||||
2. **validateInput()** (`toolExecution.ts:682-733`) — tool-level semantic validation
|
||||
3. **backfillObservableInput()** (`toolExecution.ts:784`) — backfill legacy fields
|
||||
4. **PreToolUse hooks** (`toolExecution.ts:800-862`) — hooks can return allow/deny/ask
|
||||
5. **resolveHookPermissionDecision()** (`toolExecution.ts:921-931`) — coordinate hook + pipeline decisions
|
||||
6. **hasPermissionsToUseToolInner()** (`permissions.ts:1158-1310`) — multi-layer rule check:
|
||||
- Entire tool disabled by deny rule → `deny`
|
||||
- Entire tool flagged by ask rule → `ask`
|
||||
- `tool.checkPermissions()` tool's own judgment
|
||||
- Tool itself returns deny → `deny`
|
||||
- `requiresUserInteraction()` → `ask`
|
||||
- Content-related ask rules → `ask` (not bypassable)
|
||||
- Security check violation → `ask` (not bypassable)
|
||||
- bypassPermissions mode → `allow`
|
||||
- Entire tool allowed by allow rule → `allow`
|
||||
- passthrough → converted to `ask`
|
||||
|
||||
### 3. Deny List: Not One File, but 8 Sources
|
||||
|
||||
CC doesn't have a single deny list. Permission rules come from 8 sources (`types/permissions.ts:54-62`):
|
||||
|
||||
| Source | Configuration Location |
|
||||
|--------|----------------------|
|
||||
| `userSettings` | `~/.claude/settings.json` |
|
||||
| `projectSettings` | `.claude/settings.json` |
|
||||
| `localSettings` | `settings.local.json` |
|
||||
| `flagSettings` | Feature flags |
|
||||
| `policySettings` | Enterprise management policy |
|
||||
| `cliArg` | `--allowedTools` / `--deniedTools` |
|
||||
| `command` | Inline command |
|
||||
| `session` | In-session temporary authorization |
|
||||
|
||||
Each rule format: `{ toolName: "Bash", ruleBehavior: "deny", ruleContent: "npm publish:*" }`. Rules from multiple sources are merged, with higher-priority sources overriding lower ones (low to high: user < project < local < flag < policy, plus cliArg, command, session).
|
||||
|
||||
### 4. What is isDestructive()
|
||||
|
||||
In CC, `isDestructive` (`Tool.ts:405-406`) is **purely for UI display** — showing a `[destructive]` label in the tool list. It doesn't participate in permission decisions. All tools return `false` by default. Only ExitWorktree (on remove) and MCP tools (depending on `annotations.destructiveHint`) override it.
|
||||
|
||||
### 5. YoloClassifier (Auto-Approval)
|
||||
|
||||
In CC's auto mode, it doesn't pop a dialog every time. `classifyYoloAction` (`utils/permissions/yoloClassifier.ts:1012`) sends the tool call + conversation context to a classifier LLM to judge safety. It first tries acceptEdits mode simulation (`permissions.ts:620-656`, if acceptEdits allows → auto-approve), then checks the safe tool whitelist (`permissions.ts:658-686`), and finally calls the classifier. If the classifier rejects too many times in a row → falls back to manual approval.
|
||||
|
||||
### 6. Permission Bubbling
|
||||
|
||||
A sub-Agent's (forked via AgentTool) `permissionMode` is set to `'bubble'` (`forkSubagent.ts:50`). This means permission dialogs **bubble up to the parent Agent's terminal**, rather than being silently denied in the sub-Agent. The Bash classifier continues running during this process — displaying the permission dialog while judging in the background whether auto-approval is possible.
|
||||
|
||||
### The Teaching Version's Simplification Is Intentional
|
||||
|
||||
- Multi-stage pipeline → 3 gates: dramatically lower barrier to understanding
|
||||
- 8 rule sources → 1 local DENY_LIST: manageable concept count
|
||||
- isDestructive → omitted (teaching version has no UI layer, and it doesn't participate in permission decisions in CC either)
|
||||
- YoloClassifier → omitted (depends on additional LLM calls and telemetry)
|
||||
- Permission bubbling → omitted (s15 covers multi-Agent)
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) · [中文](README.zh.md) · [日本語](README.ja.md)
|
||||
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21 → s22
|
||||
s01 → s02 → `s03` → [s04](../s04_hooks/) → s05 → ... → s20 → s21
|
||||
> *"工具执行前先做权限判断"* — 权限管线决定哪些操作需要审批。
|
||||
>
|
||||
> **Harness 层**: 权限 — 在工具执行前加一道门。
|
||||
@@ -39,7 +39,7 @@ s02 的循环完全保留。唯一的变动在工具执行前插入 `check_permi
|
||||
|
||||

|
||||
|
||||
**闸门 1**:一张硬拒绝表,先查,命中就返回阻止信息。(教学示意:简单字符串匹配不是可靠安全机制,命令变体和 shell 展开可能绕过。CC 的做法见附录。)
|
||||
**闸门 1**:一张硬拒绝表,先查,命中就返回阻止信息。这张表使用简单字符串匹配来说明权限闸门的位置,不能视为完整的安全边界。
|
||||
|
||||
```python
|
||||
DENY_LIST = [
|
||||
@@ -153,80 +153,5 @@ python s03_permission/code.py
|
||||
|
||||
s04 Hooks → 给循环加钩子,扩展逻辑挂在钩子上,循环保持干净。
|
||||
|
||||
<details>
|
||||
<summary>深入 CC 源码</summary>
|
||||
|
||||
> 以下基于 CC 源码 `types/permissions.ts`、`utils/permissions/permissions.ts`、`toolExecution.ts`、`utils/permissions/yoloClassifier.ts`、`tools/AgentTool/forkSubagent.ts` 的核查。
|
||||
|
||||
### 一、PermissionResult:不是 3 种,是 4 种
|
||||
|
||||
教学版的三道闸门(deny → ask → allow)和 CC 不完全对应。CC 的 `PermissionResult` 有 4 个 behavior(`types/permissions.ts:241-266`):
|
||||
|
||||
| behavior | 含义 | 教学版对应 |
|
||||
|----------|------|-----------|
|
||||
| `allow` | 直接允许 | 闸门 3 通过 |
|
||||
| `deny` | 直接拒绝 | 闸门 1 命中 |
|
||||
| `ask` | 弹出对话框问用户 | 闸门 2 命中 |
|
||||
| `passthrough` | 工具不表态,交给通用管线决定 | 教学版无 |
|
||||
|
||||
### 二、生产版的验证阶段
|
||||
|
||||
CC 的工具调用不是经过三道闸门,而是经过多个阶段,分布在 `checkPermissionsAndCallTool()`(`toolExecution.ts:599-1745`)、hooks、`hasPermissionsToUseToolInner()`(`utils/permissions/permissions.ts:1158-1310`)和 classifier 逻辑里:
|
||||
|
||||
1. **Zod schema 验证**(`toolExecution.ts:614-680`)— 参数类型检查
|
||||
2. **validateInput()**(`toolExecution.ts:682-733`)— 工具级语义验证
|
||||
3. **backfillObservableInput()**(`toolExecution.ts:784`)— 补全遗留字段
|
||||
4. **PreToolUse hooks**(`toolExecution.ts:800-862`)— 钩子可以返回 allow/deny/ask
|
||||
5. **resolveHookPermissionDecision()**(`toolExecution.ts:921-931`)— 协调钩子+管线决策
|
||||
6. **hasPermissionsToUseToolInner()**(`permissions.ts:1158-1310`)— 多层规则检查:
|
||||
- 整个工具被 deny rule 禁用 → `deny`
|
||||
- 整个工具被 ask rule 标记 → `ask`
|
||||
- `tool.checkPermissions()` 工具自己的判断
|
||||
- 工具自己返回 deny → `deny`
|
||||
- `requiresUserInteraction()` → `ask`
|
||||
- 内容相关的 ask 规则 → `ask`(不可绕过)
|
||||
- 安全检查违规 → `ask`(不可绕过)
|
||||
- bypassPermissions 模式 → `allow`
|
||||
- 整个工具被 allow rule 放行 → `allow`
|
||||
- passthrough → 转为 `ask`
|
||||
|
||||
### 三、拒绝列表:不是一个文件,是 8 个来源
|
||||
|
||||
CC 没有单一的 deny list。权限规则来自 8 个来源(`types/permissions.ts:54-62`):
|
||||
|
||||
| 来源 | 配置位置 |
|
||||
|------|---------|
|
||||
| `userSettings` | `~/.claude/settings.json` |
|
||||
| `projectSettings` | `.claude/settings.json` |
|
||||
| `localSettings` | `settings.local.json` |
|
||||
| `flagSettings` | Feature flags |
|
||||
| `policySettings` | 企业管理策略 |
|
||||
| `cliArg` | `--allowedTools` / `--deniedTools` |
|
||||
| `command` | 内联命令 |
|
||||
| `session` | 会话内临时授权 |
|
||||
|
||||
每条规则格式:`{ toolName: "Bash", ruleBehavior: "deny", ruleContent: "npm publish:*" }`。多个来源的规则合并,高优先级来源覆盖低优先级(从低到高:user < project < local < flag < policy,加上 cliArg、command、session)。
|
||||
|
||||
### 四、isDestructive() 是什么
|
||||
|
||||
CC 中 `isDestructive`(`Tool.ts:405-406`)**纯粹是 UI 展示用的**——在工具列表里显示 `[destructive]` 标签。它不参与权限决策。默认所有工具都返回 `false`。只有 ExitWorktree(remove 时)和 MCP 工具(依赖 `annotations.destructiveHint`)覆写了它。
|
||||
|
||||
### 五、YoloClassifier(自动审批)
|
||||
|
||||
CC 的 auto 模式下,不会每次都弹对话框。`classifyYoloAction`(`utils/permissions/yoloClassifier.ts:1012`)把工具调用 + 对话上下文发给一个分类器 LLM 判断是否安全。先尝试 acceptEdits 模式模拟(`permissions.ts:620-656`,如果 acceptEdits 允许 → 直接批准),再查安全工具白名单(`permissions.ts:658-686`),最后才调分类器。分类器连续拒绝太多次 → 回退到人工审批。
|
||||
|
||||
### 六、权限冒泡
|
||||
|
||||
子 Agent(通过 AgentTool fork 出来的)的 `permissionMode` 设为 `'bubble'`(`forkSubagent.ts:50`)。意思是权限弹窗**冒泡到父 Agent 的终端**,而不是在子 Agent 里静默拒绝。Bash 分类器在这个过程中继续跑——给权限对话框显示的同时在后台判断是否可以自动批准。
|
||||
|
||||
### 教学版的简化是刻意的
|
||||
|
||||
- 多阶段管线 → 3 道闸门:理解门槛大幅降低
|
||||
- 8 个规则来源 → 1 个本地 DENY_LIST:概念量可控
|
||||
- isDestructive → 忽略(教学版没有 UI 层,CC 里它也不参与权限决策)
|
||||
- YoloClassifier → 省略(依赖于额外的 LLM 调用和遥测系统)
|
||||
- 权限冒泡 → 省略(s15 才涉及多 Agent)
|
||||
|
||||
</details>
|
||||
|
||||
<!-- translation-sync: zh@v1, en@v1, ja@v1 -->
|
||||
|
||||
Reference in New Issue
Block a user