# 權限與確認

兩種權限模式、各入口使用哪一種，以及確認提示如何路由。

## Permission mode

| Mode | 行為 |
|---|---|
| `safe` | 每個非 ReadOnly 工具呼叫都需使用者確認 |
| `auto` | 所有工具不經確認直接執行，例外是工作目錄外的寫入與不可逆指令（見下）；只在工作目錄符合條件時生效，否則套用 `safe` 規則 |

工作目錄符合 `auto` 的條件：位於 `$HOME` 底下的子目錄、不是 `$HOME` 本身，且不是禁止或敏感路徑（`filesystem.WorkDirAllowsAll`）。此閘門由 harness 在 `internal/agents/exec/toolCall.go` 強制，而非靠 prompt。`auto` 下仍會詢問的情況：

1. 工作目錄外 —— `edit_file`、`remove_file` 或 `restore_file` 的路徑、`run_command` / `background_command` argv 中的絕對路徑／`~`／`..` token、`write_paths` 條目，或 `rm` 的操作對象，落在 `$HOME` 內但在工作目錄外時詢問一次；核准後該路徑在本 session 內都放行
2. 不可逆指令（`internal/agents/exec/irreversible.go`）—— 即使命中 allow 規則仍詢問；只有「Yes, allow this turn」能讓本輪其餘呼叫略過。涵蓋：會丟失 Git 歷史的操作（`reset --hard`、`clean`、force push、刪除遠端分支）；下載後 pipe 進直譯器，或同時連網又讀取 secret 的腳本；上傳敏感檔案；基礎設施 apply／delete（`terraform`、`tofu`、`pulumi`、`cdk`、`kubectl`、`helm`）；雲端 CLI 的 delete／deploy／IAM 變更（`gcloud`、`az`、`doctl`、`aws`、`gsutil`）；部署 CLI（`firebase`、`vercel`、`netlify`、`wrangler`、`fly`、`serverless`）；資料庫 migration；破壞性 SQL（`DROP`／`TRUNCATE`、無 `WHERE` 的 `DELETE`／`UPDATE`）；`gh pr merge`、`gh repo delete` 等，以及會變更狀態的 `gh api` 呼叫

路徑分級在所有模式下都適用：`$HOME` 內的敏感路徑只需一般確認（不需密碼）；`$HOME` 外的路徑、以 `sudo` 開頭的 argv 與 `sandbox: false` 需要系統密碼。密碼提示不提供「Yes, don't ask again」與「Yes, allow this turn」，一般確認則保留。v1.3.7 之前 `auto` 下碰到 `$HOME` 外的路徑會直接拒絕、不跳提示；現在改為要求輸入密碼。v1.3.10 起 `read_files` 與 `find_files` 讀取可讀清單中的 `$HOME` 外路徑（`/usr`、`/etc`、`/opt` 等系統與套件位置，加上 `config.json` 的 `readable_path`）不跳確認。

argv 中的 `rm` 會把目標移到垃圾桶：在工作目錄內於 `auto` 下直接執行，`$HOME` 內其他位置會詢問，`$HOME` 外需要密碼；`sh -c` 內的 `rm` 一律拒絕。`run_command` / `background_command` 帶 `network: true` 時，`safe` 下需確認，`auto` 下直接執行。

## 各入口的模式

生效的權限模式（`safe` 或 `auto`）由進入點決定：

| 進入點 | 模式 |
|---|---|
| TUI | 啟動時的工作目錄符合條件即為 `auto`，否則為 `safe`；可用 `Shift+Tab` 逐 session 切換 |
| `POST /v1/send` | web 儀表板有開啟中的確認 listener 且請求未帶 `enable_edit`、`enable_sandbox` 時為 `safe`，確認由儀表板回應；其餘情況（v1.3.9）為 API auto mode：不跳確認，未設 `enable_edit:true` 時唯讀，未設 `enable_sandbox:false` 時留在沙箱，見 [REST API](rest-api)。`agen -p` 一律使用 API auto mode。請求欄位 `allow_all` 已移除 |
| `POST /v1/chat/completions` | `auto`；工作目錄預設為 `$HOME`，不符合條件，因此除非請求指定符合條件的工作目錄，否則套用 `safe` 規則 |
| Telegram | `safe`（confirm gate 使用 Telegram inline-keyboard 選單） |
| Discord | `safe`（confirm gate 使用 Discord select menu） |
| 續跑的待處理任務 | 沿用該任務儲存的模式 |
| Subagent | 繼承母 agent 的模式；`auto` 下不受工作目錄限制 |

