leo 2026-07-20 明令:「已經改用 cf 自己的 secrets,不要再說它了」 「我希望以後再也看不到這個詞再出現」 背景:credential 早已遷移至 CF Workers per-script Secrets + D1 目錄, 舊的自管金鑰(client 端 AES-GCM + KV 密文 + crypto_decrypt)是遷移期遺留。 本次連根移除,含一併作廢的死 SaaS 碼。 移除: - 舊 KV 密文解密路徑(credential-injector.ts 整檔、dual-read fallback) 前置驗證:leo21c / youlin 兩帳號 CREDENTIALS_KV 實測 *:cred:* 皆 0 筆 - migrate-to-workers-secrets 搬家端點(回填已完成,無可回填) - /register 路由與 generateApiKey(HMAC 產 ak_ key 是 SaaS 遺物; self-hosted 走 namespace 明碼 D21,已無人使用) - platform_crypto component(三帳號實測 404 已退役,無 workflow 引用) 保留(附理由): - crypto_decrypt 保留為永遠回失敗的 stub——現役三個 auth .wasm 仍宣告該 import,缺項會讓 WASM instantiate 直接失敗。待零件重編後可真正刪除。 順帶修復(原不在範圍,但會實際壞事): - /auth/callback 有 `if (!key) redirect(server_error)` 閘,未設該 secret 的 實例會登入直接失敗 → 已移除 - OAuth 兩處把 provider token 寫進舊加密 KV(租戶鍵與實際 api_key 在 rotate 後必然分歧,已失效)→ 改導向 Workers Secrets,包 try/catch 不影響登入 - acr init Standard 模式呼叫已刪除的 /register → 改引導 OAuth 取 key - .claude/rules 與 system-dev/docs 是同一規範的兩份鏡像,先前只改 rules 導致鏡像仍在教舊做法 → 已同步(此類雙檔同步應納入檢查) 新用戶安裝從此零 secret 前置。 測試 187/188(唯一 fail 為 pre-existing,stash 驗證與本次無關); cypher-executor 與 cli typecheck 全綠。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.3 KiB
Design 補充:設定分層(env > 專案層 > 全域)+ init 非互動
2026-06-04 建立。
sdk-and-website/design.md的單檔補充(規則 02 §4.3 允許)。 來源:docs/壓測報告.md§1.2(方案 C)+ §2.2(init 非互動)= 阻斷項 #7、#8。 richblack 2026-06-04 授權:「#7#8 是同一問題,明顯發現的問題當然要解決,完成後就要推。」
1. 問題(壓測實測)
acr v1.1.0 把設定寫死在全域唯一一份 ~/.arcrun/config.yaml(config.ts:
CONFIG_DIR = join(homedir(), '.arcrun')),且 init 只能 readline 互動。後果:
- #8 多帳號:同一台電腦只能一個 arcrun 身份 → 接案者 / 多公司 / 個人+公司混用做不到。
壓測者克難法是覆寫
HOME(需讀原始碼才找得到、不直覺)。 - #7 非互動:init 只能 TTY 問答 → AI / CI 無法用 flag / env 完成。
兩者本質同一:設定來源不該只有「全域單檔 + 強制 TTY」一條路。
2. 設計(richblack 2026-06-04 拍板:三層全上 + init flag/env)
2.1 設定分層優先序(仿 git config / Claude Code MCP)
1. 環境變數 ARCRUN_* / CLOUDFLARE_* ← 最高,解 #7(AI/CI 非互動)
2. 專案層設定 <就近往上找>/.arcrun.yaml ← 解 #8(接案多帳號),有 fallback
3. 全域設定 ~/.arcrun/config.yaml ← 平常自動用(自己的帳號)
- 就近往上找:從
process.cwd()往上層目錄逐層找.arcrun.yaml,找到第一個即用(停在檔案系統根)。 → 自己的專案不放檔 → 自動 fallback 全域;客戶資料夾放檔 → 只在該樹生效,離開自動切回。零心智負擔、不會忘記切換。 - 覆蓋是「欄位級 merge」:高層只覆蓋它有提供的欄位,未提供的欄位 fallback 到低層。
(例:專案層只放
cypher_executor_url,其餘仍用全域。)
2.2 env 變數對應(最高層,欄位級覆蓋)
| env | 覆蓋 config 欄位 | 用途 |
|---|---|---|
ARCRUN_MODE |
mode |
local/standard/self-hosted |
ARCRUN_API_KEY |
api_key |
standard |
ARCRUN_CYPHER_EXECUTOR_URL |
cypher_executor_url |
self-hosted 指向自己的 cypher |
CLOUDFLARE_ACCOUNT_ID |
cloudflare_account_id |
self-hosted(沿用 wrangler 慣用名) |
CLOUDFLARE_API_TOKEN |
cf_api_token |
self-hosted(沿用 wrangler 慣用名) |
CF 兩個用
CLOUDFLARE_*而非ARCRUN_*:與 wrangler / deploy.ts 既有慣例一致(deploy.ts 跑 wrangler 時就是設這兩個 env),CI 設一次兩邊通用。
2.3 init 非互動(flag > env > 互動問答)
acr init --self-hosted 取得 account-id / api-token 的順序:
- flag:
--account-id <id>/--api-token <token> - env:
CLOUDFLARE_ACCOUNT_ID/CLOUDFLARE_API_TOKEN - 互動:前兩者缺才 readline 問(保留現有 UX)
mindset §7 判準:帳號設定不是「暴露資料 / 建零件」類風險確認,是單純設定值,flag/env 合法、不違反「非 TTY 拒絕代人類確認」。 風險確認(exposure_consent 等)仍維持需人類明示,不在本次放寬範圍。
3. 實作(只動 cli/)
| 檔案 | 動作 |
|---|---|
cli/src/lib/config.ts |
loadConfig() 改三層解析:全域 → merge 專案層 findProjectConfig() → merge env(applyEnvOverrides())。新增 acr config --where 用的 resolveConfigSources() |
cli/src/commands/init.ts |
cmdInit / initSelfHosted 收 accountId/apiToken options,缺才走 env 再 fallback 互動 |
cli/src/index.ts |
init 加 --account-id <id> / --api-token <token> option |
loadConfig() 是唯一設定入口(12 個指令全走它)→ 改它一處,全指令自動受益分層。
3.1 acr config --where(壓測 §1.2 建議 #3,避免用錯帳號)
新增輕量 acr config 指令,印出「現在這個資料夾正用哪個帳號 / 設定來自哪一層」:
mode: self-hosted(來源:專案層 /path/客戶A/.arcrun.yaml)
cloudflare_account_id: abc...(來源:env CLOUDFLARE_ACCOUNT_ID)
cypher_executor_url: https://...(來源:全域 ~/.arcrun/config.yaml)
安全價值:部署前一眼確認「沒用錯帳號」。本次一併做(成本低、直接回應壓測痛點)。
3.2 安全:專案層 .arcrun.yaml 含憑證 → 必須 gitignore
專案層 .arcrun.yaml 可能含 cf_api_token。createCredentialsYamlIfMissing() 既有 gitignore 邏輯
擴充為一併忽略 .arcrun.yaml(壓測 §1.2 安全附帶發現:憑證進版控 = 帳號外洩)。
4. 驗收標準(客觀證據,mindset §7)
- 專案資料夾放
.arcrun.yaml→acr config --where顯示來源為該專案層;離開該樹 → 顯示全域。 CLOUDFLARE_ACCOUNT_ID=x CLOUDFLARE_API_TOKEN=y acr init --self-hosted→ 不問互動直接跑(#7)。acr init --self-hosted --account-id x --api-token y→ 同上(flag 優先於 env)。- 三者皆缺 → fallback 互動問答(既有 UX 不破壞)。
- env > 專案層 > 全域 的欄位級覆蓋:單元測試覆蓋三層 merge。
npx tsc --noEmit全綠。
4.1 實作完成記錄(2026-06-04)
全部 task 完成,客觀證據如下(mindset §7):
config.ts三層解析:loadConfig()= 全域 → 專案層 → env 欄位級 merge;新增findProjectConfig()(就近往上找)/resolveConfigSources()/activeProjectConfigPath()init.ts:initSelfHosted收 flag/env,缺才互動;gitignore 一併排除.arcrun.yamlindex.ts:init 加--account-id/--api-token;新增acr config [--where]指令- 新增
commands/config.ts(token 遮罩、來源層標示) - 驗收證據:
- 端對端測試(真實 fs 臨時目錄樹)8/8 通過:深層就近找專案層、未提供欄位 fallback、env 最高層覆蓋、來源層標示、離開專案樹回全域
acr init --help顯示 flag;acr config --where正確標來源 + token 遮罩secret_t…npx tsc --noEmit全綠
5. 為何不違反鐵律
- 只動
cli/,不碰零件 / cypher-executor 執行路徑 / Service Binding。 - flag/env 是帳號設定值,非風險確認(mindset §7 風險確認仍須人類明示)。
- 不新增頂層 SDD 目錄(本檔是 sdk-and-website 子系統內單檔補充,rule 02 §4.3)。