Files
uncle6me-web 7bd7b4b26a SDD 生命週期鐵律遷移:單一活性制度上線(portal-auth=active,其餘 paused/draft)
- 鋪檔(自 system-dev-template v1.15.0):SDD-LIFECYCLE.md+pending-changes.md
  +sdd-guard.sh(覆蓋舊版,加單一活性檢查)+sdd-check.md+sdd-active-check.sh
- settings.json PreToolUse(Write|Edit|MultiEdit)掛上 sdd-guard.sh
- 全部 SDD design.md 掛 frontmatter:portal-auth=active(現行 portal 線,
  #61 demo 四件套剛 merge);artifact-sharing=draft(零任務動工);
  其餘 16 份=paused(皆有未完成任務,無明顯死件,不硬 close)
- CLAUDE.md 加「SDD 生命週期鐵律」段(指向 SDD-LIFECYCLE.md+濃縮五條)
  +SDD 速查表改以 frontmatter status: active 為現行判準
- 驗證:sdd-active-check exit 0(恰 1 份 active);guard pipe-test code 檔
  exit 0 帶現行 SDD 提示;反向測試(造 2 份 active)guard exit 2/check exit 1 全擋

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 17:03:16 +08:00

255 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
status: draft
superseded_by: ""
---
# Artifact Sharing — Design
> 狀態:草稿(待 review
> 建立:2026-07-07 | 最後更新:2026-07-07
> 負責人:Arcrun subagent(受 InkStoneCo 總管指派)
---
## 一句話說明
把 recipe 的 app-store 公庫模型,泛化成「一套公庫 record 模型 + 一組泛化端點 + 三個型別化 materialize adapter」,讓 recipe / workflow / template 都能發布、搜尋、pull、export,並在 pull 時解析依賴。
---
## 背景與問題
見 requirements.md。核心:recipe 已有 `/public-recipes` + `submit` + `installRecipeRecord` 的完整範本(`cypher-executor/src/routes/recipes.ts`),workflow / template 缺這一整套。要複製它的**公私庫分界、UUID 身份、canonical_id/author、市場數據、pull=寫進自己私庫**這幾個成熟決策,而非重新發明。
---
## 範圍
### 包含(In Scope
- 統一的公庫 record 資料模型(三型共用身份/市場欄位)。
- 三型 artifact 的可攜格式(export)+依賴清單。
- 公庫端點:泛化的 `/public-artifacts` 一套打通三型(見「關鍵決策 K1」的取捨與結論)。
- 導入語意(pull)與型別化 materialize adapter。
- 依賴解析(recipe/template 共 pull、component 引導 PR、credential 引導填值)。
- MCP tools / CLI 命令三層對齊。
- 安全與審核設計(app-store 市場信任 vs 零件 PR 閘的分界)。
### 不包含(Out of Scope
- 零件安裝(`Leo/arcrun-components` fork→PR→人審路徑,另案);credential 分享;跨環境市場聚合層;recipe 從 KV 遷 KBDB 的**執行**#16 負責;本 SDD 只以「KBDB 唯一公庫後端」為前提設計);SaaS/api-key。(詳 requirements Out of Scope。)
---
## 設計
### 架構概覽
```
┌──────────────── 公庫(KBDB,長效資料)────────────────┐
發布 submit-p │ public_artifact entryentry_type=public_artifact │ 搜尋 / pull
────────────► │ { uuid, type, canonical_id, author, portable_body, │ ◄────────────
│ dependency_manifest, market_stat(per-uuid) } │
└───────────────────────────────────────────────────────┘
▲ │
(export 產可攜檔) │ │ pull = 取全文
│ ▼
┌──────────────────────┴───────┐ ┌─────────────────────────────────────┐
│ 自己 namespace(私庫) │ │ materialize adapter(型別化落地) │
│ workflow → WEBHOOKS KV+KBDB │◄───────│ workflow → push (/webhooks/named) │
│ template → KBDB /templates │ │ template → create_template │
│ recipe → RECIPES(→KBDB#16) │ │ recipe → installRecipeRecord │
└──────────────────────────────┘ │ + 依賴解析(遞迴 pull / 引導) │
└─────────────────────────────────────┘
```
- **讀寫都走既有 worker**:公庫 record 存 KBDB`kbdb` worker 的 `/entries`),泛化端點掛在 **cypher-executor**(已是 recipe 公庫 + workflow CRUD 的所在,且已有 KBDB fetch 慣例)。**不新建 worker、不 service binding、不 wrangler**arcrun-primer A 類)。
### 設計原則(market 層)
- **資料完整性優先於界面(leo,2026-07-07)**:「可以沒有界面,但這些資訊會留下;如果哪天已有 1000 個資源、想做個網站告訴大家,卻發現資訊都不足、少東少西,那就糟了。」UI 是未來的皮,**record 完整性是現在的責任**——本 SDD 的公庫 record 與事件記錄,一律用「未來 showcase 網站需要什麼」反推首日 schema(見 R1 欄位清單),而非「現在端點用到什麼」。
- **事件型資料事後不可重建 → day-one 就 append 記錄**:衍生統計(author_reputation、熱門榜)可以晚算、隨時重算;但**原始事件**——誰何時 pull/download 了哪個 uuid、誰何時 submit 了什麼——**錯過當下就永遠沒有**。故 `artifact_pull_event` / `artifact_submission` 從第一天就寫(KBDB append-only 正好是這個用途),有沒有人看是另一回事。
### 關鍵決策
| 決策 | 選擇 | 原因 | 放棄的選項 |
|------|------|------|----------|
| **K1 端點:泛化一套 vs 每型別一套** | **泛化一套 `/public-artifacts?type=` 讀,型別化 adapter 寫** | 讀側(搜/列/取全文/market_stat/落空引導)三型邏輯完全同構,泛化成一套省 3×重複、給 AI 一致心智模型(low-code);寫側(materialize 落自己 namespace)三型的家不同,必須型別化 | ❌ 每型一套 `/public-workflows`+`/public-templates`(3× 複製 recipe 端點,維護面爆、AI 要記三套);❌ 全泛化含寫(做不到,落地各異) |
| **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 端沒判斷依據) |
### 統一公庫 record 模型(R1
公庫一筆 = KBDB entry`entry_type='public_artifact'``owner_id=author`(歸屬即隔離),`metadata_json` 承載身份與市場鍵,`content` 放 canonical_id(供 keyword/semantic search)+ `metadata_json.embed=true` 開語意搜尋:
欄位完整性用「未來 showcase 網站」反推(見設計原則):哪天有 1000 個資源想做網站,**首日投稿就捕捉的欄位不能少東少西**。每欄標【必填=投稿時必給|自記=系統寫入|可選】:
```jsonc
// public_artifact entry.metadata_json
{
"uuid": "…", // 【自記】唯一身份(誕生即領,沿用 §7.5.5)
"type": "workflow", // 【必填】recipe | workflow | template
"canonical_id": "daily_digest", // 【必填】
"author": "leo", // 【必填/自記】該 uuid 投稿者(自 namespace 帶出);'system'=種子
"created_at": "…", // 【自記】投稿時間(版本沿革與「最新發布」榜的依據)
"updated_at": "…", // 【自記】metadata 修訂時間(portable_body 不覆蓋——改版=submit-p 新 uuid
"derived_from": "…uuid?", // 【可選】fork 溯源;同 canonical_id+author 的歷代版本則靠 created_at 排序追(不需額外欄)
"display_name": "每日摘要", // 【必填】
"description": "…", // 【必填】人讀的一句話;供語意搜尋,強制非空(沿用 workflow-discovery R1
"tags": ["social", "fb"], // 【可選,建議】分類/標籤(showcase 分類頁的料)
"compat": { // 【自記,可覆蓋】相容性:投稿當下的 arcrun / portable 格式版本
"arcrun_version": "1.3.x",
"schema_version": 1
},
"license": "MIT", // 【可選】未定→不填(顯示「未聲明」);是否改必填待拍板
"embed": true, // 【自記】開 Vectorize
"portable_body": { }, // 【必填】見「可攜格式」
"dependency_manifest": [ ],// 【自記】掃 portable_body 產出,見「依賴解析」
"deps_summary": { // 【自記】manifest 的輕量聚合(submit 時一併算好存入,搜尋列表直接帶)
"recipes": ["facebook"], // 各類依賴的名稱清單;空類回空陣列
"templates": ["fb_posts"],
"components": [],
"credentials": ["facebook_token"]
}
// market_stat 不存這裡——per-uuid 記在既有 recipe-stats 機制(KBDB),import 時 fetch
}
```
> **deps_summaryleo 補點,2026-07-07**`dependency_manifest` 是 pull 用的完整清單;`deps_summary` 是它的**搜尋層摘要**(各類依賴的名稱陣列),submit/export 算 manifest 時順手聚合、存進 metadata_json → 列表回應直接帶、不必解 portable_body。**為什麼要在搜尋層**:對 low-code 用戶,「裝不裝」的判斷資訊必須在搜尋結果就看到,不是 pull 之後才發現缺東西——搜到「把 Facebook post 拉回來儲存」的 workflow,列表項直接顯示「需 1 templatefb_posts)+1 recipefacebook)+1 credential 待填(facebook_token)」,一眼可判斷。
> **市場數據**:沿用 recipe `fetchMarketStat`KBDB `/recipe-stats/:id`per-uuid)。泛化為 `/artifact-stats/:uuid`(或直接復用 recipe-stats 表,key=uuid 本就型別無關)。**不在投稿時寫自報數**(沿用 §7.3:自報數只當存證 `*_submission` entry,不併真實計數,避免污染市場)。
### 作者信譽(author reputation)—— market 的核心(leo 定義,2026-07-07
> leo 原話意涵:「Leo 發表了 100 個 recipe,他的 reputation 非常好,而你找到 Leo 就能看到他 share 的這 100 個 recipes」+未來獎勵機制掛在信譽上。**Market 的核心=作者信譽經濟(author-centric**per-uuid market_stat(單品數據)只是底層原料,作者層才是信任與激勵的單位。
- **author_reputation =衍生視圖,不另立真相源**per-author 統計(發布 artifact 數、彙總 success/failure、最近活躍時間)**全部從 per-uuid market_stat 該 author 的 public_artifact entry 清單聚合而來**。取捨:
- **第一階段=查詢時聚合(compute-on-read**:單一作者的 artifact 數量級小(10²),KBDB 查該 author 的 entries + 逐 uuid 撈 stat 聚合即可,**零新儲存、零一致性問題**(真相永遠在 per-uuid)。
- **量大再物化**:作者/流量成長後改「定期物化」(cron 聚合寫成 `author_reputation` entry,**明確標記為快取、非真相源**,過期重算)。先簡後繁,避免一開始就養兩份數據。
- **曝光位**:① 搜尋結果每項的**作者名旁**附信譽摘要(如 `leo42 發布・96% 成功)`);② **作者頁頂部**(見端點段 authors 端點)。
- **選版邏輯升級**:多作者同 canonical_id 時,排序訊號從「單品 success_count」擴為「**單品數據+作者信譽**」的複合分——單品數據不足(新發布)時作者信譽當先驗。**權重配比待 leo 拍板**(見待拍板清單)。
- **獎勵機制(future layer,本 SDD 不實作)**:**第一階段的獎勵=信譽本身**(曝光、排序加權、信任標記);未來付費分潤/積分**掛在 author identity 上**。因此 **author 身份必須穩定可驗**——現況 author 是字串 namespaceself-hosted 單租戶下夠用),**進 SaaS/多人公開市場前,author 必須綁認證身份**(否則信譽可被冒名、獎勵可被盜領),列為該階段的**前置條件**,非本 SDD 範圍。
### 可攜格式(exportR2 / US-3
每型 `portable_body` = 該型的自足定義,**去識別化 + 去機密**:
- **recipe**:既有 RecipeDefinition 去掉 `uuid/author/created_at`(導入時重領),保留 endpoint/method/headers/body/auth_service/`credentials_required`(只有 key 名,無值)。
- **workflow**`{ name, flow, config, description }`(cypher 三元組 + 節點設定)。`config` 內對零件的引用(`component: rec_xxx` / `component: <builtin>`)保留;credential 引用維持 `{{credential.xxx}}` 模板(無值)。
- **template**`{ name, slots[], description }`
export 檔(YAML/JSON,二選一,預設 YAML 對齊 workflow.yaml 慣例)= `portable_body` + `dependency_manifest` + `type`/`canonical_id` 標頭。自足=任何相同 Arcrun 部署 import 後可跑(前提:component 已具備、credential 已填)。
### 泛化端點(R3,K1 讀側泛化)
掛在 cypher-executor`type` 為必帶 query/param。行為對照 recipe `/public-recipes*` 完全同構:
- `GET /public-artifacts?type=&q=&author=&limit=&offset=` — 搜/列公庫。同 canonical_id 回多筆(多作者),各附 `market_stat` **與 `deps_summary`**(配套需求摘要:這個 artifact 要配哪些 recipe/template/component/credential 才跑得起來——「搜一個、看到各要裝什麼」在列表層就成立,見 R1 的 deps_summary 說明),作者名旁附**作者信譽摘要**(見作者信譽段)。**`author=` 過濾**=跨型別列該作者全部發布(「找到 Leo 就看到他 share 的 100 個 recipes」),可與 `type`/`q` 併用——就是 author 欄的查詢面,成本低。落空(q 無命中)→ `{ found:false, type, query, hint }` 創作引導(沿用 §7.5.6)。`type` 省略=跨型別搜(回傳項帶各自 type)。
- `GET /public-artifacts/authors/:name`**作者頁**:頂部 author_reputation 摘要(發布數、彙總成功率、最近活躍)+該作者全部發布清單(每項附 market_stat/deps_summary)。reputation=查詢時從 per-uuid stat 聚合(見作者信譽段的取捨)。
- `GET /public-artifacts/:type/:canonical_id?author=` — 取單一全文(pull 用)。多作者→**複合分選版**:單品 `market_stat` +作者信譽(單品數據不足時作者信譽當先驗;權重待拍板)。落空→創作引導。**成功回應時 append 一筆 `artifact_pull_event`**(誰的 namespace、何時、拉了哪個 uuid)——pull 事件事後不可重建,day-one 就記(見設計原則)。
- `POST /public-artifacts/submit` — 投稿(submit-p)。body 帶 `{ type, canonical_id, portable_body, dependency_manifest, author, tags?, compat?, license?, stat? }`。**領新 uuid = 新增作者版本**(不覆蓋,§7.5.5);`stat` 只寫 `*_submission` 存證 entry,不併真實計數。
> **recipe 相容(過渡)**:終態=三型都走 KBDB `public_artifact` 路徑(K2KBDB 唯一公庫後端)。#16RECIPES KV→KBDB)落地前的過渡期,泛化端點對 `type=recipe` 暫時轉呼既有 KV 公庫路徑(`listAllRecipes`/`installRecipeRecord`)——這段轉接碼是**過渡碼**#16 完成後 `type=recipe` 改走 KBDB、轉接即拆,不留雙後端。可先只上 workflow/templaterecipe 沿用既有 `/public-recipes`(見 tasks 分期)。
### 導入語意 + materialize adapterR4
`pull(type, canonical_id)` =
1. `GET /public-artifacts/:type/:canonical_id` 取全文(含 market 最佳版本 + dependency_manifest)。
2. **先解依賴**(見下),再落地。
3. **materialize(型別化)**
- `workflow``POST /webhooks/named`(既有 pushowner_id=自己 api_key/namespace)。
- `template``POST /templates`(既有 create_template)。
- `recipe``installRecipeRecord`(既有)。
4. 回報:落地的 uuid + 依賴處理結果(已 pull 的 recipe/template、缺的 component、待填 credential)。
### 依賴解析(R5 / K4)—— 關鍵設計點
一個 workflow 常引用四類東西。import 時**分類處理,各走各的邊界**:
| 依賴類 | 來源(怎麼認) | 導入處理 | 為何這樣 |
|---|---|---|---|
| **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`…) | **只偵測缺口→引導開 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)。
- **deps_summary 讓配套需求在「搜尋層」就可見**(leo 補點):算 manifest 時順手聚合出各類依賴名稱清單存進 metadata_json`GET /public-artifacts` 列表項直接帶。low-code 用戶判斷「裝不裝」的資訊要在搜尋結果就給,不是 pull 之後才發現缺東西——例:搜到「把 Facebook post 拉回來儲存」,列表項即顯示「需 1 templatefb_posts)+1 recipefacebook)+1 credential 待填(facebook_token)」。
- **遞迴有界**manifest 逐項 pull,維護 visited set 防環 + 深度上限(建議 5),超限回報中止並列未解項。
### 安全與審核(R7 / K5)—— 對照 Arcrun#23 教訓
- **#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 依賴同樣過這層。
3. **零件閘不鬆動**workflow 帶再多引用,也**不能**讓一個未經 PR 的新零件進入 host。缺零件=停在引導,這道牆就是防「拿 workflow 當殼夾帶惡意零件」。
4. **credential 零傳輸**:機密不可攜,杜絕投稿夾帶他人 token / 誘導填入釣魚 credentialimport 端自己 `acr creds push`)。
- **投稿存證**submit 寫一筆 `artifact_submission` entry(誰、何時、投了什麼 uuid、自報 stat)當**法律歸責軌跡**(沿用 recipe §7.3),不當門檻。
### API / 介面定義(R6 三層對齊)
| 層 | recipe(既有樣板) | 本 SDD 新增(workflow/template,泛化) |
|---|---|---|
| HTTP | `/public-recipes*``/recipes/submit` | `/public-artifacts*``/public-artifacts/submit``type=` 打通三型) |
| MCP | `arcrun_recipe_search/pull/submit_p` | `arcrun_artifact_search/pull/submit_p`(帶 `type` 參數)+ `arcrun_workflow_export` / `arcrun_template_export` |
| CLI | `acr recipe search/pull/submit-p` | `acr workflow search/pull/submit-p/export``acr template search/pull/submit-p/export`(薄殼包泛化端點) |
> MCP/CLI 面向使用者可保留型別化命名(`acr workflow pull` 比 `acr artifact pull --type=workflow` 更順口、更 low-code),**底層打同一泛化端點**。=「對外型別化措辭、對內泛化實作」,兼得可讀性與 DRY。
### 資料模型
- 公庫 recordKBDB `public_artifact` entry(見上),**KBDB 是唯一公庫後端**(K2;recipe 過渡期例外見上)。**不建新表**entry_type + metadata_json 承載,KBDB 鐵律)。
- market_stat:復用既有 KBDB recipe-statskey=uuid,型別無關)。
- **事件記錄(day-one append,設計原則第 2 條)**:`artifact_pull_event` entry(誰的 namespace、何時、拉了哪個 uuid——取全文成功即寫)+ `artifact_submission` entry(誰、何時、投了什麼 uuid、自報 stat)。皆 append-only、不更新不刪除;熱門榜/下載數/作者活躍度等統計全部從這兩類事件+recipe-stats 事後聚合,**事件是真相,統計是視圖**。
- **author_reputation:衍生視圖、非真相源**(見作者信譽段):第一階段查詢時聚合;量大後定期物化成標記為快取的 entry。
- 私庫落地:沿用各型既有儲存(workflow=WEBHOOKS KV+KBDB 雙寫、template=KBDB /templates、recipe=RECIPES——現為 KV**隨 #16 遷 KBDB**),本 SDD **不改**私庫儲存、materialize adapter 打各型既有寫入 API 故遷移對本 SDD 透明。
---
## 技術限制
- **不能**:新建 Worker、寫 Worker 程式碼、service binding、跑 wrangler、建 D1 新表、SQL 直寫(arcrun-primer 紅線;端點加在既有 cypher-executor / kbdb worker)。
- **必須相容**recipe 既有 `/public-recipes*` 路徑(不破現有 pull/submit);workflow 既有 `/webhooks/named` push 與 workflow-discovery 雙寫;template 既有 `/templates`
- **必須遵守**:儲存鐵律(長效→KBDB、機密→Secrets)、API-as-WallD6)、UUID 身份模型(§7.5.5)。
- **效能**:公庫搜尋走 KBDB 語意/keywordVectorize 已在 workflow entry 證可行),避免 recipe KV `list({prefix})` 全掃在量大時疊加(kbdb-base §風險 已標)——這也是 workflow/template 公庫選 KBDB 而非 KV 的附帶好處。
---
## 驗收標準
完成的定義(CC 完成任何 task 前必須確認):
- [ ] `POST /public-artifacts/submit`type=workflow)投稿後,`GET /public-artifacts?type=workflow&q=` 搜得到、帶 market_stat **與 deps_summary**(搜尋結果每項可見「要配哪些東西才跑得起來」,不必取全文)。
- [ ] `GET /public-artifacts/workflow/:canonical_id` 回市場最佳作者版本(複合分:單品+作者信譽);落空回 `{found:false,hint}`;成功取全文有 append `artifact_pull_event`
- [ ] `GET /public-artifacts?author=leo` 列出該作者跨型別全部發布;`GET /public-artifacts/authors/leo` 回信譽摘要+清單。
- [ ] `acr workflow pull <id>` 把 workflow push 進自己 namespace,且遞迴 pull 其 recipe/template 依賴、列出缺的 component 與待填 credential。
- [ ] `acr workflow export <name>` 產出自足 YAML,含 dependency_manifestgrep 不到任何機密值。
- [ ] template 同上一套(submit-p/search/pull/export)跑通。
- [ ] 投稿寫 `artifact_submission` 存證 entry;自報 stat 不進真實計數。
- [ ] 一個引用「未具備零件」的 workflow,pull 時停在引導(不落地、不抓程式)。
- [ ] **資料完整性(可測定義)**:不看任何 UI,僅用公庫 record + 事件記錄(`public_artifact`/`artifact_pull_event`/`artifact_submission`/recipe-stats),就能重建出一個完整的市場網站首頁——作者榜、熱門榜、最新發布、每項的配套需求。缺哪個欄位榜單做不出來=schema 不合格。
---
## 相關文件
- `arcrun/kbdb-base/design.md` §7.5recipe app-store / 公私庫雙向 / UUID 身份)— 本 SDD 的母範本。
- `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 兩類工作、紅線。
- Arcrun#23publish_component 零人閘教訓)、Arcrun#13workflow-store / 移除 consent 閘)。
---
## 待 leo / richblack 拍板的設計點
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,是否合適。
5. **K5 信任**:資料 artifact submit 全程無人閘是否可接受於**公開**公庫場景(vs 現況多為 self-hosted 私庫 pull);若未來上真公開公庫,是否要加 import 端的「首次 pull 陌生作者 → AI 摘要依賴清單給人看一眼」的軟提示(非硬閘)。
6. **選版複合分權重**:多作者同名時「單品 market_stat vs 作者信譽」怎麼配權(含新發布單品數據不足時作者信譽當先驗的冷啟動處理)。
7. **license 欄位**:維持可選(未填顯示「未聲明」)或投稿必填。
8. **author 綁認證身份的時點**:現況字串 namespace 夠用(self-hosted 單租戶);進 SaaS/多人公開市場前必須綁認證(信譽防冒名、獎勵防盜領)——在哪個里程碑動手。