feat/preflight-auth-check
develop
在 README 流程新增第 0 點與設計第 11 點,並在 TODO 新增階段十二, 說明 action 啟動時集中驗證 Gitea token、comment token 與 LLM API Key 是否可用,任一失敗即 exit 1。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 app/preflight.js,在 action 啟動(Step1 之後、其餘步驟之前)集中 檢查必要環境變數、GITEA_TOKEN 讀 repo、GITEA_COMMENT_TOKEN、以及 LLM provider/API Key(多把只要一把通過即可,Ollama 改檢查 base URL 連線)。 任一項失敗即印出原因並 exit 1,避免分析到一半或發 comment 時才失敗。 main.js 在 Step1 後呼叫 runPreflight();新增 preflight.test.js 覆蓋 成功、缺環境變數、token 無效、所有 LLM key 失敗、Ollama 等情境。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
git push 走 askpass + HTTP 認證,與 Gitea REST API 是兩套機制,API token 有效不代表 push 能用(曾出現 askpass 無法執行、could not read Username 而 push 失敗)。新增 git.js verifyRemoteAccess() 以相同 askpass + remote URL 跑唯讀 git ls-remote,preflight 呼叫並在失敗時 exit 1,提前攔下設定問題。 新增 git.test.js 對 verifyRemoteAccess 的測試(成功、失敗不丟例外、token 不外洩、askpass 清理)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔍 服務:gemini 模型:gemini-2.5-flash
verifyLLM
_verifyOllamaLLM
_verifyOpenAICompatibleLLM
Promise.allSettled
e.message
GITEA_SKIP_TLS_VERIFY
true
runPreflight
checkRequiredEnv
verifyGiteaToken
verifyCommentToken
verifyRemoteAccess
false
commitAndPush 傳入 async callback,但 withAskpass 是同步 try/finally, 會在第一個 await(LLM 合併指令檔)時就刪除 .git-askpass.sh,導致後續 git push 因 GIT_ASKPASS 指向已刪除腳本而失敗(cannot exec .git-askpass.sh / could not read Username)。前置驗證的 verifyRemoteAccess 用同步 callback 所以 ls-remote 通過,造成前置驗證過但 push 失敗的落差。 改為當 callback 回傳 thenable 時以 result.finally(cleanup) 延後清理, 同步 callback 維持立即清理與原樣回傳,不影響 verifyRemoteAccess / cloneRepo。 新增回歸測試斷言 git push 執行當下 askpass 腳本仍存在。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
_verifyOllama
_verifyOpenAICompatible
preflight.test.js
app/git.js
git
git.js
config.js
rejectUnauthorized: false
triage 6 筆 review findings:1 筆修正、5 筆移入 exclusions。 修正(Maya, warning):runPreflight 僅測過 env 缺失早退,缺成功路徑與 各失敗點覆蓋。將其驗證步驟改為可注入的 deps 參數(預設沿用原函式, 行為不變),並補上完整成功、comment 略過、各失敗點早停、workspace 傳遞共 8 個測試。 移入 exclusions(誤報,保留原文): - Rex critical:GITEA_SKIP_TLS_VERIFY 為預設開啟驗證的 opt-in 設定, 與既有 gitea.js 排除一致,非漏洞 - Leo warning:verifyLLM 內聚清楚,拆分屬主觀重構 - Zara warning:每把 key 30s timeout 為刻意的可靠性下限,僅失敗時累積 - Rex info:axios 錯誤訊息不含認證標頭/內容 - Aria info:預設參數引用 config 常數為刻意且利於測試的 pattern findings.json 清空(全部已修正或排除)。app/ 測試 112 pass。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
axios.post
httpsAgent
await axios.post(
, payload, { headers, timeout: 30000, httpsAgent });
Maya critical(app/preflight.js:107):verifyLLM 的 axios.post 未帶 httpsAgent,認為 GITEA_SKIP_TLS_VERIFY 未套用到 LLM 請求。 判定為誤報並移入 exclusions: - GITEA_SKIP_TLS_VERIFY 為 Gitea 端(內網自簽憑證)專用設定,外部 LLM 服務(Gemini/OpenAI/Claude)應維持 TLS 驗證,套用此 flag 屬安全降級 - 與既有 app/llm.js 排除一致(已刻意移除 rejectUnauthorized:false 還原 TLS 驗證) findings.json 清空(已排除)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
app/preflight.js
clearLLMEnv
clearLlmEnvironmentVariables
resetLlmEnv
No dependencies set.
The note is not visible to the blocked user.
🤖 AI Code Review 團隊
🔍 新發現問題(3 筆)
verifyLLM函式處理了多個 LLM 供應商(Ollama, Claude, OpenAI-compatible)的驗證邏輯,並包含多個 API Key 的迭代。這使得函式較長且複雜度稍高。考慮將不同供應商的驗證邏輯拆分成獨立的私有輔助函式(例如_verifyOllamaLLM、_verifyOpenAICompatibleLLM),以提高模組化程度、可讀性,並更容易擴展或修改特定供應商的邏輯。verifyLLM函數中,當配置了多個 LLM API Key 時,會依序嘗試每個 Key。每個嘗試都包含一個最長 30 秒的網路請求。如果配置了大量 Key 且前幾個 Key 都失敗,這可能導致前置驗證階段耗時過長(例如,5 個 Key 失敗 4 個可能需要 2 分鐘)。建議評估實際使用情境中 API Key 的數量。如果預期會有大量 Key 或希望加快驗證速度,可以考慮將這些 API Key 的驗證請求並行化(例如使用Promise.allSettled),但需注意並行請求可能對 API 服務造成壓力或觸發速率限制。e.message進行消毒或僅記錄錯誤類型,以避免潛在的敏感資訊(例如 API Key 片段)洩漏到日誌中。某些 LLM 服務的錯誤訊息可能會包含請求的敏感部分。🚨 嚴重問題
GITEA_SKIP_TLS_VERIFY為true。禁用 TLS 憑證驗證會使應用程式容易受到中間人攻擊 (Man-in-the-Middle attacks)。請確保 Gitea 伺服器使用有效的 TLS 憑證,並移除此選項或僅在受控的開發/測試環境中使用。🚨 嚴重問題
runPreflight函數是整個前置驗證流程的協調者,但目前的測試僅涵蓋了第一個環境變數檢查失敗的早期退出情境。請新增測試案例來驗證以下關鍵行為:checkRequiredEnv,verifyGiteaToken,verifyCommentToken,verifyRemoteAccess,verifyLLM)都成功時,runPreflight應回傳true。verifyGiteaToken失敗、verifyCommentToken失敗、verifyRemoteAccess失敗、verifyLLM失敗),runPreflight應正確地短路並回傳false,確保錯誤處理邏輯在每個階段都有效。 |🤖 AI Code Review 團隊
🔍 新發現問題(5 筆)
verifyLLM處理了多種 LLM 供應商的驗證邏輯(Ollama、Claude、OpenAI 相容等),導致其長度較長且複雜度較高。建議將不同供應商的驗證邏輯拆分成獨立的輔助函式(例如_verifyOllama、_verifyOpenAICompatible),以提高模組化程度和可讀性。verifyLLM函式中,當配置了多個 LLM API Key 時,系統會依序嘗試驗證每個 Key,每個嘗試都有 30 秒的逾時時間。如果前幾個 Key 驗證失敗,這可能導致顯著的累積延遲。雖然這是為了找到一個可用的 Key,但若 Key 數量多且網路不穩定,可能會造成啟動時間過長。可以考慮縮短單次 Key 驗證的逾時時間,或在特定情況下提供更快的失敗機制。runPreflight函數是一個重要的協調器,它依賴於多個內部驗證函數。目前的測試runPreflight僅涵蓋了環境變數缺失導致的早期終止情況。請為runPreflight函數添加以下測試案例,以確保其行為的完整性:checkRequiredEnv,verifyGiteaToken,verifyCommentToken,verifyRemoteAccess,verifyLLM)都成功的情況,驗證runPreflight返回true。checkRequiredEnv),添加一個測試案例,模擬該函數失敗而其之前的函數都成功的情況,驗證runPreflight返回false並在正確的步驟停止。runPreflight的測試更具單元性,請考慮在preflight.test.js中模擬verifyRemoteAccess函數(從app/git.js導入),而不是讓它執行實際的git命令。這將使runPreflight的測試更穩定且獨立於git.js的實現細節。 || 🔵 建議 | Rex | app/preflight.js:100 | 在記錄 LLM API 驗證失敗時,直接輸出了錯誤訊息
e.message。雖然通常情況下e.message不會包含敏感資訊,但為了最佳安全實踐,建議審查 LLM 服務提供商的錯誤訊息格式,確保其中不會意外洩漏 API 金鑰或其他敏感請求內容。若有疑慮,應對錯誤訊息進行消毒或僅記錄高層次的錯誤類型。 || 🔵 建議 | Aria | app/preflight.js:30 | 在
checkRequiredEnv、verifyGiteaToken和verifyCommentToken等函式中,預設參數直接引用了從config.js匯入的常數。雖然這在功能上可行,但為了提高程式碼的清晰度和一致性,建議考慮以下兩種方式之一:1. 將所有配置值作為明確的參數從呼叫端傳入。2. 讓函式直接從config.js模組中讀取這些值,而不是透過預設參數。 |🚨 嚴重問題
GITEA_SKIP_TLS_VERIFY環境變數來禁用 TLS 憑證驗證 (rejectUnauthorized: false),這會使應用程式容易受到中間人 (Man-in-the-Middle, MITM) 攻擊。攻擊者可能在不被察覺的情況下攔截和修改與 Gitea 伺服器的通訊。建議移除此功能,或確保在任何生產環境中永不啟用。如果 Gitea 伺服器使用自簽憑證,應將其憑證加入信任儲存區,而非禁用驗證。🤖 AI Code Review 團隊
🚨 嚴重問題
verifyLLM函數中,呼叫axios.post時缺少httpsAgent選項。這會導致即使設定了GITEA_SKIP_TLS_VERIFY,LLM 的 API 請求仍可能因 TLS 憑證問題而失敗。請將httpsAgent傳遞給axios.post的選項物件,例如:await axios.post(${base}/chat/completions, payload, { headers, timeout: 30000, httpsAgent });🤖 AI Code Review 團隊
🔍 新發現問題(5 筆)
app/preflight.js中的 JSDoc 和日誌),則應將此測試描述翻譯為繁體中文。clearLLMEnv雖然可理解,但可以更具描述性,例如clearLlmEnvironmentVariables或resetLlmEnv。