docs(spec): artifact-sharing 審查對齊 ×2 — K2 改 KBDB 唯一公庫後端(對齊 #16)+ 零件界線照 #23/D29

審查意見兩處(總管 2026-07-07):
1. K2 原「recipe 維持 KV 公庫、泛化端點 front 兩後端」與 #16(RECIPES KV→KBDB)衝突
   → 改為 KBDB 是唯一公庫後端;#16 落地前對 type=recipe 的 KV 轉接明定為過渡碼、
   #16 完成即拆(1.5/5.2 對應改);KV 公庫不得寫成穩態。遷移本體=#16 負責,不重工。
2. component 界線照 #23/D29 定案改:零件貢獻整層搬到獨立 repo Leo/arcrun-components
   (fork→PR→人審);市場只偵測缺件→引導去該 repo 開 PR,永不傳輸/安裝零件程式;
   arcrun_publish_component 路徑廢除。design/requirements/tasks 凡提零件發布處照此改。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015d5jDbuqT5Htwv3Q88XXKk
This commit is contained in:
Leo
2026-07-07 09:09:37 +00:00
parent 7777414b70
commit 1d7f69215a
3 changed files with 20 additions and 20 deletions
@@ -30,7 +30,7 @@
- 安全與審核設計(app-store 市場信任 vs 零件 PR 閘的分界)。
### 不包含(Out of Scope
- 零件安裝(PR 路徑,另案);credential 分享;跨環境市場聚合層;recipe 從 KV 遷 KBDBSaaS/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 embedworkflow-discovery 已證);recipe KV 公庫已上線穩定,重寫=在可用機制上重投資(mistakes 教訓) | ❌ 全部塞 KV(違鐵律、無語意搜尋);❌ 逼 recipe 立刻遷 KBDB(負 ROI,列未來選項 |
| **K2 公庫儲存後端** | **KBDB 是唯一公庫後端**`entry_type=public_artifact`。workflow/template 一開始就建在 KBDBrecipe 公庫隨 **#16RECIPES KV→KBDB 遷移)**收斂進同一後端。過渡期(#16 落地前)泛化端點可暫時把 `type=recipe` 轉呼既有 KV 路徑,但 **KV 公庫=過渡態、非穩態**#16 完成即拆轉接 | 對齊儲存鐵律(長效→KBDB)+白拿 KBDB 語意搜尋(Vectorize embedworkflow-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 一起 pullcomponent 只偵測引導、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|template` 走 KBDB `public_artifact` 路徑。對外一套 API,對內兩後端(K2)。可先只上 workflow/templaterecipe 沿用既有 `/public-recipes`(見 tasks 分期)。
> **recipe 相容(過渡)**:終態=三型都走 KBDB `public_artifact` 路徑(K2KBDB 唯一公庫後端)。#16RECIPES KV→KBDB)落地前的過渡期,泛化端點對 `type=recipe` 暫時轉呼既有 KV 公庫路徑(`listAllRecipes`/`installRecipeRecord`——這段轉接碼是**過渡碼**#16 完成後 `type=recipe` 走 KBDB、轉接即拆,不留雙後端。可先只上 workflow/templaterecipe 沿用既有 `/public-recipes`(見 tasks 分期)。
### 導入語意 + materialize adapterR4
@@ -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 的分界**:資料 artifactrecipe/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 慣例)
### 資料模型
- 公庫 recordKBDB `public_artifact` entry(見上)。**不建新表**entry_type + metadata_json 承載,KBDB 鐵律)。
- 公庫 recordKBDB `public_artifact` entry(見上)**KBDB 是唯一公庫後端**(K2;recipe 過渡期例外見上)。**不建新表**entry_type + metadata_json 承載,KBDB 鐵律)。
- market_stat:復用既有 KBDB recipe-statskey=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.5recipe 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.yamlvs JSON。本 SDD 預設 YAML、兩者皆支援。
3. **MCP/CLI 命名**:型別化措辭(`acr workflow pull`vs 泛化措辭(`acr artifact pull --type=`)。本 SDD 建議型別化對外、泛化對內。
4. **依賴遞迴深度上限**:建議 5,是否合適。
@@ -28,7 +28,7 @@ Arcrun 的可攜開發物有三類存在 KBDB / KV 的**宣告式 record**
### 範圍界線(leo 拍板,最重要)
- **本 SDD 只處理「資料庫就能完成的開發物」= recipe / workflow / template(+slots)**。它們是 KBDB / KV 裡的**可攜 record**,分享=發布到公庫 + 下載/導入進自己 namespace + 匯出成可攜格式。
- **零件(component / code)不在此範圍**。零件是**程式**,**PR → 併入 main由部署/更新流程安裝**`component-gatekeeping` + `arcrun-components` repo 已定案:投稿唯一入口=PR,廢 MCP publish 路徑,見 Arcrun#23 教訓)。本 SDD 只在「依賴解析」處與零件交界,不改零件安裝路徑
- **零件(component / code)不在此範圍**。零件是**程式**,貢獻已**整層搬到獨立 repo `Leo/arcrun-components`**:唯一入口=**fork→PR→人審**→併 main由部署/更新流程安裝#23/D29 定案;`arcrun_publish_component` 路徑廢除)。本 SDD 的市場只在「依賴解析」處與零件交界:**偵測缺件→引導去該 repo 開 PR,永不傳輸/安裝零件程式**
---
@@ -61,7 +61,7 @@ Arcrun 的可攜開發物有三類存在 KBDB / KV 的**宣告式 record**
- **R2 可攜格式(export**:每型能匯出成自足的 YAML/JSON,含 `dependency_manifest`(引用的 component/recipe/template/credential 清單),**絕不含機密值**。
- **R3 公庫端點**:搜/列(帶市場數據,落空回創作引導)、取全文(pull 用,多作者選最佳)、投稿(submit-p,新增作者版本不覆蓋)。三型都要。
- **R4 導入語意(pull)**pull = 把公庫定義寫進自己 namespace——workflow→`push`/webhooks/named)、template→`create_template`、recipe→既有 `installRecipeRecord`
- **R5 依賴解析**:導入一個 workflow 時,遞迴處理它引用的 recipe/template(一起 pull)、驗證引用的 component 是否已具備(缺→引導走 PR/部署,**不自動抓程式**)、列出需要的 credential(引導 `acr creds push`**不隨 artifact 傳輸**)。
- **R5 依賴解析**:導入一個 workflow 時,遞迴處理它引用的 recipe/template(一起 pull)、驗證引用的 component 是否已具備(缺→引導`Leo/arcrun-components` 開 PR(fork→PR→人審),**永不傳輸/安裝零件程式**)、列出需要的 credential(引導 `acr creds push`**不隨 artifact 傳輸**)。
- **R6 三介面對齊**HTTP 端點 → MCP tool → CLI 三層都補齊(沿用 recipe 三層樣板)。
- **R7 安全**:對照 Arcrun#23publish_component 零人閘教訓)明確界定——資料 artifact 走 app-store 市場信任(無 submit 前置人閘,leo 2026-06-29 已對 recipe 拍板移除 consent 閘);真正的程式攻擊面(零件)鎖在 PR 路徑。導入時以市場數據 + 依賴清單 + `data-exfil-warning` 外呼檢查作為信任判斷點。
@@ -78,10 +78,10 @@ Arcrun 的可攜開發物有三類存在 KBDB / KV 的**宣告式 record**
## Out of Scope(明確排除,避免 CC 自行延伸)
- **零件(component/code)的分享/安裝**——走 PR,另案(`component-gatekeeping` / `arcrun-components`)。本 SDD 只在依賴解析處**偵測**零件缺口並引導,不安裝零件
- **零件(component/code)的分享/安裝**——唯一路徑=獨立 repo `Leo/arcrun-components` 的 fork→PR→人審(#23/D29 定案),另案。本 SDD 只在依賴解析處**偵測**零件缺口並引導去該 repo 開 PR,**永不傳輸/安裝零件程式**
- **credential 的分享**——機密永不可攜。只匯出「需要哪些 key」的清單。
- **跨環境市場數據聚合層**(self-hosted 各部署的真實成功率匯總回公庫)——沿用 kbdb-base §7.3/§7.5 5.5「另排」,本 SDD 只讀既有 per-uuid market_stat,不做聚合管道。
- **recipe 既有公庫路徑的重寫 / 從 KV 遷 KBDB**——recipe 現行 KV 路徑已上線且穩定,不在此動它(避免「在既有可用機制上重投資」)。本 SDD 為 workflow/template 建 KBDB-native 公庫,recipe 是否收斂為未來選項(見 design 關鍵決策)
- **recipe RECIPES KV→KBDB 遷移的執行**——由 **#16** 負責(另案進行中),本 SDD 不動手遷、也不重寫 recipe 既有 `/public-recipes*`。但設計前提=**KBDB 是唯一公庫後端**design K2):#16 落地前泛化端點對 `type=recipe` 的 KV 轉接只是過渡碼,#16 完成即拆,**KV 公庫不是穩態**
- **SaaS / api-key 發放**——沒有 SaaSD21)。self-hosted 唯一形態,公庫連線走既有部署 URL。
---
@@ -30,9 +30,9 @@
- 驗收:投稿領新 uuid、不覆蓋同 canonical;寫一筆 `artifact_submission` entry;自報 stat 不進真實計數。
- 注意:沿用 recipe submit 的「新 uuid=新作者版本」與 fire-and-forget 存證。
- [ ] 1.5 recipe 相容轉接:泛化端點對 `type=recipe` 轉呼既有 KV 公庫路徑
- [ ] 1.5 recipe 相容轉接**過渡碼**#16 落地前):泛化端點對 `type=recipe` 暫時轉呼既有 KV 公庫路徑
- 驗收:`GET /public-artifacts?type=recipe` 結果與既有 `/public-recipes` 一致(不破現況)。
- 注意:K2——對外一套 API、對內兩後端;**不改** recipe 既有 `/public-recipes*` 與 KV 儲存。可延後(先只上 workflow/template,見 §狀態)。
- 注意:K2——**KBDB 是唯一公庫後端**,KV 轉接非穩態:#16RECIPES KV→KBDB)完成後 `type=recipe` 改走 KBDB、本轉接即拆(見 5.2)。**不改** recipe 既有 `/public-recipes*` 與 KV 儲存(遷移本體=#16 的事)。可延後(先只上 workflow/template,見 §狀態)。
---
@@ -66,8 +66,8 @@
- 注意:K4——recipe/template co-pullcomponent 只偵測(對照 `acr parts`)缺則引導 PR、**不抓程式**credential 只彙總 key 名引導 `acr creds push`
- [ ] 3.3 component 缺口偵測 + 引導(界線落點)
- 驗收:pull 一個引用「本部署沒有的零件」的 workflow → 停在引導(不落地、不抓程式),訊息指向 PR/`arcrun-components`
- 注意:這道牆=防「workflow 當殼夾帶惡意零件」(#23)。缺零件必須是硬停,不是警告後照裝。
- 驗收:pull 一個引用「本部署沒有的零件」的 workflow → 停在引導(不落地、**永不傳輸/安裝零件程式**),訊息指向獨立 repo `Leo/arcrun-components` 開 PRfork→PR→人審,#23/D29
- 注意:這道牆=防「workflow 當殼夾帶惡意零件」(#23`arcrun_publish_component` 已廢除,勿在引導文案提它)。缺零件必須是硬停,不是警告後照裝。
- [ ] 3.4 credential 清單引導
- 驗收:pull 後回報彙總的待填 key 清單 + `acr creds push` 指引;artifact 內無任何機密值。
@@ -95,8 +95,8 @@
- [ ] 5.1 import 端 `data-exfil-warning` 外呼檢查接線(pull 的 recipe 依賴過同層警示)
- 驗收:pull 一個 endpoint 域名異常的 recipe → import 端出警示(非硬擋)。
- [ ] 5.2待 leo 拍板 K2recipe 公庫是否從 KV 收斂到 KBDB `public_artifact`
- 注意:非阻塞,列未來選項;現況「不動 recipe」已能運作。
- [ ] 5.2已定案,跟 #16 進度走recipe 公庫收斂到 KBDB `public_artifact` 拆 1.5 的 KV 過渡轉接
- 注意:K2 已定(KBDB 唯一公庫後端,審查 2026-07-07 對齊 #16);遷移本體由 #16 執行,本項=#16 落地後把 `type=recipe` 切到 KBDB 路徑並移除轉接碼。非阻塞(過渡期 1.5 已能運作
- [ ] 5.3(待 leo 拍板 K5)公開公庫場景的 import 軟提示(首次 pull 陌生作者→AI 摘要依賴給人看)
---