arcrun — AI workflow execution engine (clean history)
Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。 此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在 richblack/arcrun 與本地 backup 分支)。含: - acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe) - recipe push 把關(資料外流提醒 + 打通檢查) - 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1) - CLI / cypher-executor / registry / 完整 SDD Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
# Design: Component Gatekeeping(零件投稿真把關)
|
||||
|
||||
> 2026-05-29。實作 requirements.md 的 R1-R6。
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 方向修正(richblack 2026-05-30):投稿走 GitHub PR,廢 registry self-service
|
||||
|
||||
**零件投稿管道 = GitHub PR,不是 registry submit API。** 理由與影響見下;以下 §0-§9 的 registry submit 設計,
|
||||
凡屬「self-service 投稿管道」者**作廢**,凡屬「把關邏輯」者**搬到 CI(PR check)跑**。
|
||||
|
||||
**為何改:** primitive 極少、未來絕大部分是 recipe → 新增零件是稀有低頻事件,不需 self-service 自動化管道。
|
||||
PR 天然滿足每道閘門:
|
||||
|
||||
| 設計的閘門 | PR 怎麼天然滿足 |
|
||||
|---|---|
|
||||
| G0 人類閘門 | PR 必須有人 merge(richblack approve);AI 偽造不了 GitHub approve |
|
||||
| 舉證「為何不是工作流」 | PR description,review 時看 |
|
||||
| G1 假零件 / G3 純WASI / G4 Gherkin / 覆蓋檢查 / 黃金向量 | **CI(PR check)跑** —— CI 有 tinygo + 能 runtime 跑 wasm,**繞開 CF Workers 不能 runtime 編譯 wasm 的 venue 牆** |
|
||||
|
||||
**§8 衝突釐清:** DECISIONS §8「不依賴 GitHub Actions」指**執行鏈路**(init/push/run/recipe,常態高頻,
|
||||
用戶機器+CF)。**零件投稿是稀有低頻、該由 PR 治理**,用 PR/CI 不違反 §8——反而更對(CI 能跑 wasm,
|
||||
registry Worker 不能)。需在 DECISIONS 補這個區別(待 richblack 確認改穩定文件)。
|
||||
|
||||
**哪些作廢 / 哪些保留:**
|
||||
- ❌ 作廢:registry submit API 當主投稿管道、四路(CLI/MCP/py/js)self-service 投稿、平台端 sandbox 重跑、`acr parts publish` 加人類閘門(投稿不走 CLI 了)。
|
||||
- ✅ 保留並搬 CI:G1 假零件偵測邏輯(detectFakeComponent.ts)、G3 純WASI(wasmImports.ts)、G4 Gherkin 真跑(CI 能跑 wasm)、B 覆蓋檢查、黃金向量人工核對。
|
||||
- ✅ 已 commit 的 registry G0/G1/G3 程式碼**保留不刪**(無害,且 G1/G3 邏輯被 CI 複用),但 registry submit 不再是主管道。
|
||||
- ✅ R5 本機 hook(擋 CC 直接造零件目錄)仍要 —— 它擋的是「繞過 PR 直接改 repo」,與 PR 管道互補。
|
||||
|
||||
**以下 §0-§9 為原 design,閱讀時套用上述修正。**
|
||||
|
||||
---
|
||||
|
||||
## 0. 架構總覽
|
||||
|
||||
### 0.0 範圍:把關跨公共庫 + self-hosted 私人庫(richblack 2026-05-29)
|
||||
|
||||
把關**不是公共庫專屬**。每個 self-hosted 部署有自己的零件庫(自己的 registry Worker)。
|
||||
**加入公共庫或任何 self-hosted 私人庫,都跑同一套把關鏈(G0-G6 + 本機 hook)。**
|
||||
- 實作上天然成立:把關邏輯在 registry Worker code 裡,self-hosted 跑同一份 registry → 把關跟著走,不需公私庫分兩套。
|
||||
- G0 人類閘門在 self-hosted 下,「人類」= 部署擁有者本人(防的是「他的 AI 自作主張把東西做成零件」,不是防他本人;他自己確認 + 舉證即可過)。
|
||||
- 理由:self-hosted 一樣有「自用服務沒驗證就變零件」的風險,且私人庫零件之後可能貢獻回公共。
|
||||
|
||||
### 0.1 把關鏈
|
||||
|
||||
投稿零件的唯一入口是 registry Worker 的 submit。把關鏈(依序,任一失敗即退稿):
|
||||
|
||||
```
|
||||
submit 請求(帶 wasm + contract + 人類確認憑證 + 舉證)
|
||||
│
|
||||
├─ G0 人類閘門(R4) ← 最先擋:沒人類確認 + 舉證 → 403
|
||||
├─ G1 假零件偵測(R2) ← contract/原碼有外部 URL 或 http 子集 → 退稿指回正路
|
||||
├─ G2 size_check(已有)
|
||||
├─ G3 syscall_scan + 純WASI(R3)← 擴充:只准 WASI preview1 + u6u host func 白名單
|
||||
├─ G4 gherkin_tests(R1) ← 真跑 WASM,given→stdin→比對 then_contains
|
||||
├─ G5 cold_start(mock,標未實作)
|
||||
└─ G6 runtime_compat(mock,標未實作)
|
||||
→ 全過 → 派 hash → 寫 KV
|
||||
```
|
||||
|
||||
另一道獨立防線:**本機 hook**(R5),擋 CC 繞過 API 直接在 repo 造零件目錄。
|
||||
|
||||
---
|
||||
|
||||
## 1. G0 人類閘門(R4)— registry submit endpoint
|
||||
|
||||
### 1.1 請求格式增欄
|
||||
submit 請求 body 增兩個欄位:
|
||||
```ts
|
||||
interface SubmitRequest {
|
||||
wasm_base64: string;
|
||||
contract: ComponentContract;
|
||||
human_confirmation?: {
|
||||
confirmed_by_human: true; // 必須為 literal true
|
||||
reason_why_not_workflow: string; // 非空,AI 舉證
|
||||
confirmed_at: string; // ISO timestamp
|
||||
};
|
||||
skip_acceptance?: boolean; // 既有:backfill 用(仍保留)
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 閘門邏輯
|
||||
```
|
||||
若 skip_acceptance(backfill 既有零件)→ 跳過 G0(這些是已驗、已部署的存量,不是新投稿)
|
||||
否則(新投稿):
|
||||
若無 human_confirmation 或 reason_why_not_workflow 空 → 403:
|
||||
"建零件需人類確認。請用 `acr parts publish`(會互動式問你),
|
||||
並說明為何工作流做不到。預設假設工作流能做——先試工作流 / recipe。"
|
||||
記錄 reason_why_not_workflow 進 KV metadata(軌跡可審)
|
||||
```
|
||||
|
||||
### 1.3 四路收斂(CLI / MCP / Python / JS)
|
||||
- 它們建零件都呼叫 registry submit endpoint → G0 在 endpoint,自動四路通管。
|
||||
- **CLI `acr parts publish`**:強制互動式 prompt 問人類「(1) 工作流為何做不到?(2) 確認要建零件?」,把答案組成 `human_confirmation` 送出。非互動環境(AI 直跑)`acr` 偵測 stdin 非 TTY → 拒絕並提示「需人類互動」。
|
||||
- MCP / Python / JS lib:傳 `human_confirmation` 才能成功;它們的 SDK 文件註明此欄位需人類提供。
|
||||
- **誠實限制**(寫進 mindset + 文件):AI 技術上能偽造 `confirmed_by_human:true`。靠 reason 留記錄 + mindset 明示「絕不代替人類確認建零件」+ 軌跡可審,讓偽造成明確越界,不聲稱不可能繞過。
|
||||
|
||||
## 2. G1 假零件偵測(R2)
|
||||
|
||||
新增 `detectFakeComponent(contract, wasmBytes): string | null`:
|
||||
- (a) **外部 URL/domain**:掃 contract 的 description / input_schema / output_schema 文字,及 wasm binary 文字,比對 URL pattern(`https?://`、常見 domain)。命中 → 退稿。
|
||||
- (b) **http_request 子集**:若 contract 宣告只做「打固定 endpoint」(heuristic:description 含「打/呼叫 ... API/endpoint」且 input 有 url-like 欄位且無實質邏輯運算),標記疑似。
|
||||
- 退稿訊息:「偵測到疑似假零件(寫死 endpoint / http 子集)。這該是 API recipe(http_request + 固定設定)或工作流,不是零件。見 DECISIONS §1。」
|
||||
- 排除:`auth_*` primitive(credential 後端,DECISIONS §3b 不適用假零件判準)、`http_request` 自己。
|
||||
|
||||
## 3. G3 純 WASI 把關(R3)
|
||||
|
||||
擴充現有 `scanSyscalls`:
|
||||
- 現況:掃 `FORBIDDEN_SYSCALLS` 黑名單。
|
||||
- 擴充:改為「import 白名單」——解析 wasm import section,確認所有 import module 只屬 `wasi_snapshot_preview1` + `u6u`(host functions)。出現其他 module → 退稿(runtime 鎖定風險)。
|
||||
- 實作:簡易 wasm import section 解析(不需完整 wasm parser,掃 import 段的 module name 字串)。
|
||||
|
||||
## 4. G4 Gherkin 真實作(R1)— **修訂(2026-05-29,richblack review)**
|
||||
|
||||
### 4.0 為何不能在 registry Worker 跑(原設計作廢)
|
||||
原設計假設 registry Worker instantiate 投稿 wasm 跑 Gherkin。**此假設錯誤**:
|
||||
- **Cloudflare Workers 禁止 request-time 編譯 WASM**(`new WebAssembly.Module(bytes)` / `WebAssembly.compile()` 只能 startup 用 bundle 的 module;workers-types 把 `Module` 標 abstract 正反映此限制)。registry 收到的是 runtime 投稿 bytes → 跑不了。
|
||||
- DECISIONS §8:第一期**不依賴 GitHub Actions** → 也不能靠 CI 跑 Gherkin。
|
||||
- 剩下唯一一致 venue = **投稿者本地機器**(有 tinygo + 能跑 wasm,與現有 build 流程同環境)。
|
||||
|
||||
### 4.1 正確設計:Gherkin 在投稿指令本地跑
|
||||
零件投稿走一個**獨立 CLI 指令**(既有指令;「本地或公共都是投稿」):
|
||||
1. 本地 `tinygo build`(或讀已 build 的 .wasm)。
|
||||
2. **本地跑 Gherkin**:對每個 `gherkin_tests[]`,用 Node 的 WebAssembly + 同一份 wasi-shim instantiate wasm,given→stdin→run→比對 then_contains。Node 環境能 runtime 編譯 wasm(不像 CF Workers)。
|
||||
3. 任一 scenario 失敗 → 投稿指令本地就擋下,不送出。
|
||||
4. 通過 → 把**測試結果隨投稿上傳**(見 4.2)。
|
||||
|
||||
`runGherkin.ts`(已寫,用 createWasiShim)邏輯正確,只是**執行 venue 從 registry Worker 改成 CLI(Node)**。registry 端不再跑 Gherkin。
|
||||
|
||||
### 4.2 「平台看得到測試結果」(呼應 §3c:執行者不能驗證自己)
|
||||
投稿 payload 帶 `gherkin_evidence`:每個 scenario 的 `{scenario, given, actual_stdout, passed}`。
|
||||
- registry 存進 KV metadata(軌跡可審)。
|
||||
- 平台看得到**原始 stdout**,不是只看投稿者宣稱的「passed」。
|
||||
- **誠實限制**(同人類閘門):本地跑 + 自報結果,AI 技術上能偽造 actual_stdout。靠軌跡可審 + mindset 明示 + 未來 §3c 的 test/relay(投稿走 relay 讓平台當下親跑,第一期後)補強。第一期是「本地跑 + 上傳證據 + 可審」,不聲稱不可繞過。
|
||||
|
||||
### 4.3 公私庫分流(投稿指令旗標)
|
||||
- 預設投稿 → **私人庫**(self-hosted 自己的 registry)。
|
||||
- `-p` / `--public` → 推**公共庫**。
|
||||
- 兩者都跑同一套把關(§0.0:跨公私庫同一套)。差別只在目標 registry。
|
||||
|
||||
### 4.4 registry 端對應
|
||||
- registry submit 仍跑 G1(假零件)、G3(純WASI)——這兩個是**靜態掃描,不需執行 wasm,CF Worker 可跑**。
|
||||
- G4 Gherkin 的執行移到 CLI;registry 收 `gherkin_evidence` 存證、可選做輕量一致性檢查(evidence 的 scenario 數與 contract.gherkin_tests 對得上、每個 passed=true),但**不重跑**(跑不了)。
|
||||
- G5/G6(cold_start/runtime_compat)維持 unimplemented_steps 標記。
|
||||
|
||||
## 4.5 信任模型與發佈風險(richblack 2026-05-29 定,重要——勿誤讀為零風險)
|
||||
|
||||
**Gherkin 全綠 ≠ 零件安全可發佈。** 把關能驗到什麼、不能驗到什麼,要說清楚:
|
||||
|
||||
### 把關各層各防什麼
|
||||
| 層 | 防得了 | 防不了 |
|
||||
|---|---|---|
|
||||
| G4 Gherkin | 「零件對宣稱的 given 不 work」 | 「Gherkin 寫得避重就輕、只測會過的 case」——投稿者可寫不完整的測試,沒測到的 input 仍可能出錯/惡意 |
|
||||
| G1 假零件 / G3 純WASI | 連外 / 非 WASI / 寫死 endpoint | 沙箱內的邏輯錯誤 |
|
||||
| **純 WASI 沙箱(真正的發佈底氣)** | **框死零件能做的事**:只能 stdin→stdout,無網路 syscall、無檔案系統、無 host 能力(除白名單 host func)→ 就算邏輯有問題或惡意,傷害被沙箱框死 | 沙箱允許範圍內的錯誤輸出 |
|
||||
| 市場機制(§1) | 長尾:別人用了發現不對 → 回報 → 修 | 投稿當下測不到的 |
|
||||
|
||||
**結論:發佈非零風險,是風險可控。** 主要安全保證是**純 WASI 沙箱框死能力**(不是 Gherkin)。Gherkin 驗行為契約、沙箱框死破壞力、市場補長尾,三者合起來讓「發佈陌生人的零件」風險可控到能接受。
|
||||
|
||||
### 信任層級(誰跑 Gherkin 決定可信度,§3c:執行者不能驗證自己)
|
||||
- **第一期**:投稿者**本地跑 + evidence 上傳可審**。AI 技術上能偽造 actual_stdout(它控制本地環境)。**誠實標明:第一期 evidence 可造假**,靠純 WASI 沙箱 + 軌跡可審 + mindset 撐著。
|
||||
- **未來**:平台**自己重編源碼 + 重跑 Gherkin**(投稿者無法造假「跑的結果」)。需要能 runtime 跑 wasm 的 venue——**非 CF Worker(不能 runtime 編譯)、非 CI(§8 不依賴)**——可能是公共庫專屬的 sandbox 服務。列未來,可能擋公共庫「完全可信發佈」。
|
||||
- 再往後:§3c 的 test/relay(投稿走 relay 讓平台當下親跑)。
|
||||
|
||||
## 5. G5/G6 mock 標未實作(R3 誠實)
|
||||
|
||||
- cold_start / runtime_compat 保留 mock,但 **SandboxResult 增 `unimplemented_steps: string[]`**,回傳時明列 `["cold_start","runtime_compat"]`,submit 回應與文件明示「這兩步未實作、未真正驗證」。不回 `success:true` 假裝全綠——回 success 但附 unimplemented 清單。
|
||||
|
||||
## 5.5 黃金向量:人工核對 + B 覆蓋檢查(richblack 2026-05-30 定)
|
||||
|
||||
Claude.ai 建議用「黃金向量 + 把關自己重跑」自動驗收,防放水的 Gherkin。**價值保留,實作降級**,理由:
|
||||
|
||||
- **primitive 極少、未來絕大部分是 recipe**(人類閘門 + 工作流優先把零件擋在源頭)。現役 17 白名單 + cron/platform_crypto,未來極少新增。
|
||||
- 「把關自動重跑向量」是為「零件大量增加」做的規模化基建——但零件不會大量增加 → 為不存在的規模做自動化 = 過度工程(DECISIONS 附錄「會不會累積成債」判準)。
|
||||
- 且「把關自己重跑 wasm」撞 venue 牆(CF 不能 runtime 編譯 wasm,同 §4.0)→ 需平台端 sandbox(第一期沒有)。
|
||||
|
||||
**降級後做法:**
|
||||
- **A 黃金向量 conformance → 人工核對**:黃金向量當「人類閘門時用 CC 核對 primitive 的對照表」。新增 primitive(極稀有)時,人類閘門已要你親自確認,那一刻用 CC 本地跑向量核對(本地有 tinygo + 能跑 wasm,繞開 venue 牆)、人工凍結。**不做機器自動重跑。**
|
||||
- **B 覆蓋檢查 hook → 現在做(純靜態、不可造假、成本低、價值與零件數無關)**:靜態 parse contract:`input_schema` 每個 required 欄位至少出現在一個 Gherkin given、`output_schema` 每個欄位至少被一個 then_contains 斷言。缺 → exit 2 指出漏哪個欄位。擋「只測 happy path、不碰宣告過的行為面」。
|
||||
- **初始向量來源(信任根:寫向量≠寫實作)**:另起 session 從 contract 語義寫、不看實作原碼(primitive 語義客觀如 add(2,2)=4)。人工核對用,不急、新增 primitive 時逐個補,不必 21 個一次到位。
|
||||
- 殘留(誠實):向量/覆蓋檢查擋不住「列出的 case 全對、沒列到的 case 錯」。交給「用」——出 bug 補進向量,永不 regress。是會長大的網,非設一次完美。
|
||||
|
||||
## 6. R5 白名單 + 本機 hook
|
||||
|
||||
- `registry/MVP_COMPONENTS.txt`:一行一個白名單 canonical_id(現役 22 個)。
|
||||
- `pre-write-guard.sh` 增規則:寫入 `registry/components/{name}/...` 且 `{name}` 不在 MVP_COMPONENTS.txt → exit 2,訊息「新增零件需走 submit API 人類閘門,不可直接造 repo 目錄」。
|
||||
- `pre-bash-guard.sh` 增規則:`mkdir .../registry/components/{白名單外}` → exit 2。
|
||||
- `.ts` 偵測現有 hook 已做(rule 1.1)。
|
||||
- **B 覆蓋檢查**(5.5):可放 registry submit 的靜態驗收(不需跑 wasm,CF 可跑)或 pre-write hook,擋宣告過的欄位沒被 Gherkin 測到。
|
||||
|
||||
## 7. 範圍邊界
|
||||
|
||||
- **動 registry TS**(sandboxAcceptance / submitComponent / routes / types)+ **CLI**(acr parts publish,既有指令)+ **hook**。
|
||||
- 不動 cypher-executor 執行路徑、不動既有零件 wasm。
|
||||
- backfill 路徑(skip_acceptance)保持可用,不被新閘門擋(存量零件不需人類閘門)。
|
||||
- CLI/MCP/Python/JS 四路:本期至少做 CLI `acr parts publish` + registry endpoint 強制;MCP/Python/JS 補 `human_confirmation` 欄位支援(薄)。
|
||||
|
||||
## 8. 驗收標準
|
||||
|
||||
- 投一個寫死 endpoint 的假零件 → G1 退稿(終端輸出)。
|
||||
- 投一個 `.ts` 進 registry/components → hook exit 2。
|
||||
- 投一個白名單外的新零件目錄(本機造)→ hook exit 2。
|
||||
- 無 human_confirmation 的 submit → 403。
|
||||
- 帶 human_confirmation + 過 Gherkin 的真零件 → 通過、寫 KV、reason 留 metadata。
|
||||
- Gherkin given/then 對真零件跑綠;故意改壞 then_contains → 退稿。
|
||||
- cold_start/runtime_compat 在回應裡列入 unimplemented_steps(不假綠)。
|
||||
|
||||
## 9. 決議(richblack 2026-05-29 design review 定)
|
||||
|
||||
- **Q1 → 消解**:Gherkin 測的零件**永遠是封閉邏輯(框架),不連外**。任何要加外部 URL 的東西按定義就是 recipe,不是零件——這種「連外零件」根本不該存在(會被 G1 假零件偵測擋下、降成 recipe)。所以 G4 Gherkin 只跑不需 host function 的封閉邏輯零件,**不需要 mock host func、不需要 skip 機制**。零件用 `u6u.http_request` 連外 = G1 直接退稿。
|
||||
- **Q2 → 兩者都硬擋**:(a) contract/原碼有具體外部 URL/domain → 硬退稿;(b) 宣告能力是 http_request 子集 → 也硬退稿。理由:與 Q1 一致——零件不該連外,這兩個 pattern 都是「該是 recipe 的東西偽裝成零件」,硬擋無誤殺顧慮(真的要連外就去做 recipe)。
|
||||
- **Q3 → submit 過閘門後自動 append**:人類閘門通過 + 驗收綠的零件,submit 成功時自動把 canonical_id append 進 `MVP_COMPONENTS.txt`。白名單反映「已正當投稿的零件」,不需手動維護。本機 hook 讀此檔擋「白名單外的直接造目錄」。
|
||||
|
||||
### Q1 連帶結論(強化 G1)
|
||||
既然「零件不連外、連外即 recipe」是硬規則,G1 假零件偵測 = G4 Gherkin 的前置守門:
|
||||
G1 擋掉所有連外/http 子集的投稿 → 能進到 G4 的必然是封閉邏輯零件 → Gherkin 必然不需 host func。
|
||||
兩道閘門邏輯自洽。
|
||||
@@ -0,0 +1,105 @@
|
||||
# Design 補充:recipe 入庫把關(push 那一刻)
|
||||
|
||||
> 2026-06-01。本檔是 `component-gatekeeping/design.md` 的單檔補充(規則 02 §4.3 允許)。
|
||||
> **狀態:待 richblack review 才動 code(這是 change)。**
|
||||
> 背景:richblack 2026-06-01 方向修正(見下「方向定調」)+ docs/HANDOFF-self-host-harness.md。
|
||||
|
||||
---
|
||||
|
||||
## 0. 方向定調(richblack 2026-06-01)
|
||||
|
||||
把關的對象與位置整個移位了,先講清楚才不會做歪:
|
||||
|
||||
### 0.1 零件這條路 = 封鎖,且「不再有假零件這件事」
|
||||
- 零件由維護者(richblack)管理,**CC 不能自製/修改零件**。
|
||||
- 封鎖機制 = **零件投稿走 GitHub PR + 人 merge**(DECISIONS §8 / design 頂部方向修正)。
|
||||
AI 偽造不了 GitHub approve,這是天然人類閘門。CC 在本機產不出能進庫的零件。
|
||||
- → 因此「擋假零件」(原 W1)這件事**不存在了**:CC 根本造不出零件,workflow 引用 recipe
|
||||
(如 `component: kbdb_get`)是**合法且未來唯一的擴充方式**,不該被當假零件擋。
|
||||
|
||||
### 0.2 零件 PR 把關 = 人工,不自動化(除非未來爆量)
|
||||
- richblack 2026-06-01 澄清 BACKLOG 步驟5「不做 hook/自動化」的真意:
|
||||
**零件真實數量很少、絕大多數是 recipe** → 原本想做的「驗證零件 PR 的自動化機制」
|
||||
(CI 跑 Gherkin/沙箱/向量)**不需要**,量少 → **有 PR 進來就人工檢查**。
|
||||
**只有零件開發量變很大時**才回頭想自動化。
|
||||
- → component-gatekeeping 的 G4/覆蓋檢查/黃金向量自動化 = **不做**(人工取代),與既有 tasks 收尾一致。
|
||||
|
||||
### 0.3 真正的 harness 把關 = recipe 入庫(push)那一刻
|
||||
CC 唯一能擴充的是 recipe。recipe 一律用「**推(push)**」,**自有庫與公共庫同一套指令**。
|
||||
把關依庫別分強度:
|
||||
|
||||
| 庫別 | 能做到的把關 | 機制 |
|
||||
|---|---|---|
|
||||
| **自有庫(self-hosted)** | 只能**提醒**(無法在別人機器強制) | (1) 資料外流提醒 (2) 打通檢查 |
|
||||
| **公共庫** | 維護者機制**檢核實際打通、真收到成功回傳** | PR/CI relay(DECISIONS §3c,第一期後)|
|
||||
|
||||
---
|
||||
|
||||
## 1. 自有庫 push 把關(self-hosted,第一期做)
|
||||
|
||||
`acr recipe push` 的兩個提醒。**提醒級 = 告知 + 需人類明示同意,不硬擋**(self-hosted 是用戶自己的庫,
|
||||
他同意後就是他的責任 — mindset §6 / data-exfil-warning 既有原則)。
|
||||
|
||||
### 1.1 資料外流提醒(W2.2)
|
||||
- **觸發**:push 的 recipe / 或部署的 workflow 會讓「資料對外可見」——主要是產生**對外可被呼叫的 webhook**
|
||||
(`POST /webhooks/named/...` 對外 trigger URL),或 recipe 把本地資料 POST 到外部服務。
|
||||
- **行為**:CLI 印明確警示「這個動作會讓 X 對外界可見/可呼叫,確認要繼續嗎?」→ 需人類明示同意(y/N)。
|
||||
非 TTY(AI 直跑)→ 拒絕,提示「需人類確認」(mindset §7:絕不代替人類做暴露確認)。
|
||||
- **與既有 data-exfil-warning 的關係**:已有 API 層 + pre-bash hook(commit 51d40ee 等)。
|
||||
本項確認**涵蓋 recipe push 這條路徑**;若已涵蓋則只補文件,若沒涵蓋則補上 push 路徑的提醒。
|
||||
- **誠實限制**:AI 技術上能偽造 exposure_consent。價值是法律歸責 + 軌跡可審,不聲稱不可繞過(mindset §7)。
|
||||
|
||||
### 1.2 打通檢查(W2.3)
|
||||
- **目的**:recipe 是「指向外部 API 的指針」,正確性一半在「打不打得通」(DECISIONS §1 recipe 驗收標準 = 2xx)。
|
||||
- **行為**:push 時(或 push 後)對 recipe 的 endpoint **實打一次**,回報 HTTP status。
|
||||
- 2xx → 「✓ recipe 打通(HTTP 200)」
|
||||
- 4xx/5xx → 「⚠️ recipe 未打通(HTTP 401/404/...)」+ 誠實標原因(如「缺 credential → 先 acr creds push」)
|
||||
- 連不上 → 「⚠️ 無法連線」
|
||||
- **self-hosted 是提醒級**:打不通**不硬擋 push**(用戶可能就是要先 push 再設 credential),只如實回報。
|
||||
- **誠實**(mindset §7):缺 credential 打不到 2xx 就誠實標「未驗收:缺 X」,不 mock 充綠燈。
|
||||
|
||||
### 1.3 動到的檔案(待 review 後)
|
||||
| 檔案 | 動作 |
|
||||
|---|---|
|
||||
| `cli/src/commands/recipe.ts` | push 流程加 (1) 資料外流提醒 prompt (2) 打通檢查(實打 endpoint 回報 status) |
|
||||
| `.claude/hooks/*`(如需)| 確認 data-exfil pre-bash hook 涵蓋 recipe push;缺則補 |
|
||||
|
||||
**不動**:cypher-executor 執行路徑、零件、credential 解密邏輯。
|
||||
|
||||
---
|
||||
|
||||
## 2. 公共庫 push 把關(第一期後)
|
||||
|
||||
- recipe 進公共庫 = 別人會用 → 需維護者機制檢核「**實際打通、真收到成功回傳**」(不是投稿者自報)。
|
||||
- 機制:DECISIONS §3c 的 **test/relay**——push 公共庫走 relay,維護者當下親見真實打通記錄
|
||||
(執行者不能驗證自己,§7 閉環)。
|
||||
- **範圍**:依賴公共庫 + relay 基建,**第一期不做**(第一期是 self-hosted + 提醒級)。
|
||||
- 本檔只記框架,第一期不實作。
|
||||
|
||||
---
|
||||
|
||||
## 3. 同一套指令、不同把關強度的切分(W2.4)
|
||||
|
||||
- `acr recipe push`(自有庫,預設)→ §1 提醒級。
|
||||
- `acr recipe push --public`(公共庫,未來)→ §2 relay 檢核級。
|
||||
- 同一指令、旗標分流(呼應 design §4.3 公私庫分流:`-p`/`--public`)。
|
||||
- 第一期只實作預設(自有庫)路徑。
|
||||
|
||||
---
|
||||
|
||||
## 4. 驗收標準(客觀證據,mindset §7)
|
||||
|
||||
第一期(自有庫提醒級):
|
||||
1. `acr recipe push` 一個會產對外 webhook 的東西 → CLI 印資料外流警示 + 要人類同意;非 TTY → 拒絕。
|
||||
2. `acr recipe push` 一個 endpoint 可達的 recipe → 打通檢查回報「✓ HTTP 2xx」。
|
||||
3. `acr recipe push` 一個缺 credential 的 recipe → 回報「⚠️ 未打通:缺 credential」(誠實,不假綠),但仍允許 push。
|
||||
4. 確認 workflow 引用 recipe(`component: kbdb_get`)**不再被任何 validate 步驟當假零件擋**(W1 已作廢)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 與既有 SDD 的一致性確認(無新矛盾)
|
||||
|
||||
- 不動「零件投稿走 PR + 人工檢查」(§0.1/0.2,與 design 頂部方向修正、DECISIONS §8 一致)。
|
||||
- 不重啟「零件 PR 自動化把關」(§0.2,與 BACKLOG 步驟5 真意一致)。
|
||||
- 資料外流提醒延續既有 data-exfil-warning 原則(mindset §6),只確認涵蓋 recipe push 路徑。
|
||||
- 打通檢查 = recipe 驗收標準 2xx 的落地(DECISIONS §1)。
|
||||
@@ -0,0 +1,53 @@
|
||||
# Requirements: Component Gatekeeping(零件投稿真把關)
|
||||
|
||||
> 2026-05-29 建立(richblack 確認)。對應第一期 BACKLOG 步驟 4(補零件庫真把關)+ 步驟 5(人類閘門 + 白名單 hook)。
|
||||
> 判準源:DECISIONS.md §1(工作流是 default / 建零件人類閘門 / ABC 三管齊下)、§7(讓 AI 不做歪三層機制 + 閉環)、§3c/§7(禁假綠)。
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
第一期要把「零件投稿」從「無審核」變成「真的會擋」的把關。現況:
|
||||
- `registry/src/actions/sandboxAcceptance.ts`:size_check / syscall_scan 已實作;cold_start / gherkin_tests / runtime_compat 是 `return null` mock。
|
||||
- `submitComponent.ts`:跑 sandboxAcceptance → 派 hash → 寫 KV。無假零件偵測、無人類閘門。
|
||||
- 風險(DECISIONS):CC 把自用服務(通訊錄/帳本)做成零件進公共庫 → 全生態能打 → 機密外洩。
|
||||
|
||||
## 需求
|
||||
|
||||
### R1 — Gherkin 驗收真實作(取代 mock)
|
||||
- `runGherkinTests` 要真的跑零件 WASM:對每個 `gherkin_tests[]` 的 given → 餵 stdin → 比對 stdout 是否 `then_contains`。
|
||||
- 失敗 → 退稿,回明確 reason + guide anchor。
|
||||
- recipe 不適用 Gherkin(DECISIONS §1:recipe 驗收 = 2xx);本需求只針對 WASM 零件投稿。
|
||||
|
||||
### R2 — 假零件偵測(退稿並指回正路)
|
||||
依 DECISIONS §1 判準,投稿零件若滿足任一,退稿:
|
||||
- (a) contract 或(可得的)原碼出現具體外部服務 URL / domain
|
||||
- (b) 宣告能力是 http_request 子集(打某固定 endpoint)
|
||||
退稿訊息要指回正路:「這該是 recipe / 工作流,不是零件」。
|
||||
|
||||
### R3 — 純 WASI preview1 / 零宿主依賴把關
|
||||
- 擴充 syscall 掃描:確認零件只依賴 WASI preview1 + u6u host functions 白名單,無其他宿主特定依賴(避免 runtime 鎖定債,DECISIONS §4)。
|
||||
- 冷啟動 / runtime 相容兩步可暫留 mock,但**明確標「未實作」**,不可假裝通過(§3c/§7 禁假綠)。
|
||||
|
||||
### R4 — 建零件的人類閘門(核心,BACKLOG 步驟 5 強化規格)
|
||||
- **把關點 = 建立零件的 API 本身**(registry submit endpoint),不是寫檔案。CLI / MCP / Python lib / JS lib 四路全收斂到這關。
|
||||
- submit 預設**拒絕**,除非請求帶:
|
||||
- (a) 人類已確認憑證(CLI `acr component create` 強制互動式問人類,AI 非互動環境生不出)
|
||||
- (b) 舉證 `reason_why_not_workflow`(AI 須證明工作流為何做不到;舉證責任在 AI,預設假設工作流能做)
|
||||
- 缺 → 403 + 指回正路(先試工作流)。
|
||||
- 誠實限制:沒技術能 100% 防 AI 假冒人類確認;靠閘門 + 舉證留記錄 + mindset 明示「絕不代替人類確認」+ 軌跡可審計,讓假冒成明確越界。
|
||||
|
||||
### R5 — 白名單 + 本機 hook 兜底
|
||||
- `MVP_COMPONENTS.txt` 白名單檔。
|
||||
- pre-write / pre-bash hook:CC 直接在 `registry/components/{白名單外新名}/` 造目錄或 mkdir → exit 2(擋繞過 API 直接改 repo 等 CI 部署的旁門)。
|
||||
- pre-write hook:`registry/components/` 下出現 `.ts`(非 AssemblyScript)→ exit 2(現有 hook 已部分做)。
|
||||
|
||||
### R6 — 不限制自由
|
||||
- 不做「audience 宣告 / 禁止自用進公共庫」式的限制(DECISIONS:別人要建零件是他的自由)。
|
||||
- 唯一硬約束:零件 = 只打一個 endpoint 的薄殼。閘門是「要建得先說服人 + 舉證」的摩擦,非禁止。
|
||||
- arcrun 不做授權判斷(能否打通由發 key 的服務裁決)——把關針對「是否該是零件」,不針對「誰能打哪個 API」。
|
||||
|
||||
## 非目標
|
||||
- Phase 5 用戶自製零件 R2 上傳(未啟用)。
|
||||
- registry KV schema 大改(用既有結構)。
|
||||
- 完整的 audit trail 系統(DECISIONS §7 事後機制第一層,另議)。
|
||||
@@ -0,0 +1,102 @@
|
||||
# Tasks: Component Gatekeeping
|
||||
|
||||
> 對應 design.md。每完成一個 task 立刻標 [x],不批次。
|
||||
> Design 已 richblack 確認(2026-05-29,含 Q1-Q3 決議)。
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 收尾狀態(2026-05-30,方向修正後)
|
||||
|
||||
投稿改走 **GitHub PR**(廢 registry self-service,見 design 頂部「方向修正」)。本 SDD 收尾於:
|
||||
- **已完成且 commit**:G1(detectFakeComponent)、G3(wasmImports)、G5/G6(unimplemented_steps)、
|
||||
G0 registry 人類閘門(保留不刪)。測試 15 綠。
|
||||
- **改去向**:G4 Gherkin / 覆蓋檢查 → 未來接 CI PR check(CI 能跑 wasm)。G1/G3 邏輯可複用。
|
||||
- **不做**:CI PR check(richblack:人工 review 就夠,primitive 極少)、R5 本機 hook
|
||||
(PR/merge + G1 + 沙箱已防「未經同意變公共零件」,hook 過度工程)、registry self-service、
|
||||
acr parts publish 加閘門、平台 sandbox 重跑。
|
||||
- **黃金向量**:人工核對(另起 session 從語義寫),不急、不機器自動化。
|
||||
- **轉出範圍**:真正的裸奔風險在「資料外流」(recipe/webhook 把資料送出去),不分公私庫
|
||||
→ 另開新 SDD「資料外流警示」(API 層警示 + AI 動手前 hook)。用戶 API 保護(入站認證)
|
||||
+ recipe/part/function 架構釐清 → 記 BACKLOG 待決策。
|
||||
|
||||
---
|
||||
|
||||
## G1 假零件偵測(R2,Q2=兩者硬擋)
|
||||
- [x] 1.1 `registry/src/actions/detectFakeComponent.ts`:(a) 外部 URL/domain 偵測(掃 contract 文字 + wasm binary 文字)硬擋;(b) http_request 子集偵測硬擋
|
||||
- [x] 1.2 排除 `auth_*` primitive 與 `http_request` 自己
|
||||
- [x] 1.3 接進 sandboxAcceptance 步驟鏈(fake_component_scan 為第一步)
|
||||
- [x] 1.4 退稿訊息指回正路(「這該是 recipe/工作流」)
|
||||
|
||||
## G3 純 WASI 把關(R3)
|
||||
- [x] 3.1 `wasmImports.ts` 解析 wasm import section,取出所有 import module name(已對真實零件驗證)
|
||||
- [x] 3.2 白名單:只准 `wasi_snapshot_preview1` + `u6u`;其他 module → 退稿
|
||||
- [x] 3.3 接進 scanSyscalls(白名單為主,黑名單為次)
|
||||
|
||||
## G4 Gherkin 真實作(R1)— venue 修訂:CLI 本地跑,非 registry(design §4 修訂)
|
||||
> CF Worker 不能 runtime 編譯 wasm + §8 不依賴 CI → Gherkin 在投稿指令本地(Node)跑。
|
||||
> 在第一段(tinygo build→wasm 之後)測,跟 worker 無關。registry 只存 evidence 不重跑。
|
||||
- [x] 4.1 `runGherkin.ts`(createWasiShim 跑 wasm,邏輯正確)—— 但 venue 要從 registry 改 CLI
|
||||
- [ ] 4.2 回退 sandboxAcceptance:registry 不跑 Gherkin(移除 await runGherkin),改回靜態步驟
|
||||
- [ ] 4.3 Gherkin 邏輯搬到 CLI 投稿指令(Node 環境 instantiate wasm)
|
||||
- [ ] 4.4 投稿 payload 帶 gherkin_evidence(scenario/given/actual_stdout/passed),registry 存 metadata 可審
|
||||
- [ ] 4.5 誠實標明第一期 evidence 可造假(mindset + 文件);平台重跑列未來
|
||||
- [ ] 4.6 投稿指令(暫名 acr component submit)+ 公私庫分流(-p 公共)— 新 CLI 工程
|
||||
|
||||
## G5/G6 誠實標未實作(R3 禁假綠)
|
||||
- [x] 5.1 SandboxResult 增 `unimplemented_steps: string[]`
|
||||
- [x] 5.2 cold_start / runtime_compat 列入 unimplemented_steps,submit 回應明示
|
||||
|
||||
## G0 人類閘門(R4,核心)
|
||||
- [x] 0.1 submit 請求增 `human_confirmation`(SubmitOptions in submitComponent.ts)+ route 解析(multipart/JSON 皆支援)
|
||||
- [x] 0.2 submit 邏輯:非 skip_acceptance 的新投稿,無 human_confirmation/空 reason → gateError(指回正路)
|
||||
- [x] 0.3 human_confirmation + gherkin_evidence 寫進 KV metadata(軌跡可審)
|
||||
- [ ] 0.4 CLI `acr parts publish`(既有指令):互動式問人類(工作流為何做不到 + 確認),非 TTY 拒絕
|
||||
- [ ] 0.5 MCP / Python lib / JS lib 補 human_confirmation 欄位支援(薄)
|
||||
- [ ] 0.6 誠實限制寫進 mindset Skill(步驟 7)+ SDK 文件
|
||||
|
||||
> 命名修正(2026-05-29):投稿走**既有** `acr parts publish`(cli/src/commands/parts.ts),
|
||||
> 非另建 acr component create(符合「修改現有不重建」)。G0-CLI(0.4)與 G4-CLI 合併在此指令做。
|
||||
|
||||
## R5 白名單 + 本機 hook
|
||||
- [ ] 5.3 `registry/MVP_COMPONENTS.txt`(現役 22 個 canonical_id)
|
||||
- [ ] 5.4 submit 過閘門成功 → 自動 append canonical_id 進白名單(Q3)
|
||||
- [ ] 5.5 pre-write-guard.sh:寫 `registry/components/{白名單外}/` → exit 2
|
||||
- [ ] 5.6 pre-bash-guard.sh:mkdir `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 relay,DECISIONS §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
|
||||
- [ ] V3 本機造白名單外零件目錄 → hook exit 2
|
||||
- [ ] V4 無 human_confirmation 的 submit → 403
|
||||
- [ ] V5 帶 human_confirmation + 過 Gherkin 真零件 → 通過 + reason 留 metadata + 白名單 append
|
||||
- [ ] V6 故意改壞 then_contains → Gherkin 退稿
|
||||
- [ ] V7 回應含 unimplemented_steps(cold_start/runtime_compat 不假綠)
|
||||
Reference in New Issue
Block a user