feat(self-hosted): acr init --self-hosted installer + recipe push 把關 + commit 部署 wasm

讓任何 CC 用自己的 CF 帳號一鍵 self-host arcrun(戰法轉 self-hosted 開源)。

Task 1 — acr init --self-hosted installer(用戶只給 CF Account ID + token,其餘自動):
- cli/src/lib/cf-api.ts: CfAccountClient(驗 token / 建 KV 冪等 / 建 R2 / 查 workers.dev subdomain)
- cli/src/lib/deploy.ts: 從 GitHub codeload tarball 拉部署物 → 注入用戶 KV id → wrangler deploy
  (tier1 component-builds 先、tier2 cypher-executor/registry 後;部分失敗誠實回報不假綠)
- cli/src/lib/api-recipe-seeds.ts: 10 個現役 API recipe 種子(KBDB 採 Supabase 模式)
- cli/src/commands/init.ts: initSelfHosted() 改寫成 installer 流程
- cli/src/commands/update.ts: acr update(拉新 ref 重部署)
- cypher-executor/scripts/seed-api-recipes.ts: prod 補灌腳本

Task 2 — recipe 入庫把關(封鎖自製零件後,CC 唯一能擴充的是 recipe):
- cli/src/commands/recipe.ts: 新增 probeRecipeEndpoint 打通檢查(提醒級不硬擋,
  含模板誠實說明待 run 才知,401/403 標多半缺 credential 非 bug)
- 資料外流提醒沿用既有 obtainExposureConsent(非 TTY 拒絕)

部署物產製:commit 預編譯 wasm 進 repo(推翻 rule 05「wasm 不 commit」):
- .gitignore: 放行 .component-builds/**/component.wasm(registry 中間產物仍排除)
- 只 commit 19 個正當零件 wasm;claude_api / km_writer / kbdb_upsert_block 排除
  (非薄殼、是把工作流硬塞進零件,違反 DECISIONS §1,待降級)
- rule 05 同步記錄此慣例變更 + 膨脹 trade-off

SDD: sdk-and-website/self-hosted-init.md(installer 定案)、
     component-gatekeeping/recipe-push-gatekeeping.md(recipe 把關)
README 重寫成單一 self-hosted 路徑。CLI typecheck exit 0。

未完(待 richblack):push 此 commit 到 GitHub 後 codeload 才拿得到 wasm;
用第二 CF 帳號端對端驗收 acr init --self-hosted。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 18:44:41 +08:00
parent 51d40ee515
commit fb2d0b0c2d
35 changed files with 1448 additions and 224 deletions
@@ -63,6 +63,35 @@
- [ ] 5.5 pre-write-guard.sh:寫 `registry/components/{白名單外}/` → exit 2
- [ ] 5.6 pre-bash-guard.shmkdir `registry/components/{白名單外}` → exit 2
## W1 ~~CLI workflow validate 擋假零件式 component 名~~2026-06-01 作廢,方向修正)
> **作廢原因(richblack 2026-06-01**:「擋假零件」這件事不再存在——因為**自製/修改零件的路
> 已被封鎖**(CC 根本造不出零件),workflow 引用 recipe(如 component: kbdb_get)是**合法且
> 未來唯一的擴充方式**,不該被當「假零件」擋。把關點從「workflow validate」**移到 recipe 入庫
> push)那一刻**。已動的 yaml-parser.ts `LEGAL_PRIMITIVES`/`findSuspectComponents` 已回退。
> 取而代之 → 見 W2。
## W2 封鎖自製零件 + recipe 入庫把關(2026-06-01 新方向)
> richblack 2026-06-01 定調:
> - 零件由維護者管理,**CC 不能自製/修改零件**(hook + CLI 拒絕)→ 不再有「假零件」。
> - CC 唯一能擴充的是 **recipe**。recipe 一律用「推(push)」,**自有庫與公共庫同一套指令**。
> - 把關依庫別分強度:
> - **自有庫(self-hosted**:只能**提醒**(無法在別人機器強制)。兩個提醒:
> (1) 資料外流提醒——某動作會讓外界看到你的東西(如 workflow 產對外 webhook),同意後是他的責任;
> (2) 打通檢查——查他要打的 API 是否打得通(2xx)。
> - **公共庫**:由維護者機制檢核「實際打通、真收到成功回傳」(PR/CI relayDECISIONS §3c,第一期後)。
> 屬 change,需先寫 design 給 richblack review 才動 code。本節先記框架。
- [x] W2.1 封鎖自製零件 — **釐清完成(richblack 2026-06-02**:靠「零件投稿走 GitHub PR + 人 merge」
天然閘門(DECISIONS §8)。BACKLOG 步驟5「不做 hook」真意 = 零件少、不為零件 PR 蓋自動化把關
(量少人工檢查;爆量才回頭想),**不是**不阻止自製。無矛盾,不需新做 hook。
- [x] W2.2 `acr recipe push` 資料外流提醒 — **既有實作已涵蓋**recipe.ts:70-79 `obtainExposureConsent`
exposure-warning.ts:互動打資源名確認、非 TTY 拒絕、首次問記住)。data-exfil-warning SDD 已做,確認涵蓋 recipe push 路徑。
- [x] W2.3 `acr recipe push` 打通檢查 — **新增** `probeRecipeEndpoint`recipe.ts):push 成功後實打 endpoint
回報 2xx/⚠。提醒級不硬擋;endpoint 含 {{模板}} → 誠實說明待 run 才知;401/403 → 標「多半缺 credential,非 recipe bug」(不假綠,mindset §7
- [ ] W2.4 公共庫 push--public= 維護者 relay 檢核(DECISIONS §3c)— 第一期後,本期只做自有庫提醒級
## 驗收(design §8
- [ ] V1 投寫死 endpoint 假零件 → G1 退稿(終端輸出)
- [ ] V2 投 `.ts` 進 registry/components → hook exit 2