@@ -30,7 +30,7 @@
- 安全與審核設計(app-store 市場信任 vs 零件 PR 閘的分界)。
### 不包含(Out of Scope)
- 零件安裝(PR 路徑,另案);credential 分享;跨環境市場聚合層;recipe 從 KV 遷 KBDB; SaaS/api-key。(詳 requirements Out of Scope。)
- 零件安裝(`Leo/arcrun-components` fork→PR→人審 路徑,另案);credential 分享;跨環境市場聚合層;recipe 從 KV 遷 KBDB 的**執行**( #16 負責;本 SDD 只以「KBDB 唯一公庫後端」為前提設計) ; SaaS/api-key。(詳 requirements Out of Scope。)
---
@@ -51,7 +51,7 @@
│ 自己 namespace(私庫) │ │ materialize adapter(型別化落地) │
│ workflow → WEBHOOKS KV+KBDB │◄───────│ workflow → push (/webhooks/named) │
│ template → KBDB /templates │ │ template → create_template │
│ recipe → RECIPES KV │ │ recipe → installRecipeRecord │
│ recipe → RECIPES(→KBDB#16) │ │ recipe → installRecipeRecord │
└──────────────────────────────┘ │ + 依賴解析(遞迴 pull / 引導) │
└─────────────────────────────────────┘
```
@@ -63,7 +63,7 @@
| 決策 | 選擇 | 原因 | 放棄的選項 |
|------|------|------|----------|
| **K1 端點:泛化一套 vs 每型別一套 ** | **泛化一套 `/public-artifacts?type=` 讀,型別化 adapter 寫 ** | 讀側(搜/列/取全文/market_stat/落空引導)三型邏輯完全同構,泛化成一套省 3×重複、給 AI 一致心智模型(low-code);寫側(materialize 落自己 namespace)三型的家不同,必須型別化 | ❌ 每型一套 `/public-workflows` +`/public-templates` (3× 複製 recipe 端點,維護面爆、AI 要記三套);❌ 全泛化含寫(做不到,落地各異) |
| **K2 公庫儲存後端 ** | **workflow/template 公庫建在 KBDB ** ( `entry_type=public_artifact` ) , ** recipe 維持 既有 KV 公庫**、泛化端點 front 兩者 | 對齊儲存鐵律(長效→KBDB)+白拿 KBDB 語意搜尋(Vectorize embed, workflow-discovery 已證);recipe KV 公庫已上線穩定,重寫=在可用機制上重投資(mistakes 教訓) | ❌ 全部塞 KV(違鐵律、無語意搜尋);❌ 逼 recipe 立刻遷 KBDB(負 ROI,列未來選項 ) |
| **K2 公庫儲存後端 ** | **KBDB 是唯一公庫後端 ** ( `entry_type=public_artifact` ) 。workflow/template 一開始就建在 KBDB; recipe 公庫隨 * * #16 ( RECIPES KV→KBDB 遷移)**收斂進同一後端。過渡期(#16 落地前)泛化端點可暫時把 `type= recipe` 轉呼 既有 KV 路徑,但 **KV 公庫=過渡態、非穩態 ** , #16 完成即拆轉接 | 對齊儲存鐵律(長效→KBDB)+白拿 KBDB 語意搜尋(Vectorize embed, workflow-discovery 已證);與 #16 同向不打架——遷移本體由 #16 負責,本 SDD 不對 KV 公庫做任何新投資 | ❌ 全部塞 KV(違鐵律、無語意搜尋);❌ 把「KV 公庫 front 兩後端」寫成穩態(與 #16 衝突,雙後端維護面永久化);❌ 本 SDD 自己動手遷 recipe(與 #16 重工 ) |
| **K3 身份模型 ** | **沿用 recipe UUID 身份模型 ** ( uuid=身份、canonical_id/author/type=屬性、submit-p=新增作者版本不覆蓋、per-uuid market_stat) | 已被 recipe 驗證(kbdb-base §7.5.5);三型共用同一套,pull「選市場最佳作者版本」邏輯可共享 | ❌ 為 workflow/template 另設身份模型(分裂、無法共用選版邏輯) |
| **K4 依賴傳輸邊界 ** | **recipe/template 隨 workflow 一起 pull; component 只偵測引導、credential 只列清單 ** | component 是程式=攻擊面,鎖 PR 路徑(#23 );credential 是機密,永不可攜(鐵律) | ❌ export 內嵌 component 程式(把 PR 閘繞掉,重演 #23 );❌ export 內嵌 credential 值(機密外洩) |
| **K5 審核閘 ** | **資料 artifact 無 submit 前置人閘 ** (市場信任),**信任判斷點移到 import 時**(市場數據+依賴清單+外呼檢查) | leo 2026-06-29 已對 recipe 移除 exposure_consent 閘(arcrun 給 AI 用);資料 artifact 不在 host 上跑任意碼,風險≠零件 | ❌ 對 submit 加人類 consent 閘(與 recipe 已定案反向、增摩擦);❌ 完全無信任訊號(import 端沒判斷依據) |
@@ -109,7 +109,7 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
- `GET /public-artifacts/:type/:canonical_id?author=` — 取單一全文(pull 用)。多作者→選 `market_stat.success_count` 最高版本(沿用 recipe 選版邏輯)。落空→創作引導。
- `POST /public-artifacts/submit` — 投稿(submit-p)。body 帶 `{ type, canonical_id, portable_body, dependency_manifest, author, stat? }` 。**領新 uuid = 新增作者版本**(不覆蓋,§7.5.5);`stat` 只寫 `*_submission` 存證 entry,不併真實計數。
> **recipe 相容**: 泛化端點內部 對 `type=recipe` 轉呼既有 KV 公庫路徑(`listAllRecipes`/`installRecipeRecord`) ,對 `type=workflow|templat e` 走 KBDB `public_artifact` 路徑。對外一套 API,對內兩後端(K2) 。可先只上 workflow/template, recipe 沿用既有 `/public-recipes`(見 tasks 分期)。
> **recipe 相容(過渡)**:終態=三型都走 KBDB `public_artifact` 路徑(K2: KBDB 唯一公庫後端)。#16( RECIPES KV→KBDB)落地前的過渡期, 泛化端點對 `type=recipe` 暫時 轉呼既有 KV 公庫路徑(`listAllRecipes`/`installRecipeRecord`) ——這段轉接碼是**過渡碼**, #16 完成後 `type=recip e` 改 走 KBDB、轉接即拆,不留雙後端 。可先只上 workflow/template, recipe 沿用既有 `/public-recipes`(見 tasks 分期)。
### 導入語意 + materialize adapter( R4)
@@ -130,7 +130,7 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
|---|---|---|---|
| **recipe ** | workflow `config` 裡 `component: rec_xxx` / http_request 引用的 canonical_id | **遞迴 co-pull ** :對每個 recipe canonical_id 走 `pull('recipe', …)` 寫進自己私庫。有界遞迴(recipe 通常不再引用其他 artifact;設深度上限防環) | recipe 是資料,同屬「資料庫就能完成」,一起帶走才可跑 |
| **template ** | workflow 若寫 KBDB record(引用某 template name) | **co-pull ** : template 不存在→`pull('template', …)` →create_template | 同上;template 是 slots 宣告,可攜 |
| **component(零件/code) ** | workflow `flow:` cypher 用到的 builtin 零件(`http_request` /`code` /`cron` …) | **只偵測不安裝 ** :對照本部署 `acr parts` ( component registry) 。齊→放行;缺→回報「此 workflow 需零件 X,你的部署沒有。零件走 PR→併 main→部署安裝( `arcrun-components` repo ),非 pull」。用 §7.5.6 式引導, **絕不自動抓程式** | 零件是程式=攻擊面,鎖 PR 閘(#23 、component-gatekeeping )。這是本 SDD 與零件案的**界線落點** |
| **component(零件/code) ** | workflow `flow:` cypher 用到的 builtin 零件(`http_request` /`code` /`cron` …) | **只偵測缺口→引導開 PR,永不傳輸/安裝零件程式 ** :對照本部署 `acr parts` 。齊→放行;缺→回報「此 workflow 需零件 X,你的部署沒有。零件貢獻已整層搬到獨立 repo * * `Leo/arcrun-components` **( fork→PR→人審→併 main→隨部署/更新安裝 ),非 pull」。用 §7.5.6 式引導 | 零件是程式=攻擊面,唯一入口= `Leo/arcrun-components` 的 PR 人審 閘(#23/D29 定案; `arcrun_publish_component` 路徑已廢除 )。這是本 SDD 與零件案的**界線落點** |
| **credential ** | recipe 的 `credentials_required[].key` / workflow `{{credential.xxx}}` | **只列清單引導 ** :彙總所有需要的 key,回報「請 `acr creds push` 填:notion_token, …」。**值永不隨 artifact 傳輸** | 機密鐵律:值存 CF Worker Secrets,可攜檔只帶 key 名 |
- **dependency_manifest** 在 **export/submit 時就算好並存進 record ** (掃 portable_body 抽引用),import 端不必反解 workflow 內部結構就能預覽「這東西會拉進哪些 recipe/template、需要哪些零件與 credential」——也是 import 的**信任預覽面**( K5)。
@@ -138,7 +138,7 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
### 安全與審核(R7 / K5)—— 對照 Arcrun#23 教訓
- **#23 教訓**: `publish_component` 零人閘(提交即 active/public + MCP 全域)=攻擊面。結構解已定:**廢 MCP 發布路徑、零件投稿唯一入口=PR**( `arcrun-components` ) 。
- **#23 教訓 → #23/D29 定案 **: `publish_component` 零人閘(提交即 active/public + MCP 全域)=攻擊面。結構解已定案 : **`arcrun_publish_component` 路徑廢除**;**零件貢獻整層搬到獨立 repo `Leo/arcrun-components` ,唯一入口=fork→PR→人審**。市場/artifact 分享機制只做「缺件偵測→引導去該 repo 開 PR」,**永不傳輸、永不安裝零件程式** 。
- **本 SDD 的分界**:資料 artifact( recipe/workflow/template) **不是**零件那種攻擊面——它們是宣告式資料,pull 進來只會**執行預先審過的零件**、只會打 recipe 指定的 endpoint、只會用 template 的 slots。故:
1. **submit 無前置人閘 ** ( app-store 市場信任,沿用 leo 2026-06-29 對 recipe 移除 consent 的拍板)。壞版本靠市場數據淘汰,不靠事前審。
2. **信任判斷點在 import 時 ** ,用三個既有訊號:① `market_stat` (真實使用成功率,per-uuid);② `dependency_manifest` (import 前預覽「會拉哪些依賴、打哪些 endpoint、要哪些 credential」);③ * * `data-exfil-warning` 外呼檢查**(該 SDD 的 API 層:recipe endpoint 域名異常時警示)——pull 進來的 recipe 依賴同樣過這層。
@@ -158,10 +158,10 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
### 資料模型
- 公庫 record: KBDB `public_artifact` entry(見上)。**不建新表**( entry_type + metadata_json 承載,KBDB 鐵律)。
- 公庫 record: KBDB `public_artifact` entry(見上), **KBDB 是唯一公庫後端**(K2;recipe 過渡期例外見上) 。**不建新表**( entry_type + metadata_json 承載,KBDB 鐵律)。
- market_stat:復用既有 KBDB recipe-stats( key=uuid,型別無關)。
- 存證:`artifact_submission` entry。
- 私庫落地:沿用各型既有儲存(workflow=WEBHOOKS KV+KBDB 雙寫、template=KBDB /templates、recipe=RECIPES KV),**不改** 。
- 私庫落地:沿用各型既有儲存(workflow=WEBHOOKS KV+KBDB 雙寫、template=KBDB /templates、recipe=RECIPES——現為 KV, **隨 #16 遷 KBDB**),本 SDD **不改**私庫儲存、materialize adapter 打各型既有寫入 API 故遷移對本 SDD 透明 。
---
@@ -190,7 +190,7 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
## 相關文件
- `arcrun/kbdb-base/design.md` §7.5( recipe app-store / 公私庫雙向 / UUID 身份)— 本 SDD 的母範本。
- `component-gatekeeping/` + `arcrun-components` repo — 零件走 PR 的 界線另一側。
- `component-gatekeeping/` + 獨立 repo * * `Leo/arcrun-components` **( #23/D29 :零件貢獻整層外移,fork→PR→人審)— 零件 界線的 另一側。
- `workflow-discovery/` — workflow 已雙寫 KBDB + 語意搜尋,本 SDD 的公庫搜尋基礎。
- `data-exfil-warning/` — import 時外呼信任檢查層。
- `4-guides/arcrun-primer.md` ( InkStoneCo 頂層)— A/B 兩類工作、紅線。
@@ -200,7 +200,7 @@ export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)
## 待 leo / richblack 拍板的設計點
1. **K2 ** : recipe 公庫是否收斂到 KBDB(與 workflow/template 同後端),或永久維持 KV 雙後端?本 SDD 預設「不動 recipe、泛化端點 front 兩後端」,收斂列未來選項 。
1. ~~ **K2**: recipe 公庫是否收斂到 KBDB~~ **已定(審查 2026-07-07,對齊 #16) ** : KBDB 是唯一公庫後端,recipe 隨 #16 收斂;KV 只是 #16 落地前的過渡轉接,不是穩態。剩餘協調點只有「轉接拆除時機跟 #16 進度對齊」 。
2. **export 預設格式 ** : YAML(對齊 workflow.yaml) vs JSON。本 SDD 預設 YAML、兩者皆支援。
3. **MCP/CLI 命名 ** :型別化措辭(`acr workflow pull` ) vs 泛化措辭(`acr artifact pull --type=` )。本 SDD 建議型別化對外、泛化對內。
4. **依賴遞迴深度上限 ** :建議 5,是否合適。