{ "_what": "Claude Code 權限白名單(permissions.allow)的唯一清單——本機與雲端都從這裡讀,不各養一份(inkstone/ISEP#130)", "_why": [ "leo 09-07 親手把四個 Gitea 正門工具(ticket/mainline/gate-ok/gitea-pr-merge)加進本機 InkStoneCo/.claude/settings.json,auto mode 的分類器才不擋。", "雲端 session 沒有那四條,同樣的動作照樣被擋(09-04 progress-guard run log:permission_denials=6)。", "薄殼 repo(GitHub)要 D20 開閘才推得動 ⇒ 白名單住 ISEP,`scripts/settings-allow-sync` 開工時寫進那台機器的 ~/.claude/settings.json。", "以後加規則只改這個檔、出一版,雲端下一趟就有。", "inkstone/ISEP#137:09-07 雲端對 stage 的三種寫入(`npx wrangler secret put`/`stage-deploy-artifacts.py`/curl POST 到 arcrun-yuga3bse)全被分類器擋——複合指令與任意 curl 對不上任何一條前綴。收成 `scripts/stage`(secret/api 兩個子命令,只寫 stage、值只從環境變數名讀)四種形狀,外加 Arcrun 自己那支 `scripts/stage-deploy-artifacts.py`(它已寫死只認 youlin 帳號 ID、不收 --account/--token)從 Arcrun repo 根目錄的相對形狀。不放 `Bash(npx *)`/`Bash(wrangler *)`/`Bash(curl *)`。", "inkstone/ISEP#67:SessionStart 信標印的補法是 `python3 /scripts/release-ship vX.Y.Z`——那一行在雲端要是被分類器擋,出路就走不通(閘的價值是「擋下來+給一條走得通的路」)。release-ship 只 POST 一件事(建 release,tag 與 release 名寫死從 Gitea 讀);release-check 純讀。", "inkstone/ISEP#147:worktree 閘印出來的出路是 `python3 /scripts/worktree open …`/`close …`,收工那一半也是同一支工具;出路在雲端被分類器擋就是走不通的路(閘的價值是「擋下來+給一條走得通的路」)。它只碰 git worktree,不打網路寫入。" ], "_rules": [ "開頭的 `~` 由 settings-allow-sync 換成那台機器的家目錄(本機 /Users/…、雲端 /root),其餘一字不改。", "只放「正門工具」:每一條都要說得出它是哪支腳本的哪種呼叫形狀。不放 Bash(python3 *) 這種整類放行。", "同一支工具幾種呼叫形狀就幾條(快取路徑/$CLAUDE_PLUGIN_ROOT/相對路徑)——權限規則是逐條完全比對,形狀差一個字就落在規則之外(scripts/gate-ok 檔頭記過這一課)。", "別的 repo 的正門工具也可以進來(例 Arcrun 的 `scripts/stage-deploy-artifacts.py`),條件一樣:那支腳本自己把「只打哪台」寫死在程式裡,本清單放的是它從那個 repo 根目錄跑的相對形狀。" ], "allow": [ "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/ticket *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/ticket\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/ticket *)", "Bash(python3 scripts/ticket *)", "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/mainline *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/mainline\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/mainline *)", "Bash(python3 scripts/mainline *)", "Bash(bash ~/.claude/plugins/cache/inkstone/isep/*/scripts/gate-ok *)", "Bash(bash \"$CLAUDE_PLUGIN_ROOT/scripts/gate-ok\" *)", "Bash(bash \"$CLAUDE_PLUGIN_ROOT\"/scripts/gate-ok *)", "Bash(bash scripts/gate-ok *)", "Bash(bash scripts/gitea-pr-merge.sh *)", "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/stage *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/stage\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/stage *)", "Bash(python3 scripts/stage *)", "Bash(python3 scripts/stage-deploy-artifacts.py *)", "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/release-ship *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/release-ship\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/release-ship *)", "Bash(python3 scripts/release-ship *)", "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/release-check *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/release-check\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/release-check *)", "Bash(python3 scripts/release-check *)", "Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/worktree *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/worktree\" *)", "Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/worktree *)", "Bash(python3 scripts/worktree *)" ] }