權限模式不會渲染進 turn context 或 system prompt：`## Permission Mode` 段落與 `configs/prompts/system_prompt/inject/permission/*.md` 移除於 v1.3.7，上述閘門完全由 harness 執行。位於唯讀指令清單的指令在任何模式下都跳過 gate。

## 自動核准規則

以下規則決定 `safe` 下（以及工作目錄不符合條件時的 `auto` 下）哪些呼叫需要確認。帶 `mode` 的工具由 mode 決定閘門：`list` / `read` / `search` 視為唯讀並跳過確認，而 `mode=remove`（`edit_skill` / `edit_tool`）即使在已自動核准的工具上仍一律確認。`remove_file` 與 `restore_file` 亦同：v1.3.11 起由這兩個工具取代 `edit_file` 的 `remove` / `restore` mode（移除於 v1.3.11），allow 規則不會略過它們。

此外，工具註冊為 `AlwaysAllow`、`http_request` 使用 `GET`，或 `run_command` / `background_command` 的 argv 命中唯讀清單時跳過確認（argv 中有 token 碰到敏感路徑即不算命中）；`open_file` 開 URL 與 `read_files` 讀敏感檔案一律確認，帶 `sandbox: false` 的指令呼叫（v1.3.0）或以 `sudo` 開頭的 argv（v1.3.2）也一樣，即使在 `auto`、allow-all Skill 或命中 allow 規則時仍要求系統密碼。其餘呼叫對照 allow list（`internal/agents/exec/allow`）：

| 項目 | 說明 |
|---|---|
| 檔案 | `~/.config/agenvoy/allow_tool`（全域）與 `<workDir>/.agenvoy/allow_list`（專案），一行一條，`#` 開頭為註解；兩者都載入並取聯集 |
| 條目 | `name` 核准該工具的所有呼叫；`name(argGlob)` 只核准主體相符的呼叫。主體在 `run_command` 與 `background_command`（`run_command_background` 已更名，移除於 v1.3.2）是以空白串接的 argv，`edit_file` 是絕對路徑的 `path`，`http_request` 是 `METHOD URL`（method 預設 `GET`），其他工具取 `path`（依工作目錄轉成絕對路徑）、`url` 或 `target` 參數，都沒有則為原始 JSON 參數。自 v1.3.0 起相對路徑會先解析再比對，空的 `argv`、`edit_file` 路徑或 `http_request` URL 一律不命中規則，也無法被記住 |
| Glob | 同時用於名稱與 `argGlob`，須比對整個字串：`*` 只在單一 `/` 區段內匹配、`**` 可跨越 `/`（v1.3.0 起 `**/` 也可匹配零層目錄，`src/**/*.go` 涵蓋 `src/main.go`）、`?` 匹配一個非 `/` 字元，`\*`、`\?`、`\\` 為字面字元 |
| 記住 | 在確認時選擇記住，會把 `name(<主體>)` 寫進專案的 `allow_list`，主體中的 `*`、`?`、`\` 會被跳脫，因此只匹配完全相同的呼叫 |
| MCP | `/mcp` → server → tools，或 `POST /v1/allowlist` 帶 `{tool: {prefix, entries}}`，會把全域清單中 `mcp__<server>__` 開頭的條目整組換成給定集合；每個條目都必須以該前綴開頭，含 `prefix*` 時整組收斂為整個 server 的授權 |
| Skill | `~/.config/agenvoy/allow_skill` 與 `<workDir>/.agenvoy/allow_skill` 列出 Skill 名稱；作用中 Skill 在清單內的執行以 allow-all 進行 |

## 依來源路由的確認

每個互動請求都帶有來源前綴——`cli-`、`chat-`、`tg-` 或 `dc-`。CLI 的確認只由 TUI 消費——自 v1.2.0 起經 daemon socket 只送到發起該次執行的 TUI 視窗，而非所有開著的 TUI——web 請求由 web 確認串流消費，Telegram 或 Discord 請求由對應的通道 listener 消費。TUI 以外通道的確認 5 分鐘未回覆即視為 skipped，任務保留為待決（v1.1.1 起 TUI 的確認不設時限），因此一個通道既無法攔截、也無法無限期占住另一個通道的提示。
