refactor: 移除已廢棄的自管加密金鑰機制(credential 全面託管 CF Workers Secrets)
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>
This commit is contained in:
@@ -30,7 +30,8 @@
|
||||
|---|---|
|
||||
| `u6u.http_request` | 發 HTTP 請求 |
|
||||
| `u6u.kv_get` | 讀 Cloudflare KV(Worker 側依 key 前綴路由到正確 KV) |
|
||||
| `u6u.crypto_decrypt` | AES-GCM 解密(encryption key 永不暴露給 WASM) |
|
||||
| `u6u.secret_get` | 讀 CF Workers Secrets(只放行 `CRED_` 前綴) |
|
||||
| `u6u.crypto_decrypt` | ⚠️ 已廢除,保留成永遠回失敗的 stub(現役 wasm 仍宣告此 import) |
|
||||
| `u6u.crypto_sign_rs256` | RSA-SHA256 簽章(PKCS8 bytes 傳入) |
|
||||
|
||||
**所有 host function 在 `cypher-executor/src/lib/wasi-shim.ts` 實作**。零件透過 WASI import 使用。
|
||||
@@ -50,16 +51,22 @@
|
||||
|
||||
**警告:R2 不存平台內建零件的 WASM**。平台零件已 bundle 進各自的 Worker binary(`[[wasm_modules]]` 或 `import ... assert { type: 'webassembly' }`)。
|
||||
|
||||
## 加解密規範
|
||||
## Credential 儲存規範
|
||||
|
||||
- **演算法**:AES-GCM 256-bit
|
||||
- **加密位置**:Client 端(CLI / Python SDK / JS SDK)
|
||||
- Python:`cryptography` 套件
|
||||
- JS:Web Crypto API(`crypto.subtle`)
|
||||
- **解密位置**:Server 端 **WASM primitive**(透過 host function `crypto_decrypt`)
|
||||
- cypher-executor TS **不解密**,只提供 host function
|
||||
- `ENCRYPTION_KEY` 只在 Worker host function 內部讀取,**永不經 stdin / 回傳值傳給 WASM**
|
||||
- **傳輸格式**:`{ name, encrypted, iv }`(iv base64、encrypted base64)
|
||||
**arcrun 不自管加密金鑰。** credential 明文由 **Cloudflare Workers Secrets** 託管
|
||||
(per-script secret,掛在用戶自己的 cypher worker 上):
|
||||
|
||||
- secret 名稱 = `CRED_{NAME}_{sha256(api_key)[:8]}`(跨租戶命名隔離)
|
||||
- D1 `credentials` 表只存**目錄**(api_key / name / service / secret_ref),不存值
|
||||
- D19:擁有目錄,不擁有內容物——連 owner 都讀不回,只能覆寫/刪除
|
||||
- 需要 worker 設 `CF_SECRETS_API_TOKEN`(機密,用戶手動 put)+ `CF_ACCOUNT_ID`(自動注入)
|
||||
|
||||
> 註:`crypto_decrypt` host function 是**永遠回失敗的 stub**,因為現役三個 `auth_*`
|
||||
> `.wasm` 仍宣告該 import(缺項會讓 WASM instantiate 失敗)。三個零件重編後即可刪除。
|
||||
- **取用位置**:Server 端 **WASM primitive**(透過 host function `secret_get(ref)`)
|
||||
- cypher-executor TS 不碰業務邏輯,只提供 host function
|
||||
- `secret_get` 只放行 `CRED_` 前綴,WASM 讀不到 worker 本身的其他機密
|
||||
- **傳輸格式**:明文值走 TLS(`POST /credentials`),不做 client 端加密
|
||||
|
||||
## 網路部署
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ superseded_by: ""
|
||||
|
||||
# Design Document: arcrun MVP
|
||||
|
||||
> ⚠️ 本檔的 credential 注入程式碼範例描述舊儲存機制,已於 2026-07-20 移除。
|
||||
> 現行做法見 `.claude/rules/01-tech-stack.md`「Credential 儲存規範」。
|
||||
|
||||
## Overview
|
||||
|
||||
arcrun MVP 的核心設計原則是**最小異動、最快可用**。所有目標都能透過以下三個操作達成:
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
- [x] 14. `acr init` 已實作,修正項:
|
||||
- [x] 14.1 Standard 模式不再傳送 `cf_api_token` 至 arcrun.dev(只傳 `email`)
|
||||
- [x] 14.2 `require()` 改用 `await import()` 修正 ES module 相容
|
||||
- [ ] 14.3 **待補**:`acr init` 需詢問 `ARCRUN_ENCRYPTION_KEY` 並寫入 config(目前加密 key 需手動設定)
|
||||
- _Requirements: 4.2, 6.3_
|
||||
|
||||
- [x] 15. `acr creds push` 已實作
|
||||
@@ -193,7 +192,6 @@
|
||||
|
||||
- [ ] A. `builtins/` 清理:`initComponents.ts` 仍用舊的 HTTP endpoint 模式上架零件(`buildComponentDefs` 含 URL),應改為呼叫 `POST /submit` 送 WASM binary + contract,或直接移除 builtins(功能已整合到 registry)
|
||||
- [ ] B. `validate` 指令 credential 檢測邏輯修復(見 Phase 4 Task 18)
|
||||
- [ ] C. `acr init` 加入 `ARCRUN_ENCRYPTION_KEY` 設定步驟
|
||||
- [ ] D. `acr parts` YAML 解析改用 `js-yaml`
|
||||
|
||||
---
|
||||
|
||||
@@ -63,10 +63,10 @@ P0 全部清除才啟動封測。
|
||||
|---|------|------|------|
|
||||
| 1 | acr parts scaffold 正確輸出 | ✅ 完成 | 21 個零件內建清單 |
|
||||
| 2 | acr recipe push 端對端 | ✅ 完成 | httpbin_post 驗證通過 |
|
||||
| 3 | acr creds push 代碼 | ✅ 完成 | 需 ARCRUN_ENCRYPTION_KEY |
|
||||
| 3 | acr creds push 代碼 | ✅ 完成 | 值交 CF Workers Secrets 託管 |
|
||||
| 4 | credential 注入端對端 | ✅ 完成 | 無 token 時錯誤訊息正確 |
|
||||
| 5 | acr push + webhook trigger | ✅ 完成 | 端對端驗證通過 |
|
||||
| 6 | acr creds push 實測 | ✅ 完成 | /register 回傳 encryption_key,acr init 自動存入 config(CLI 1.0.9)|
|
||||
| 6 | acr creds push 實測 | ✅ 完成 | acr init 自動存入 config(CLI 1.0.9)|
|
||||
| 7 | Google Sheets 真實寫入 | ⚠️ 部分驗證 | credential 注入已驗證;實際 Sheets 寫入需真實 OAuth token |
|
||||
| 8 | 第三方服務認證 recipe | ✅ 完成 | 20 個服務(Notion/Slack/GitHub/OpenAI 等),CLI 1.1.0 |
|
||||
| **9** | **cypher-executor outbound HTTP fetch 全失效** | ✅ **已解決 2026-05-13**(CF 同 zone 自循環死鎖,改走 workers.dev)| 詳見下方專段 |
|
||||
@@ -339,8 +339,7 @@ acr push 就會自動建立 cron-idx 並開始定時觸發。
|
||||
|
||||
## 四、封測前 P3(啟動當天)
|
||||
|
||||
- [ ] 用封測者 email 呼叫 `/register`,取得 api_key
|
||||
- [ ] 將 ARCRUN_ENCRYPTION_KEY 以安全方式提供給封測者
|
||||
- [ ] 引導封測者到 arcrun.dev 登入取得 api_key
|
||||
- [ ] 確認聯絡管道
|
||||
|
||||
---
|
||||
|
||||
+10
-1
@@ -1,5 +1,9 @@
|
||||
# Credential Store 遷移 SDD — KV → D1(目錄)+ CF Workers per-script Secrets(密文)
|
||||
|
||||
> ⚠️ **歷史記錄(本卷 T1-T10 已全數完成,2026-07-20 收尾)**。本檔記述的是「從舊自管金鑰
|
||||
> 遷移到 CF Workers Secrets」的過程,文中提及的舊機制**均已不存在**,僅供考古,勿依此操作。
|
||||
> 現行做法見 `.claude/rules/01-tech-stack.md`「Credential 儲存規範」。
|
||||
|
||||
> 建立:2026-06-29 by arcrun CC|對應 issue:Arcrun#13(優先序 3)|決策:leo 2026-06-29 拍板(D19)
|
||||
> **修訂 2026-07-03(T1.5 spike,證據 Arcrun#2)**:密文的家由「CF Secrets Store 產品」改為「**CF Workers per-script Secrets**」(`wrangler secret put` / API `PUT /accounts/{id}/workers/scripts/{script}/secrets` 那套)。原因:T1 spike 實證 Secrets Store 的 Worker binding 部署時靜態宣告、`.get(ref)` 參數被忽略,不支援「runtime 依 D1 ref 動態查任意 secret」;T1.5 spike 四驗證全過(API 動態加免重部署/`env[ref]` 動態索引可行/14 把未觸上限/重部署後存活),方向定案。§2.3、§2.5、T3、T4 已依此改寫;**雙讀過渡、回填、回滾、治理(D1 只存 metadata+secret_ref 不存密文)設計不動**。D21(2026-07-02 leo 拍板):當作 SaaS 不存在,按單用戶自架設計,多租戶段落標「future SaaS 再議」。
|
||||
> 範圍宣告:本檔是既有 SDD `credential-primitives-wasm/` 的補充設計(rule 02 §4.3 例外:現有 SDD 目錄內新增單檔)。**不施工,先 SDD,總管審對齊後放行。**
|
||||
@@ -370,6 +374,11 @@ CLI 薄殼(rule 07):`acr creds list`(讀 D1 顯示)、`acr creds repla
|
||||
清空 → 另外手工在 KV 塞一筆「只存在舊 KV、無 D1 row」的假資料,`DELETE` 走
|
||||
legacy-kv fallback 分支,CF API 核對 KV key 真的被刪除。兩分支皆對真實
|
||||
leo21c 帳號驗證通過,非模擬。
|
||||
- [ ] T10 回填驗證 + 觀察期 → 廢 ENCRYPTION_KEY(§4.4,leo 明示放行)。
|
||||
- [x] T10 回填驗證 + 觀察期 → 舊自管金鑰路徑全數移除(§4.4,leo 明示放行)。2026-07-20 完成:
|
||||
兩帳號 CREDENTIALS_KV 實測 0 筆密文(無可回填)→ 移除舊雙讀 fallback、回填端點、
|
||||
client 端加密與相關零件(`platform_crypto`、`credential-injector.ts`、`register.ts`)。
|
||||
`crypto_decrypt` host function 保留成永遠回失敗的 stub(現役三個 `auth_*` .wasm 仍宣告
|
||||
該 import,缺項會讓 WASM instantiate 失敗);三個零件重編後即可刪除。
|
||||
**本卷至此全數完成,屬歷史記錄。**
|
||||
|
||||
> **每個 cred 操作跨 TS / WASM / host-function / 兩個 store,必端到端實測**(防再假綠,mindset §7)。原「T1 不通則整案停」已兌現一輪:T1 負結果 → 整案停 → 總管裁決轉向 → T1.5 全過 → **T2-T9 解凍**。備援(若施工再撞死路):codegen binding + 自動重部署(Arcrun#2 總管裁決的方向 1)。
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Credential Store 重設計提案(A telegram 一致性 + B KV→D1 + C 友善前門)
|
||||
|
||||
> ⚠️ **歷史記錄**:本檔的儲存決策已被 `credential-store-migration.md` 取代並執行完畢
|
||||
> (2026-07-20)。文中提及的舊自管金鑰機制**已不存在**,僅供考古,勿依此操作。
|
||||
|
||||
> 建立:2026-06-29 by arcrun CC|更新:2026-06-29(依 leo 最終精確 spec 改寫)|對應 issue:Arcrun#13
|
||||
> 範圍宣告:本檔是既有 SDD `credential-primitives-wasm/` 的補充設計筆記(不是新 SDD 子系統,rule 02 §4.3 例外)。
|
||||
> 詞彙(leo 堅持精確):**零件/component=TinyGo WASM**、**recipe=http_request+固定設定(打最終 API)**、
|
||||
|
||||
@@ -5,6 +5,11 @@ superseded_by: ""
|
||||
|
||||
# Design Document: Credential Primitives TS → WASM 改寫
|
||||
|
||||
> ⚠️ **本檔的 credential 儲存/解密段落已過時**(`crypto_decrypt` 現為永遠回失敗的 stub,
|
||||
> credential 值改由 CF Workers Secrets 託管、經 `secret_get(ref)` 取用)。遷移已於
|
||||
> 2026-07-20 完成,見 `credential-store-migration.md`;現行做法見
|
||||
> `.claude/rules/01-tech-stack.md`「Credential 儲存規範」。以下解密相關敘述僅供考古。
|
||||
|
||||
## Overview
|
||||
|
||||
將 `cypher-executor` 中以 TypeScript 實作的 credential 注入邏輯,改寫為 4 個獨立的 WASM 零件。這是 `credential_parts.md` 長期規格的實現,不再是「未來 Phase」。
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Implementation Tasks: Credential Primitives TS → WASM
|
||||
|
||||
> ⚠️ **歷史記錄**:文中 credential 加解密相關的完成記錄描述的是舊機制,該機制已於
|
||||
> 2026-07-20 完全移除(見 `credential-store-migration.md` T10)。僅供考古,勿依此操作。
|
||||
|
||||
**嚴格規範(richblack 2026-04-19)**:cypher-executor TS 不得實作任何 credential / auth / template / JWT / 解密邏輯。全部走 TinyGo WASM + host functions(方案 B)。
|
||||
|
||||
**封測狀態**:推遲(richblack 2026-04-19 決定)。先完成 Phase 1-3 清除違規 TS,再啟動封測。
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|---|---|---|
|
||||
| `ARCRUN_MODE` | `mode` | local/standard/self-hosted |
|
||||
| `ARCRUN_API_KEY` | `api_key` | standard |
|
||||
| `ARCRUN_ENCRYPTION_KEY` | `encryption_key` | standard/self-hosted |
|
||||
| `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 慣用名)|
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
- **`wrangler deploy` 部署全部 Worker**(用戶已裝 wrangler)
|
||||
- seed auth recipe + API recipe 進 RECIPES KV
|
||||
- 寫回 `~/.arcrun/config.yaml`
|
||||
- 印出「手動 `wrangler secret put ENCRYPTION_KEY` ×3」提示(secret 不自動化,rule 05)
|
||||
- 印出「手動 `wrangler secret put CF_SECRETS_API_TOKEN`」提示(secret 不自動化,rule 05)
|
||||
|
||||
### 關鍵技術決策(richblack 2026-06-02)
|
||||
| 決策 | 選擇 | 理由 |
|
||||
@@ -82,10 +82,8 @@ acr init --self-hosted
|
||||
├─ 7. 寫回 config(mode: self-hosted + 所有 id + cypher_executor_url = 部署後 workers.dev URL)
|
||||
│
|
||||
└─ 8. 印手動 secret 提示:
|
||||
wrangler secret put ENCRYPTION_KEY --name arcrun-cypher-executor
|
||||
wrangler secret put ENCRYPTION_KEY --name arcrun-auth-static-key
|
||||
wrangler secret put ENCRYPTION_KEY --name arcrun-auth-service-account
|
||||
(三 Worker 共用同一把 key,見 memory: encryption-key-drift-trap)
|
||||
wrangler secret put CF_SECRETS_API_TOKEN --name arcrun-cypher-executor
|
||||
(credential 值交 CF Workers Secrets 託管;auth 零件不需 secret)
|
||||
```
|
||||
|
||||
### `acr update`(同一條路,未來新零件)
|
||||
@@ -208,7 +206,7 @@ codebase 只有 auth recipe seed。新增 `seed-api-recipes.ts`,把現役 API
|
||||
|
||||
1. richblack 用**全新 CF 帳號** + wrangler 已裝 + 一個 CF API Token 跑 `acr init --self-hosted`
|
||||
→ 全程無手動建 KV / 無手動 clone / 無 tinygo / 無手動填 namespace id。
|
||||
2. 跑完印 secret 提示,richblack 手動 `wrangler secret put ENCRYPTION_KEY` ×3。
|
||||
2. 跑完印 secret 提示,richblack 手動 `wrangler secret put CF_SECRETS_API_TOKEN`。
|
||||
3. `acr push` 一個含 http_request + 自建 recipe 的 workflow → trigger → **HTTP 2xx + execution trace**。
|
||||
4. 冪等:重跑 init 不重建已存在 KV / 不報錯。
|
||||
5. `acr update` 拉新 codeload tarball(tag)→ 重部署成功。
|
||||
@@ -286,23 +284,22 @@ credential/部署/執行三條路徑全建在多租戶 `{api_key}:cred:{name}`
|
||||
|
||||
### 設計(richblack 2026-06-06)
|
||||
**self-hosted 的「api_key」= 明碼 namespace,用戶在 `.env` 自填。工具不生成、不 hash、不外傳。**
|
||||
- 兩欄(像 username/password,但都由用戶持有):
|
||||
- 一欄(由用戶持有):
|
||||
- `NAMESPACE=leo`(明碼分區標籤,當 KV 前綴;**非密碼**)
|
||||
- `ENCRYPTION_KEY=<64+ hex>`(creds 加密金鑰,用戶自保管;須與 worker secret 一致)
|
||||
- **誠實限制**(mindset §7):namespace 明碼不提供認證。要防外部呼叫 → 對 webhook 加保護(mindset §6);arcrun 不做授權判斷(mindset §3)。
|
||||
- **零分叉**:SaaS 仍走 register 發的真 api_key;self-hosted 走 .env 的 NAMESPACE。**同一條 `api_key` 路徑、同一份 config 解析**,只是值來源不同。
|
||||
|
||||
### 改法
|
||||
| 檔案 | 改動 |
|
||||
|---|---|
|
||||
| `cli/src/lib/config.ts` | `ENV_MAP` 加 `NAMESPACE`/`ARCRUN_NAMESPACE`/`ENCRYPTION_KEY` → 對應 `api_key`/`encryption_key`;新增 `.env` 自動載入(就近往上找,shell > .env,無 dotenv 依賴)|
|
||||
| `cli/src/commands/creds.ts`、`push.ts` | self-hosted 缺值時,引導設 `.env` 的 NAMESPACE/ENCRYPTION_KEY(不再叫去 register)|
|
||||
| `cli/src/commands/init.ts` | self-hosted 結尾改提示「在 .env 設 NAMESPACE + ENCRYPTION_KEY」+「把同把 key wrangler secret put 進 worker;不想自己跑可明示同意我代設」|
|
||||
| `cli/src/lib/config.ts` | `ENV_MAP` 加 `NAMESPACE`/`ARCRUN_NAMESPACE` → 對應 `api_key`;新增 `.env` 自動載入(就近往上找,shell > .env,無 dotenv 依賴)|
|
||||
| `cli/src/commands/creds.ts`、`push.ts` | self-hosted 缺值時,引導設 `.env` 的 NAMESPACE |
|
||||
| `cli/src/commands/init.ts` | self-hosted 結尾改提示「在 .env 設 NAMESPACE」+「把 CF_SECRETS_API_TOKEN wrangler secret put 進 worker;不想自己跑可明示同意我代設」|
|
||||
| `cypher-executor/src/routes/webhooks-named.ts` | 新增 `POST /webhooks/named/:ns/:name/trigger`(namespace 走 path,公開表單免 header);與 header 路徑共用 `triggerNamed`,不分叉 |
|
||||
| `cli/src/commands/push.ts` | self-hosted 輸出 path-based 公開 webhook URL(免 header)|
|
||||
|
||||
### 為何 namespace 進 URL path 安全
|
||||
namespace 是明碼標籤非密碼,放 path 不洩漏任何祕密。真正的祕密是 `ENCRYPTION_KEY`(在 worker secret + 用戶 .env,永不進 URL/path)。要防外部濫用 webhook 是「webhook 保護層」職責,非 namespace。
|
||||
namespace 是明碼標籤非密碼,放 path 不洩漏任何祕密。真正的祕密是 credential 值(由 CF Workers Secrets 託管,永不進 URL/path)。要防外部濫用 webhook 是「webhook 保護層」職責,非 namespace。
|
||||
|
||||
## 7.8 壓測修正(2026-06-08):onboarding 四缺陷 → pip 式自我修復安裝(CHANGE,待 review)
|
||||
|
||||
@@ -349,7 +346,7 @@ namespace 是明碼標籤非密碼,放 path 不洩漏任何祕密。真正的
|
||||
- [x] **P1**:`acr whoami`(`cli/src/commands/whoami.ts`,人讀 + `--json`,印 mode/帳號/連哪台/來源層,薄殼讀 resolveConfigSources)+ MCP `arcrun_whoami`(`mcp/src/tools/arcrun_whoami.ts`,回報 orgNamespace + binding,與 CLI 對齊)。AI 問工具拿身份,不自己 curl 猜。cli+mcp tsc exit 0。**2026-06-09 完成**
|
||||
- [x] **P2**:MCP 掛載重啟提示(D3)。`cli/src/commands/mcp-setup.ts` 寫完 `.mcp.json` 後印「⚠ 請重啟 IDE/client 才會載入 project scope MCP」+ 信任工作區提醒。經 init 也會流到(init 呼叫 cmdMcpSetup)。**2026-06-09 完成**
|
||||
- [~] **P3**:README/GitHub 入口整理成「AI 讀了就照著裝」的單一指引(D 無腦入口)。**部分完成 2026-06-09**:
|
||||
- 新增 repo 根 `.env.example` 範本(CF Account/Token 基礎兩格 + NAMESPACE/ENCRYPTION_KEY + 服務 token 區,
|
||||
- 新增 repo 根 `.env.example` 範本(CF Account/Token 基礎兩格 + NAMESPACE + 服務 token 區,
|
||||
每格上面白話說明「去哪申請、怎麼拿」,值留空。`.gitignore` 加 `!.env.example` 放行進 repo)。
|
||||
- `llms.txt` step 3 改成「**你(AI)先 `cp .env.example .env`**,帶用戶填值(用戶只填「=」右邊)」——
|
||||
把「建 .env 結構」從用戶身上挪到 AI,用戶只做貼值。step 4 補 init「安裝驗收」說明。
|
||||
|
||||
@@ -57,7 +57,7 @@ superseded_by: ""
|
||||
| P3 | `acr install-harness`(裝防護)| 否 | 自己跑 | CC 代跑(CC 讀 llms.txt 第一步就做)|
|
||||
| P4 | **建 CF 帳號 + 拿 Account ID + API Token** | **是**(憑證在用戶手上)| 自己建 | **CC 白癡化手把手帶**(§1.0 步驟2)|
|
||||
| P5 | `acr init --self-hosted`(貼 token,自動建 KV/部署/seed)| 否 | 自己跑 | CC 代跑(用 P4 拿到的兩串)|
|
||||
| P6 | `wrangler secret put ENCRYPTION_KEY` ×3 | 否 | 自己跑 | CC 代跑 |
|
||||
| P6 | `wrangler secret put CF_SECRETS_API_TOKEN` | 否 | 自己跑 | CC 代跑 |
|
||||
| P7 | 連 arcrun MCP(`claude mcp add`,CC 偏好的工具)| 否 | 自己跑 | CC 代跑(install-harness 順便)|
|
||||
|
||||
### 兩種執行者
|
||||
|
||||
@@ -62,10 +62,13 @@ find . -name 'wrangler.toml' -not -path '*/node_modules/*' -not -name 'wrangler.
|
||||
**CI 只提供 Cloudflare 驗證,不碰 runtime secret**。
|
||||
|
||||
- GH Actions secrets:`CLOUDFLARE_API_TOKEN`、`CLOUDFLARE_ACCOUNT_ID`(一次性設好)
|
||||
- Runtime secret(例:`ENCRYPTION_KEY`、`OPENAI_KEY`、`GOOGLE_API_KEY`):
|
||||
- Runtime secret(例:`CF_SECRETS_API_TOKEN`、`OPENAI_KEY`、`GOOGLE_API_KEY`):
|
||||
- **由 richblack 一次性手動** `wrangler secret put <KEY>` 設進各 Worker
|
||||
- 不進 CI,不進 `wrangler.toml` `[vars]`
|
||||
- 需要的 Worker:`auth_static_key`、`auth_service_account`(兩個都要 `ENCRYPTION_KEY`)
|
||||
- 需要的 Worker:`arcrun-cypher-executor`(`CF_SECRETS_API_TOKEN`——寫 credential 進
|
||||
Workers Secrets 用;`CF_ACCOUNT_ID` 非機密由 `acr init` 自動注入)
|
||||
|
||||
> `auth_static_key` / `auth_service_account` 不需要任何 secret。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# 5. Records — 日誌 + 驗收報告
|
||||
|
||||
> 線上事件復盤、測試報告、決策軌跡。
|
||||
>
|
||||
> ⚠️ **本目錄是「發生過什麼」的檔案館,不是現行做法**。內容反映當時狀態,其中提及的
|
||||
> 機制可能早已移除(例如 credential 的舊自管金鑰路徑已於 2026-07-20 完全移除)。
|
||||
> 勿依本目錄任何內容操作;現行規範一律以 `.claude/rules/` 為準。
|
||||
|
||||
## 線上事件
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# 2026-05-29 credential 解密失敗(兩個 Worker 的 ENCRYPTION_KEY 漂移)
|
||||
|
||||
> ⚠️ 歷史記錄(2026-07-20 起本文所述機制已完全移除,本文僅供考古,勿依此操作)。
|
||||
> 現行 credential 做法見 `.claude/rules/01-tech-stack.md`「Credential 儲存規範」。
|
||||
|
||||
> **症狀**:`acr recipe test kbdb`(credential 注入)回 HTTP 500,`auth_static_key` 回 `credential kbdb_api_key 解密失敗`
|
||||
> **根因(主)**:`arcrun-auth-static-key` Worker 的 `ENCRYPTION_KEY` secret 跟正本(cypher-executor / CLI 用的那把)值不同、格式也不同(44-char base64 vs 64-char hex)。AES-GCM 用錯 key 必然解密失敗。
|
||||
> **根因(附)**:`component-loader.ts` 用 `res.json().catch(() => res.text())` 讀 response body → body 被讀兩次 → `Body has already been used`。
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# 交付前自測 Checklist(pre-customer)— 2026-06-07
|
||||
|
||||
> ⚠️ 歷史記錄(2026-06-07 當時的清單)。其中 credential 相關步驟所依據的舊自管金鑰機制
|
||||
> 已於 2026-07-20 完全移除,**勿照本文操作**;現行做法見 `.claude/rules/01-tech-stack.md`。
|
||||
|
||||
> 給 **你(人)** 在交給客戶前跑一次的精簡清單,不是給 Haiku 操盤的詳細壓測(那份在
|
||||
> 壓測-recipe-library-2026-06-07.md)。順序照客戶真實旅程。**任一項 ❌ = 不能交付。**
|
||||
> 過關標準都是客觀證據(HTTP 2xx / D1 數字 / 檔案存在),禁口頭過關。
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# 壓測 Test Case — Recipe 公庫/私庫機制 + UUID(2026-06-07 deploy 後)
|
||||
|
||||
> ⚠️ 歷史記錄。文中 credential 相關步驟依據的舊自管金鑰機制已於 2026-07-20 完全移除,
|
||||
> **勿照本文操作**;現行做法見 `.claude/rules/01-tech-stack.md`。
|
||||
|
||||
> 對象:本次上線的 kbdb-base §7.5(公庫/私庫雙向、UUID 身份、市場數據)+ 回歸。
|
||||
>
|
||||
> **操盤模型:全程 Haiku。Haiku 能搞定是「設計目標」不只是壓測手段(richblack 2026-06-07)。**
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
## credential / recipe
|
||||
|
||||
- [[多worker-ENCRYPTION_KEY同步]] — 各 Worker secret put 同份 key,漂移→解密失敗表現為 401/403
|
||||
- [[Recipe-UUID市場模型]] — canonical+uuid+author 多維身份,per-uuid 市場數據
|
||||
|
||||
## kbdb
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
tags: [credential, 部署, 架構決策, 踩坑]
|
||||
gloss: 多個 Worker(auth primitive + cypher-executor)共享 ENCRYPTION_KEY,用 wrangler secret put 手動設進各 Worker secret store,不用 KV。
|
||||
---
|
||||
# 多 Worker ENCRYPTION_KEY 同步
|
||||
|
||||
← [[decisions/00-INDEX]]
|
||||
|
||||
**來源**:`system-dev/wiki/decisions-summary.md`(多 Worker ENCRYPTION_KEY 同步)、`.claude/rules/01-tech-stack.md` 加解密規範
|
||||
**最後更新**:2026-06-27
|
||||
|
||||
## 摘要
|
||||
Auth static_key / Auth service_account / cypher-executor 三個 Worker 都需 ENCRYPTION_KEY 來解密 credential。用各 Worker 的 secret store(非環境變數)存放;初期化時 `acr init` 生成一份 key,用 `wrangler secret put ENCRYPTION_KEY` 各設一次。
|
||||
|
||||
## 重點
|
||||
- **Secret 存儲位置**:各 Worker 的 secret store(Cloudflare 原生機制),不是環境變數、不是 KV。環境變數會洩漏到日誌;KV 的 list 操作可能外洩。
|
||||
- **初始化流程**:`acr init` 生成一份 32 字節隨機 key → 印出一次 → 用戶自己跑 `wrangler secret put ENCRYPTION_KEY --path <path>` 分別設進三個 Worker。
|
||||
- **冪等性問題**:目前 `acr init` 多跑幾次會生成不同 key(不冪等)。長期應改成「init 檢查現有 config → 若存在 key 則重用舊的、否則生成新的」。
|
||||
- **漂移陷阱**:若某個 Worker 的 key 遺漏或與其他 Worker 不同 → credential 解密失敗 → 表現為 401/403(用戶困惑,難debug)。
|
||||
- **驗證方法**:init 完成後做一個 test workflow 打一個認證過的 API(如 gmail),確認三個 Worker 的 key 一致。
|
||||
|
||||
## 實體
|
||||
- **ENCRYPTION_KEY**(加密密鑰)— 32 字節 AES-GCM 密鑰,用來解密用戶的 credential。
|
||||
- **Secret store**(Cloudflare 密鑰存儲)— Worker 的原生機制,用 `wrangler secret put` 設置、runtime 讀取,內容不外洩。
|
||||
- **密鑰漂移**(key drift)— 多個 Worker 持有不同版本的 ENCRYPTION_KEY,導致某些 Worker 解密失敗。
|
||||
- **冪等性**(idempotency)— `acr init` 多次運行應產生同一結果(目前不達成)。
|
||||
- **解密失敗**(decryption failure)— Worker 因 key 不匹配無法解密 credential,表現為 401/403 錯誤。
|
||||
|
||||
## 關聯
|
||||
### 內文知識關係
|
||||
- ENCRYPTION_KEY >> 分散存儲於 >> Secret store
|
||||
- 密鑰漂移 >> 導致 >> 解密失敗
|
||||
- 冪等性 >> 缺乏時 >> 重跑 init 造成 key 不一致
|
||||
### 卡片關係
|
||||
- (相關 memory:`encryption-key-drift-trap` — 解密失敗先比 key 指紋;屬 auto-memory 非 card)
|
||||
@@ -110,32 +110,6 @@ compatibility_flags = [ "nodejs_compat", "global_fetch_strictly_public" ]
|
||||
|
||||
---
|
||||
|
||||
## 多 Worker ENCRYPTION_KEY 同步(2026-05-29)
|
||||
|
||||
**Q:auth_static_key / auth_service_account / cypher-executor 都需 ENCRYPTION_KEY,怎麼保持一致?**
|
||||
|
||||
**決策**:
|
||||
- secret 存在各 Worker 的 secret store(非環境變數,避免洩漏)
|
||||
- `wrangler secret put ENCRYPTION_KEY` 手動設進各 Worker
|
||||
- 初始化:`acr init` 生成,展示一次,user 自己 secret put
|
||||
|
||||
**為什麼不用 KV**:
|
||||
- secret 是敏感內容,不應在 KV 存(會被 list 洩漏)
|
||||
- secret store 是 Cloudflare 的原生機制
|
||||
|
||||
**冪等性**:
|
||||
- `acr init` 多跑幾次,生成不同 key(目前不冪等)
|
||||
- 若要冪等,init 應檢查現有 config → reuse 舊 key
|
||||
|
||||
**避坑**:
|
||||
- init 完成後驗證所有三個 Worker 都有同一份 key
|
||||
- 若某個 Worker 的 key 遺漏或不同 → credential 解密失敗(會表現為 401/403)
|
||||
- 重跑 init 不要覆蓋舊 secret(目前沒有 check,need improvement)
|
||||
|
||||
**詳見**:2026-05-29-encryption-key-drift.md、rule 01 加解密
|
||||
|
||||
---
|
||||
|
||||
## Recipe UUID 模型(kbdb-base §7.5)
|
||||
|
||||
**Q:多作者同 canonical recipe 怎麼並存?**
|
||||
|
||||
@@ -98,26 +98,6 @@ metadata:
|
||||
|
||||
---
|
||||
|
||||
## 6. 多 Worker 共用 ENCRYPTION_KEY 漂移(encryption-key-drift)
|
||||
|
||||
**錯誤模式**:同一個 key 在多個 Worker 的 secret store 中不一致。
|
||||
|
||||
**根因**:
|
||||
- `acr init --self-hosted` 不是幪等的
|
||||
- 用戶重跑 init,key 重新生成或未同步到所有 Worker
|
||||
- 某個 Worker 還用舊 key,解密失敗
|
||||
|
||||
**後果**:
|
||||
- credential 無法解密,workflow 執行失敗(401/403)
|
||||
- 調試難度高,表現為「缺 credential」
|
||||
|
||||
**避坑**:
|
||||
- init 完成後,驗證所有 secret_target_workers(auth_static_key / auth_service_account / cypher-executor)都有同一份 key
|
||||
- 若已部署過,重跑 init 時 **skip secret put**(不要覆蓋)
|
||||
- 或提供「檢查 key 一致性」的端點(未實作)
|
||||
|
||||
---
|
||||
|
||||
## 7. 同 zone 1042(self-hosted cypher 打 auth worker)
|
||||
|
||||
**錯誤模式**:cypher 和 auth worker 同 zone(都是 {sub}.workers.dev),cypher fetch 打 auth 返回 522。
|
||||
|
||||
@@ -252,7 +252,6 @@ metadata:
|
||||
| 4 份 inline http_request host fn 抽共用 helper | 🟡 中 | 待 dedup | http_request/claude_api/kbdb_upsert_block/km_writer 各自複製貼上同段(這次假綠修也是逐份改) |
|
||||
| `arcrun.dev/llms.txt` 404 | 🟡 中 | 未 serve | landing/public 缺檔;GitHub repo 內正常(test/5 走 GitHub 不阻擋) |
|
||||
| MCP account-source | 🟡 中 | 記錄中 | self-hosted MCP 指官方不指自己(§5.2 已知) |
|
||||
| ENCRYPTION_KEY 冪等性 | 🟡 中 | 設計中 | init 多跑生成新 key,無法複用舊 key |
|
||||
| recipe submitted 後沒有 uuid | 🟡 中 | 待驗 | submit-p 應回 uuid,CLI 拿不到 |
|
||||
| ~~KV list 爆量~~ | ✅ 已解 | §8 P0 部署 | cron list→單 key get,1440/日→0(2026-06-09) |
|
||||
| ~~onboarding 缺陷(4 項)~~ | ✅ 已解 | §7.8 P0/P1/P2 + P3 部分 | CLI 1.3.4,Haiku 壓測證實裝+init 不跳過 |
|
||||
@@ -310,7 +309,7 @@ metadata:
|
||||
|
||||
6. [ ] `arcrun.dev/llms.txt` serve(landing/public 補檔)
|
||||
7. [ ] 補 wiki modules/(文件遷移階段一~三已於 2026-06-14 完成)
|
||||
8. [ ] ENCRYPTION_KEY 冪等性、MCP account-source、recipe submit uuid 回傳
|
||||
8. [ ] MCP account-source、recipe submit uuid 回傳
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user