# 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 保護機制」待決策項——本系統先在警示處**提示它存在**，實作後接上。）
