Skip to content

fix(coolify,hetzner): 修正 Claude Code 桌面版 MCP env 傳遞失效 - #116

Merged
terry90918 merged 7 commits into
mainfrom
develop
Jul 8, 2026
Merged

fix(coolify,hetzner): 修正 Claude Code 桌面版 MCP env 傳遞失效#116
terry90918 merged 7 commits into
mainfrom
develop

Conversation

@terry90918

@terry90918 terry90918 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

問題

在 Claude Code 桌面版中,/coolify 完全沒有工具、/hetzner 的工具一律回 401。從終端機啟動 claude 則一切正常。

根因

桌面 App 從 launchd 啟動,整條行程鏈不經過任何 shell:

launchd → Claude.app → disclaimer → claude → MCP server

官方文件(Environment configuration → Local sessions)明載:

macOS reads shell profiles for PATH and fixed Claude Code variables

也就是自訂變數(COOLIFY_ACCESS_TOKEN 等)設計上就不繼承~/.zshenv 從未被讀取。

再者,MCP SDK 的 DEFAULT_INHERITED_ENV_VARS 只有 HOME / LOGNAME / PATH / SHELL / TERM / USER——即使 token 在 claude 行程的 env 裡,子行程一樣拿不到。.mcp.jsonenv 區塊是唯一通道,而其 ${VAR} 需由桌面 App 從自己的 env 展開,那裡沒有這些變數。

結果 ${COOLIFY_ACCESS_TOKEN} / ${HETZNER_API_TOKEN} 展開成空字串,兩支 server 以不同方式失敗:

