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,117 @@
|
||||
# Design: 資料外流警示(Data Exfiltration Warning)
|
||||
|
||||
> 2026-05-30。實作 requirements.md。**本 design 需 richblack review 後才動 code。**
|
||||
> 觸發策略(richblack 定):**只在「資料變成可被外部呼叫」時問**(暴露面),不管「我去打別人 API」(出站,高頻低風險)。
|
||||
|
||||
---
|
||||
|
||||
## 0. 核心定義:什麼是「資料變成可被外部呼叫」
|
||||
|
||||
警示的觸發點 = 一個動作**讓某份資料 / 能力變成「別人能呼叫得到」**。這是真正的裸奔動作。
|
||||
**不觸發**:「我自己的 workflow 去打別人的 API」(出站)——那是我主動用別人服務,不是把我的東西開放出去。
|
||||
|
||||
### 哪些動作屬於「變成可被外部呼叫」(要警示)
|
||||
| 動作 | 為何是暴露 |
|
||||
|---|---|
|
||||
| 部署 webhook trigger(`acr push` workflow → 可被 POST 觸發) | workflow 變成一個對外可呼叫的 endpoint。誰打它就能跑它、拿它的輸出 |
|
||||
| recipe 貢獻到公共庫(未來飛輪項) | recipe(含 endpoint 設定)變成全生態可見可用 |
|
||||
| 把 workflow / recipe 的可見性改為 public(若未來有此欄位) | 同上 |
|
||||
|
||||
### 哪些動作**不**觸發(避免盲目按 yes)
|
||||
- `acr run`(本機跑,不暴露)
|
||||
- `acr recipe push`(存私人 KV,綁 api_key,只有自己 + 自己的 workflow 用——**不是**對外暴露)
|
||||
- ⚠️ 待 design review 確認:recipe push 現況是私人的,**不暴露**。除非未來加「公共」旗標才觸發。
|
||||
- workflow 裡「打別人 API」的 http 節點(出站,不暴露我的資料給別人呼叫)
|
||||
- 查詢類、creds push(上傳加密 credential 是保護不是暴露)
|
||||
|
||||
### 灰色地帶(design review 要定)
|
||||
- **webhook trigger 現況**:要 `X-Arcrun-API-Key`(owner 的 key)才能打 → 嚴格說「只有我能打」,不算對全世界暴露。
|
||||
但:(a) key 一旦外流就全開;(b) 用戶可能不知道「部署 webhook = 開了一個 endpoint」。
|
||||
→ **是否警示 webhook 部署?** 傾向「是」,因為用戶可能不知情它變成 endpoint,且這是「把 workflow 變 API」的那一步(richblack 最早的風險點)。
|
||||
|
||||
## 1. 兩道防線
|
||||
|
||||
### 1a. hook(防在前,AI 動手當下)
|
||||
AI 在本機寫「會變成可被外部呼叫的東西」前,hook 警告 + 要人類確認。可偵測的訊號:
|
||||
- 寫 workflow YAML 含 webhook trigger / 對外觸發設定。
|
||||
- 跑 `acr push`(部署 webhook)、未來的 recipe 公共貢獻指令。
|
||||
- pre-bash / pre-write hook 偵測這些 → 輸出警示「這會把 X 變成可被外部呼叫,需人類確認」。
|
||||
- **誠實限制**:hook 偵測的是「動作形態」(部署 webhook),不是「資料是否敏感」(機器判不準)。
|
||||
|
||||
### 1b. API 層(防在後,真的暴露前)
|
||||
暴露動作打到 server(webhook 部署 endpoint / 未來公共貢獻 endpoint)時,server 要求帶
|
||||
「人類已確認暴露」的明示旗標,沒帶 → 拒絕 + 提示。與 component-gatekeeping 的 human_confirmation 同模式:
|
||||
```ts
|
||||
exposure_confirmation?: {
|
||||
confirmed_by_human: true;
|
||||
understood_exposure: string; // 人類說明「我知道這會把什麼開放給誰」
|
||||
confirmed_at: string;
|
||||
}
|
||||
```
|
||||
缺 → 拒絕,訊息:「部署 webhook = 開一個對外可呼叫的 endpoint。確認你知道這會暴露 [workflow 名]
|
||||
的能力/輸出?用 `acr push --confirm-exposure` 並說明。」
|
||||
|
||||
### 為何兩道都要
|
||||
- 只有 hook:AI 可繞過 CLI 直接打 server API → API 層補。
|
||||
- 只有 API 層:AI 已經寫好暴露的東西才在送出時被擋,浪費 + 用戶較晚看到 → hook 提前。
|
||||
- 同 component-gatekeeping 的雙層精神。
|
||||
|
||||
## 2. 警示要讓人看得懂(R1)
|
||||
|
||||
不是「確認嗎 Y/N」,是說清楚風險:
|
||||
```
|
||||
⚠️ 這個動作會把 workflow "contacts_lookup" 變成可被外部呼叫的 endpoint:
|
||||
https://cypher.arcrun.dev/webhooks/named/contacts_lookup/trigger
|
||||
|
||||
任何持有觸發憑證的人都能呼叫它、取得它的輸出。
|
||||
這個 workflow 讀取:[盤出 workflow 用到的資料源,若可得]
|
||||
需要保護(要求呼叫者認證)嗎?目前的觸發認證是:[現況]
|
||||
|
||||
確認部署?(需人類明示)
|
||||
```
|
||||
- 「workflow 讀取什麼資料源」:盡力從 workflow 定義盤(用了哪些 recipe / endpoint),盤不出就標「無法自動判斷,請自行確認」。誠實。
|
||||
|
||||
## 3. known-destinations / 不重複問(R4 避免盲目按 yes)
|
||||
|
||||
觸發策略已經很窄(只暴露動作),但同一個 workflow 重複部署不該每次問。
|
||||
- 首次部署某 workflow 為 webhook → 問。人類確認後記住(該 workflow 標記 exposure-confirmed)。
|
||||
- 之後同 workflow 更新 → 不重問(除非暴露面變大,如新增對外觸發)。
|
||||
- 記在哪:workflow metadata(WEBHOOKS KV 的 record 加 `exposure_confirmed_at`)。
|
||||
|
||||
## 4. 與既有一致(R5)
|
||||
- 同 component-gatekeeping:AI 不可替人類決定有外洩風險的動作;誠實限制(AI 能偽造 confirmed_by_human,靠軌跡可審 + mindset)。
|
||||
- 同「arcrun 不做授權判斷」:不判斷「該不該暴露」,只「攔下來讓人類明示同意」。不禁止暴露,要明示同意。
|
||||
|
||||
## 5. 範圍邊界
|
||||
- **動**:webhook 部署路徑(webhooks-named.ts)的 exposure_confirmation + CLI `acr push --confirm-exposure` 互動 + hook。
|
||||
- **不動**:用戶 API 入站保護機制(發 key/權限/限流,另列 BACKLOG);recipe 私人 push(不暴露,不擋);出站 http 節點(不擋)。
|
||||
- recipe 公共貢獻路徑未實作 → 本系統只要求它**未來**內建 exposure 閘門(記進那條 BACKLOG 項)。
|
||||
|
||||
## 6. 決議(richblack 2026-05-30 design review)
|
||||
|
||||
- **Q1 → recipe push 也警示,公私一視同仁。** 不是因為 recipe 本身暴露,而是統一原則「凡有資料去向/暴露面的動作都警示」。用戶可選「以後不要警示」(記偏好)。理由見 §7 同意 log。
|
||||
- **Q2 → webhook 部署要警示,但角度是「提醒 + 提供保護」不是「擋」。** 用不用認證是用戶決定(如美國氣象 API 本就無 key 公開)。我們警示時**順便提醒「可用 arcrun 提供的保護措施」**(接「用戶 API 保護機制」資安優勢,BACKLOG 待決策)。首次問、記住(§3)。
|
||||
- **Q3 → hook 偵測 `acr push` 指令**(簡單版,pre-bash 攔指令)。
|
||||
|
||||
## 7. 同意 = 法律憑證(richblack 2026-05-30,重要)
|
||||
|
||||
每次人類同意「暴露/送資料」的動作,**留 log(誰、何時、同意了什麼)**。這不只是「軌跡可審」,是**法律保護**:
|
||||
|
||||
- 真發生資料外洩 / 糾紛時,有「用戶在 [時間] 明示知情同意把 [什麼] 暴露給 [誰]」的證據 → 避免訴訟風險(責任在明示同意的用戶,不在 arcrun)。
|
||||
- 「以後不要警示」這個選擇**本身也要 log**(用戶在 [時間] 選擇了不再對 [X] 警示 = 他知道風險並接受)。
|
||||
- 同意 log 存放:與動作關聯(webhook record / recipe record 的 `exposure_consent: { confirmed_by, understood, confirmed_at, suppress_future }`)。
|
||||
- 誠實限制同前:AI 能偽造 confirmed_by_human。但**法律意義上,憑證存在 + 可審 = 用戶有機會知情**,這道防線的價值是法律歸責不是技術防偽。
|
||||
|
||||
→ 這把 §1b 的 `exposure_confirmation` 升級為**帶法律意義的同意憑證**,所有暴露/送資料動作(recipe push / webhook 部署)共用此機制。
|
||||
|
||||
## 8. 警示是「保護措施的入口」(不只是攔)
|
||||
|
||||
警示訊息除了說明風險,**主動提供 arcrun 的保護措施**(產品價值,非只防呆):
|
||||
```
|
||||
⚠️ 這個動作會把 [X] 開放/送出。
|
||||
arcrun 可以幫你保護它:
|
||||
- 要求呼叫者帶 API Key(你發給特定對象)
|
||||
- 設定權限 / 限流
|
||||
一個動作就能加上。要加保護嗎?還是確認公開(如公開資料 API)?
|
||||
```
|
||||
(具體保護機制是 BACKLOG「用戶 API 保護機制」待決策項——本系統先在警示處**提示它存在**,實作後接上。)
|
||||
@@ -0,0 +1,56 @@
|
||||
# Requirements: 資料外流警示(Data Exfiltration Warning)
|
||||
|
||||
> 2026-05-30 建立(richblack 確認)。資安優先、及早做。
|
||||
> 判準源:DECISIONS §7(讓 AI 不做歪 + 閉環)、§0(減少不可控依賴 / 風險);BACKLOG 步驟 5b。
|
||||
|
||||
---
|
||||
|
||||
## 背景與風險
|
||||
|
||||
arcrun 讓「產生 API / 把資料送出去」變很簡單(一堆資料 + webhook trigger = API;recipe = 打某 endpoint)。
|
||||
**這個「簡單」本身是風險**:簡單到 AI 可能在用戶不知情下,把含個資的東西變成可被呼叫的 endpoint,或把
|
||||
敏感資料送到非預期對象。
|
||||
|
||||
**richblack 的核心情境**:用戶有個 Google Sheets 存所有朋友的個資。正確用法是「call 它查詢」(自用)。
|
||||
但若 AI 把它變成一個 recipe / workflow,**送資料到非預期對象**(公開 webhook、公司群、外部 endpoint),
|
||||
且**沒做認證** → 所有資料裸奔。
|
||||
|
||||
**關鍵原則(richblack 2026-05-30):**
|
||||
1. **不分公私庫都要警示**。私人庫(公司用)一樣會出事(不小心把個資 POST 到公司群)。觸發點不是「推公共」,
|
||||
是「這動作會讓資料流向某處」。
|
||||
2. **不禁止**用戶公開 / 送資料(他要放什麼給誰是他的自由)——**但要確定他自己明示同意了**,不是 AI 替他決定。
|
||||
3. **兩道防線**:(a) hook 在 AI 動手前警告(防在前);(b) API 層在資料真送出前攔(防在後)。不論哪條路都攔。
|
||||
|
||||
## 需求
|
||||
|
||||
### R1 — API 層警示(資料送出前需人類同意,不分公私庫)
|
||||
任何「把資料送往某目的地」的 API 動作,在執行/儲存前需人類明示同意。涵蓋(待 design 盤準):
|
||||
- `acr recipe push`:recipe 定義一個 endpoint(資料去向)。
|
||||
- `acr push`(workflow):workflow 可能含「讀敏感源 → 送往某 endpoint」的節點。
|
||||
- webhook trigger 部署:把 workflow 變成可被呼叫的 API。
|
||||
- 未來「recipe 貢獻公共庫」路徑(BACKLOG 飛輪項)。
|
||||
|
||||
同意內容要讓人看得懂風險:**這個動作會把 [什麼資料] 送到 [哪個目的地],需不需要 credential 保護?確認?**
|
||||
|
||||
### R2 — hook 在 AI 動手前警告
|
||||
AI 要做這類動作(寫含外部 endpoint 的 recipe/workflow、跑會送資料的指令)前,hook 先警告 + 要人類確認。
|
||||
這是「防在前」——在 AI 本機動手當下就提醒,不等到 API 層才攔(省一趟、且更早讓人看到)。
|
||||
|
||||
### R3 — 誠實的偵測範圍(不假裝能全防)
|
||||
「敏感資料送到非預期對象」機械上難完整偵測。本系統做**可機械判斷的部分**,誠實標明擋不住的:
|
||||
- 能偵測:動作含「外部 endpoint」(recipe endpoint / workflow http 節點 / webhook 對外)。
|
||||
- 難偵測:「這份資料是否敏感」「這個目的地是否非預期」——這需要語境,機器判不準。
|
||||
- 做法:偵測到「資料 → 外部目的地」的動作就警示,由**人類**判斷該資料/目的地是否該放行(人類同意是判斷點,機器只負責「攔下來問」)。
|
||||
|
||||
### R4 — 不擋自用、不製造過度摩擦
|
||||
- 純自用、不送資料出去的動作(acr run 本機、查詢類)不該被警示淹沒。
|
||||
- 警示要精準在「資料外流」動作,不是每個動作都問(否則用戶會盲目按 yes,警示失效)。
|
||||
|
||||
### R5 — 與既有閘門一致
|
||||
- 與「建零件人類閘門」(component-gatekeeping)同精神:AI 不可替人類決定有外洩風險的動作。
|
||||
- 與「arcrun 不做授權判斷」一致:不判斷「該不該送」,只「攔下來讓人類明示同意」。
|
||||
|
||||
## 非目標
|
||||
- 用戶自己的 API 保護機制(入站認證:發 key 給別人 / 權限 / 限流)—— 另列 BACKLOG 待決策。
|
||||
- 完整 DLP(資料外洩防護)系統 / 內容掃描判斷敏感度 —— 機器判不準,不做。
|
||||
- recipe 公共貢獻路徑本身 —— 未實作(飛輪項),本系統只要求它未來內建同意閘門。
|
||||
@@ -0,0 +1,40 @@
|
||||
# Tasks: 資料外流警示
|
||||
|
||||
> 對應 design.md(richblack 已 review,Q1-Q3 + 法律憑證 + 保護入口決議)。
|
||||
> 每完成一個 task 立刻標 [x],不批次。
|
||||
|
||||
---
|
||||
|
||||
## 共用:同意憑證機制(§7 法律憑證)
|
||||
- [x] C1 定義 `exposure_consent { confirmed_by, understood, confirmed_at, suppress_future }` 型別
|
||||
- [x] C2 同意 log 寫入動作關聯的 record(webhook record / recipe record),可審
|
||||
- [x] C3 「以後不要警示」(suppress_future)本身也 log(用戶知風險並接受)
|
||||
|
||||
## API 層警示(R1,防在後)
|
||||
- [x] A1 webhook 部署(webhooks-named.ts POST)要 exposure_consent,缺且未 suppress → 拒絕 + 提示
|
||||
- [x] A2 recipe push(/recipes POST)同上(公私一視同仁)
|
||||
- [x] A3 首次暴露某資源問、記住(exposure_confirmed / suppress_future)→ 之後不重問(§3)
|
||||
- [x] A4 警示訊息說明風險 + 盤資料源(盡力,盤不出標「請自行確認」)+ **提示 arcrun 保護措施**(§8)
|
||||
|
||||
## CLI 警示(互動 + 旗標)
|
||||
- [x] B1 `acr push`:部署前互動式警示(首次某 workflow),人類確認組 exposure_consent 送出;`--confirm-exposure` 跳過互動(CI/非 TTY);`--suppress-warning` 記偏好
|
||||
- [x] B2 `acr recipe push`:同上
|
||||
- [x] B3 非 TTY(AI 直跑)無 --confirm-exposure → 拒絕並提示「需人類確認暴露」
|
||||
|
||||
## hook(R2,防在前,Q3=偵測指令)
|
||||
- [x] H1 pre-bash-guard:偵測 `acr push` / `acr recipe push` → 警示「這會把 X 變可被外部呼叫,需人類確認」
|
||||
|
||||
## mindset / 文件
|
||||
- [x] M1 誠實限制(AI 能偽造 confirmed_by_human,靠憑證可審 + 法律歸責)寫進 mindset Skill(步驟 7)+ 文件
|
||||
|
||||
## 驗收
|
||||
- [ ] V1 acr push 部署 webhook(首次)→ 互動警示 + 說明暴露 + 提示保護 的終端輸出
|
||||
- [x] V2 非 TTY 跑 acr push 無 --confirm-exposure → 拒絕的輸出
|
||||
- [x] V3 webhook 部署 API 無 exposure_consent → 拒絕的輸出
|
||||
- [x] V4 同一 workflow 二次部署 → 不重問(已記住)
|
||||
- [ ] V5 --suppress-warning 後 → 不再警示,但 suppress 選擇有 log
|
||||
- [x] V6 同意後 → exposure_consent 寫進 record 可查(法律憑證)
|
||||
|
||||
## 範圍邊界
|
||||
- 不動用戶 API 入站保護機制(發 key/權限/限流)—— BACKLOG 待決策,本系統只在警示處「提示它存在」。
|
||||
- 不擋出站 http 節點(不暴露我的資料)、不擋 acr run(本機)。
|
||||
Reference in New Issue
Block a user