失敗時機 症狀
coolify-mcp 啟動即 fatal exit(COOLIFY_URL must be a valid URL 完全沒有工具
hetzner-mcp 照常啟動,延到呼叫時 每次呼叫 401

修法

"command": "/bin/zsh",
"args": ["-lc", "exec env -i <白名單> npx -y @jurislm/coolify-mcp@latest"]
  • login shell 負責解析 ~/.zshenv,不依賴 Claude Code 的展開器與 env 傳遞
  • 外層再以 env -i 只把該 plugin 需要的變數交給 MCP server

為什麼 -lc 而非 -c-c 只讀 .zshenv(拿得到 token 但 PATH 沒有 npx);-lc 為 login shell,會讀 .zshenv + .zprofile,兩者兼得。已驗證 login shell 在 exec 前不會輸出任何 stdout,不會污染 stdio JSON-RPC。

Code review 追加修正(1af9e57)

單純用 login shell 會讓 npx -y ...@latest(runtime 才從 npm 抓下來的套件)繼承整個 login shell 環境。node 探針實測,coolify server 可讀到 NPM_TOKENGITHUB_PERSONAL_ACCESS_TOKENHETZNER_API_TOKENJURISLM_DRONE_RELEASE_PLEASE_TOKEN——遠比原本 env 區塊的兩個變數寬鬆。

加上 env -i 白名單後,實測這些 token 皆已隔離。

README 補上三項先前沒寫的前提:變數必須放 ~/.zshenv 而非 ~/.zshrc、需要 macOS + /bin/zshenv -i 的隔離範圍。

為什麼不含 langfuse

langfuse-mcp 的 published bin 使用 #!/usr/bin/env bun shebang,而 .bun/bin 僅存在於 .zshrc-lc 不讀),套用後反而會讓原本可用的 CLI 情境失效。已在 jurislm/langfuse-mcp#22 修正為 node runtime,待其發版後再比照套用。

驗證

先在本機 plugin cache 套用、重啟 Claude Code 桌面版實測(非模擬):

另以 env -i(僅 MCP SDK 會傳的 6 個變數,等同桌面 App 實況)spawn 本檔設定,兩支 server 均完成 handshake 並成功呼叫工具。

附帶發現:MCP server 清單在 session 啟動時就固定,執行中掛載的 server(實測以 claude mcp add 註冊、claude mcp list 顯示 Connected)ToolSearch 完全看不到。因此此類修正必須完全重啟 App 才能驗證。

Test plan

  • env -i 模擬桌面 App 環境 spawn 兩支 server,handshake + 工具呼叫成功
  • node 探針確認無關 token 已隔離
  • 本機 plugin cache 套用 + 完全重啟桌面 App,實測 /coolify 恢復
  • merge 後 release-please 產生 release PR

Summary by CodeRabbit

  • 文件更新

    • 補充 Coolify 與 Hetzner 外掛的環境變數設定說明,明確建議將必要變數放在 ~/.zshenv
    • 說明啟動方式與 macOS / zsh 的使用要求,並提醒避免多餘環境變數外洩。
  • Chores

    • 調整兩個外掛的啟動設定,改用更精簡的環境執行方式。
    • 新增自動審查規則,並略過特定發版標題的 PR。

* feat(codebase-sync): 強化深度審計 — 強制 Audit Report + 完整自動化偵測

- Step 0 新增 8 項強制自動化偵測(目錄/檔案存在性、scripts 差異、版本號現況)
- 引入強制 Audit Report 格式,每次執行都必須輸出,不得以「看起來沒問題」為由跳過
- 所有文件修改必須有對應 Audit Report finding,禁止無依據地動筆
- command 明確禁止跳步驟,強調「先審計後動筆」順序
- 新增未記載新功能偵測(實際存在但文件未提及的目錄/plugin)

* feat(codebase-sync): 加入 git 近期變動分析(0-J ~ 0-N)

- 新增 0-J:近期 30 筆 git commit 摘要
- 新增 0-K:近期 commit 涉及的檔案變動統計
- 新增 0-L:近期新增的檔案(可能尚未記載於文件)
- 新增 0-M:近期刪除的檔案(文件可能仍有引用)
- 新增 0-N:近期 feat/fix/refactor commits 過濾(最可能影響文件)
- Audit Report 加入 Section 8 git 近期變動分析
- 修正常見錯誤措辭:區分「用 git 找訊號」vs「把 commit message 複製進文件」

* fix(codebase-sync): 修正 code review 發現的 5 個問題

- fix(0-K): grep pattern 從 '^(A|D|R|M)\s' 改為 '^[ADMR][0-9]*\t',正確捕捉 git rename(R100 格式)
- fix(0-L/0-M): awk '{print $2}' 改為 cut -f2-,避免含空格的檔案路徑被截斷
- fix(Step 5-A): 移除不可執行的 'ls <每個新加的目錄路徑>' 佔位符,改為可操作的 find 說明
- fix(5-C): cat file | jq . 改為 jq . file(避免多餘 cat,更安全)
- fix(補充區塊): 移除與 Step 0-D 重複的 scripts 比對(regex 也不一致),只保留 .env.example env var 比對(唯一不在 Step 0 的檢查)
- feat(Audit Report): 新增 Section 9 記錄環境變數比對結果(補充區塊原本有比對但無處寫入)

* fix(codebase-sync): 0-G 補上 README.md 的檔案引用存在性檢查

原本 0-G 只檢查 README 中的目錄引用(/結尾),
不檢查 .ts/.json/.md 等檔案路徑,已刪除的檔案引用無法被偵測。
新增對應的檔案檢查區塊,與 0-F(CLAUDE.md)的邏輯對齊。

* fix(codebase-sync): 修正 grep pattern 跨平台相容性與點前綴路徑漏抓

- fix(0-K): \t 在 ERE 為實作相依,改用 POSIX [[:blank:]] 確保 macOS/GNU grep 皆正確匹配 tab
- fix(0-G): 目錄與檔案 regex 從 [a-z] 開頭改為 \.?[a-z0-9_],覆蓋 .github/、.env、.env.example 等點前綴路徑
裸 filename(如 marketplace.json)在 CLAUDE.md 散文中出現時,
[ -f marketplace.json ] 會報 MISSING,但實際檔案在 .claude-plugin/marketplace.json。
修法:regex 強制要求至少含一個 /(<dir>/<file>.<ext> 格式),
純 filename 不含路徑的不會被提取,避免 Audit Report 產生誤導性 MISSING 條目。
同樣修正 0-G 的 README.md 檔案檢查,並補上 0-F 缺少的 \.? 點前綴支援。
… 傳遞失效

Claude Code Desktop app 從 launchd 啟動(launchd → Claude.app → disclaimer →
claude → MCP server),整條行程鏈不經過任何 shell,因此 ~/.zshenv 從未被讀取。
再加上三個已知的 Desktop-only upstream bug:

- anthropics/claude-code#40372:Desktop app 不展開 .mcp.json env 的 ${VAR}
- anthropics/claude-code#42203 / #43210:Desktop app 忽略 settings.json 的 env 區塊
- #42203 留言:launchctl setenv 對子行程無效(會被覆寫)

結果是 ${COOLIFY_ACCESS_TOKEN} / ${HETZNER_API_TOKEN} 拿不到值,所有工具呼叫
一律 401。從終端機啟動 claude 則正常(父行程是 zsh,env 已繼承)。

改以 `/bin/zsh -lc "exec npx ..."` 啟動:env 解析發生在**子行程內部**,
不依賴 Claude Code 的展開器與 env 傳遞,因此不受上述三個 bug 影響。
同時移除 env 區塊,避免憑證來源一分為二。

why -lc 而非 -c:-c 只讀 .zshenv(拿得到 token 但 PATH 沒有 npx);
-lc 為 login shell,會讀 .zshenv + .zprofile,兩者兼得。已驗證 login shell
在 exec 前不會輸出任何 stdout,不會污染 stdio JSON-RPC。

why 不含 langfuse:langfuse-mcp 的 published bin 使用 `#!/usr/bin/env bun`
shebang,而 .bun/bin 僅存在於 .zshrc(互動式,-lc 不讀),套用後反而會讓原本
可用的 CLI 情境失效。該套件應改為 node shebang,另案處理。

驗證:以 env -i(僅 HOME + 最小 PATH,模擬 Desktop sandbox)spawn 本檔設定,
coolify 與 hetzner 皆成功完成 MCP initialize handshake 並回傳 serverInfo。
fde9a60。code review 指出該 commit 引入安全迴歸:

原本 .mcp.json 的 env 區塊只把 2 個變數交給 MCP server(最小權限)。改成
`/bin/zsh -lc "exec npx ..."` 之後,子行程繼承整個 login shell 環境。以 node
探針實測,`npx -y @jurislm/coolify-mcp@latest`(runtime 才從 npm 抓下來的套件)
可以讀到 NPM_TOKEN、GITHUB_PERSONAL_ACCESS_TOKEN、HETZNER_API_TOKEN、
JURISLM_DRONE_RELEASE_PLEASE_TOKEN——遠比修正前寬鬆。

改為 `exec env -i <白名單> npx ...`:login shell 仍負責解析 ~/.zshenv,但外層
以 env -i 清空環境,只把該 plugin 實際需要的變數傳進去。保留 MCP SDK 本來就會
繼承的 HOME/LOGNAME/PATH/SHELL/TERM/USER(npx 需要 PATH 與 HOME)。

README 補上三件先前沒寫的前提:
- 變數必須放 ~/.zshenv,不能放 ~/.zshrc(-lc 為 login shell,不讀 .zshrc)
- 需要 macOS + /bin/zsh
- env -i 的隔離範圍

驗證(env -i 模擬 Desktop app 實況,僅 MCP SDK 會傳的 6 個變數):
- coolify list_applications → 正常回傳應用清單
- hetzner_list_ssh_keys → 正常回傳金鑰
- node 探針:NPM_TOKEN / GITHUB_PERSONAL_ACCESS_TOKEN / HETZNER_API_TOKEN
  對 coolify server 皆已隔離,僅 COOLIFY_ACCESS_TOKEN / COOLIFY_BASE_URL 可見
Copilot AI review requested due to automatic review settings July 8, 2026 09:36
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 929ab037-5392-4fc2-a5ad-a4198273df36

📥 Commits

Reviewing files that changed from the base of the PR and between 1af9e57 and 2c0bcc5.

📒 Files selected for processing (4)
  • plugins/coolify/.mcp.json
  • plugins/coolify/README.md
  • plugins/hetzner/.mcp.json
  • plugins/hetzner/README.md
📝 Walkthrough

Walkthrough

本次變更新增 .coderabbit.yaml 設定審查語言與 auto_review 規則,並修改 coolify、hetzner 兩個插件的 .mcp.json 啟動方式,改用 /bin/zsh -lc 搭配 env -i 建立最小化環境變數,同時更新對應 README 說明環境變數需放置於 ~/.zshenv

Changes

審查自動化設定

Layer / File(s) Summary
CodeRabbit 審查設定檔
.coderabbit.yaml
新增審查與回覆語言(繁體中文台灣正體)、auto_review 限定基底分支為 main,並用標題關鍵字跳過 release PR。

MCP 環境變數隔離

Layer / File(s) Summary
Coolify MCP 啟動與環境變數說明
plugins/coolify/.mcp.json, plugins/coolify/README.md
.mcp.json 改用 /bin/zsh -lc 執行 exec env -i ... 顯式注入指定環境變數後再啟動 npx;README 新增需將 COOLIFY_ACCESS_TOKENCOOLIFY_BASE_URL 放於 ~/.zshenv 而非 ~/.zshrc 的說明。
Hetzner MCP 啟動與環境變數說明
plugins/hetzner/.mcp.json, plugins/hetzner/README.md
.mcp.json 改用 /bin/zsh -lc 執行 exec env -i ...,將 HETZNER_API_TOKEN 移入指令字串;README 新增需將該變數放於 ~/.zshenv 而非 ~/.zshrc 的說明。

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: bug

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 標題清楚點出修正 Claude Code 桌面版的 MCP 環境變數傳遞問題,且與 coolify、hetzner 兩個變更範圍一致。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

此 PR 針對 Claude Code **桌面版(macOS / launchd 啟動鏈)**無法繼承自訂環境變數,導致 Coolify / Hetzner MCP server 取不到 token(Coolify 啟動即退出、Hetzner 呼叫時 401)的問題,改以 zsh -lc 主動載入 ~/.zshenv,並用 env -i 白名單隔離環境,避免多餘敏感變數外洩到 MCP 子行程。

Changes:

  • plugins/coolifyplugins/hetzner.mcp.json 改為透過 /bin/zsh -lc 啟動,並在內層用 exec env -i <白名單> 執行 npx -y @jurislm/*-mcp@latest
  • 在 Coolify / Hetzner README 補充桌面版環境變數傳遞限制、~/.zshenv 放置要求與 env -i 隔離說明
  • 新增 .coderabbit.yaml 設定審查語言與忽略 release-please 產生的 release PR

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
plugins/hetzner/README.md 補充桌面版 env 繼承限制與 zsh -lc/env -i 的使用前提說明
plugins/hetzner/.mcp.json 改用 zsh -lc 啟動並以 env -i 白名單方式傳遞必要變數
plugins/coolify/README.md 補充桌面版 env 繼承限制與 zsh -lc/env -i 的使用前提說明
plugins/coolify/.mcp.json 改用 zsh -lc 啟動並以 env -i 白名單方式傳遞必要變數
.coderabbit.yaml 設定 CodeRabbit 使用繁體中文語氣並忽略 release-please release PR

Comment thread plugins/coolify/README.md Outdated
Comment thread plugins/hetzner/README.md Outdated
Comment thread plugins/coolify/.mcp.json Outdated
Comment thread plugins/hetzner/.mcp.json Outdated
1. `command` 由 `/bin/zsh` 改為 `zsh`(依 PATH 解析)
   硬編絕對路徑把 plugin 綁死在 macOS——多數 Linux 發行版的 zsh 在
   /usr/bin/zsh。實測桌面 App 的最小 PATH(/usr/bin:/bin:/usr/sbin:/sbin)
   下 `zsh` 仍解析得到 /bin/zsh,改用 PATH 查找零成本且可攜。
   已重新以該最小環境驗證兩支 server 皆正常。

2. README 修正 login shell 讀取的檔案清單
   原文寫「只讀 ~/.zshenv + ~/.zprofile」不精確。實測(各檔植入 stderr 標記):
     zsh -lc  → .zshenv, .zprofile, .zlogin
     zsh -c   → .zshenv
   兩者皆不讀 .zshrc。README 補上 .zlogin。

3. README 補上 stdout 污染警告
   MCP 走 stdio JSON-RPC,上述任一啟動檔只要有 echo/printf,輸出就會排在第一個
   JSON 訊息前面導致 handshake 失敗。實測:.zprofile 放一行 `echo GARBAGE`,
   stdout 首行即為 GARBAGE。已在 README 指示改用 `print -u2`。

驗證:以 env -i(僅 MCP SDK 傳遞的 6 個變數 + 最小 PATH)spawn 新設定,
coolify list_applications 與 hetzner_list_ssh_keys 皆正常,且 stdout 首行
為合法 JSON(無前置污染)。
@terry90918
terry90918 merged commit 5dcad73 into main Jul 8, 2026
1 check passed
terry90918 added a commit that referenced this pull request Aug 22, 2026
兩個 finding 都取證確認後修正。

1. fine-grained PAT 漏了 Administration: Read(Codex 於 jurislm-tools #251 指出)

   scripts/release-pr-auto-merge.mjs 會呼叫
   GET /repos/{owner}/{repo}/branches/{branch}/protection 驗證分支保護設定。
   GitHub 官方 fine-grained PAT 權限表明列該端點需要 Administration: Read。
   照原本的清單(只有 Contents/Pull requests/Issues)鑄出來的 token,每個符合
   資格的 release PR 都會在合併前 403 失敗。

   這一項只適用有 release-pr-auto-merge pipeline 的 repo(lexvision、rimivo、
   jurislm-tools、entire),因此以條件句寫入,不是無條件要求。

2. 「唯一可靠的症狀是版號不再前進」講太絕對(CodeRabbit 於 memory-dessert #116 指出)

   我原本的意思是「不要靠 stage 的綠紅去推斷缺哪個權限」,但寫成了「其他症狀都
   不可靠」,那是錯的:pipeline log 裡 release-please 的實際輸出與 GitHub API
   回應都會顯示權限問題,403 回應甚至會帶 X-Accepted-GitHub-Permissions header
   直接指出缺哪一項。改為指向這些真正的診斷來源,並提醒一併確認 Drone Web UI 上
   secret 是否確實已設定。

五個 repo 的註解仍逐字相同(sha256 指紋 5e2f76a4ce3d),repo-standards 的 secret 表
與 SKILL.md 同步更新——那是權威來源,漏掉的話日後新建的 repo 會再踩一次同一個坑。
terry90918 added a commit that referenced this pull request Aug 22, 2026
…共用範圍的描述

* refactor(ci): 將 RELEASE_PLEASE_TOKEN 統一為 GITHUB_API_TOKEN,並讓 repo-standards 反映其共用性質

JurisLM 各 repo 統一為單一 GitHub token 與單一名稱(見 jurislm/entire JUR-126、JUR-128)。

本 repo 是這批裡最要緊的一個:repo-standards plugin 定義了新 repo 的 CI 樣板與
建置 checklist。不改它,日後每個新建的 repo 都會沿用舊名字,等於改到一半又長回來。

## 改名範圍

.drone.yml、CLAUDE.md、scripts/{drone-ci-policy.test,validate-drone-config,
release-eligibility,release-eligibility.test,release-pr-auto-merge}.mjs、
openspec/specs/docs-and-standards/repo-standards-detail.md,以及 repo-standards
plugin 的 SKILL.md 與兩份 reference。openspec/changes/archive/ 是歷史記錄,不動。

## 不只改名:把描述改對

改了名字沒跟著改語意,正是第一批被外部審查抓到 3 個 Major 的根因。這次一併處理:

- validate-drone-config.mjs 與 drone-ci-policy.test.mjs 的錯誤訊息由「the release
  token」「Drone release-token secret indirection」改為指名這是共用的 GitHub API
  token。這顆 token 早就不只服務 release-please。
- openspec/specs/ci-platform/spec.md 兩處同樣的敘述一併更新。

## repo-standards 的三處實質補強

1. secret 表:原文只寫「release-please 寫 GitHub release PR / tag」。實際上
   release-pr-auto-merge 與 deploy(讀 live main commit)也用它。表格改為列出全部
   三種用途,並明寫它是跨各 repo 共用的同一份憑證,輪替時必須同步更新每一個 repo
   的同名 secret——漏掉的 repo 是在那一邊靜默失敗,從操作當下的 repo 完全看不到。

   同時補上 fine-grained PAT 需要 Issues: Read and write。release-please 以
   autorelease: pending/tagged label 追蹤狀態,label 端點在 fine-grained 權限下
   歸 Issues 而非 Pull requests。這條最常被漏掉,而漏掉的症狀是版號靜默不動。
   取證:GitHub 官方 fine-grained PAT 權限表;且 memory-dessert #114、lawyer #237、
   wedding #28、lexvision #224 這些已合併的 release PR 全都帶 autorelease: tagged。

2. new-repo-checklist 第 28 項:明寫新 repo 要用「現有的那一份共用憑證」,不要另鑄
   一把。另鑄會讓日後輪替漏掉這個 repo。

3. SKILL.md 的規則行補上共用性質與 Issues 權限。

## 驗證

npm run validate:drone(validate + release + release-pr-auto-merge 三個 pipeline)、
npm run validate(160 tests 全過、plugin repository validation、version sync 1.41.1、
markdownlint)全數通過。

Drone secret GITHUB_API_TOKEN 已先建立;RELEASE_PLEASE_TOKEN 保留到本 PR 合併
且發版流程實測通過之後才刪除。

* docs(ci): 用實查結果校正 GITHUB_API_TOKEN 的 scope 敘述

我先前照抄 repo-standards 寫的「classic PAT scopes repo + workflow」,實查之後發現
三個數字互不相同:

- **repo-standards 原本寫的**:repo + workflow
- **實際需要的**:只有 repo。它已涵蓋建 PR、建 tag/release、貼 label、合併 PR。
  workflow 只有在該 repo 有 .github/workflows/ 且 release-please 會改動它時才需要
  ——2026-08-22 逐一實查 entire / lawyer / memory-dessert / wedding / lexvision /
  rimivo / jurislm-tools 七個 repo,全都沒有該目錄,且 release-please-config.json
  的 extra-files 也沒有任何一項指向 workflow 檔。
- **實際持有的**:21 個 scope,含 admin:org、admin:enterprise、admin:org_hook、
  delete_repo、write:packages 等。透過 GitHub API 回應的 X-OAuth-Scopes header 讀回。

也就是說這顆共用憑證是明顯的過度授權:一個只需要 repo 的用途,配了一把能刪 repo、
能改組織設定的鑰匙。文件現在把「最小需求」與「現況」分開寫,並註明下次輪替應收斂。

沒有在這次一併收斂 scope,因為那是會影響七個 repo 發版的動作,且該 token 同時被
GitHub MCP 與 gh api 使用,收斂前要先確認那些用途的需求——另行處理。

* docs(ci): 依外部審查補上 Administration: Read 並修正權限診斷指引

兩個 finding 都取證確認後修正。

1. fine-grained PAT 漏了 Administration: Read(Codex 於 jurislm-tools #251 指出)

   scripts/release-pr-auto-merge.mjs 會呼叫
   GET /repos/{owner}/{repo}/branches/{branch}/protection 驗證分支保護設定。
   GitHub 官方 fine-grained PAT 權限表明列該端點需要 Administration: Read。
   照原本的清單(只有 Contents/Pull requests/Issues)鑄出來的 token,每個符合
   資格的 release PR 都會在合併前 403 失敗。

   這一項只適用有 release-pr-auto-merge pipeline 的 repo(lexvision、rimivo、
   jurislm-tools、entire),因此以條件句寫入,不是無條件要求。

2. 「唯一可靠的症狀是版號不再前進」講太絕對(CodeRabbit 於 memory-dessert #116 指出)

   我原本的意思是「不要靠 stage 的綠紅去推斷缺哪個權限」,但寫成了「其他症狀都
   不可靠」,那是錯的:pipeline log 裡 release-please 的實際輸出與 GitHub API
   回應都會顯示權限問題,403 回應甚至會帶 X-Accepted-GitHub-Permissions header
   直接指出缺哪一項。改為指向這些真正的診斷來源,並提醒一併確認 Drone Web UI 上
   secret 是否確實已設定。

五個 repo 的註解仍逐字相同(sha256 指紋 5e2f76a4ce3d),repo-standards 的 secret 表
與 SKILL.md 同步更新——那是權威來源,漏掉的話日後新建的 repo 會再踩一次同一個坑。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants