Files
Arcrun/kbdb/migrations/0005_arcrun_asset_templates.sql
T
uncle6me-web 3d3973ecbc feat(storage): 工作流與 recipe 的家搬到 KBDB,KV 降成可丟棄的快取(Arcrun#16+#17)
leo 08-12:「我要的是寫進 KBDB,不是 KV,他的 Recipes、Cypher 是一段話,文字,
數據,一個 entry」「如果零件和工作流的 recipe 不見了,是很可怕的事情」。
同日實害:一次例行更新讓九支工作流在畫面上全部消失。#97 已修掉直接原因
(別再照名字猜使用者的資源、別再擅自新建一顆空的綁上去);這裡修更下面那一句——
**資產本來就不該只存在於一個會被換掉的暫存層裡**。

做法(換 binding,不改四十幾處呼叫端):
- lib/asset-keys.ts    哪些 KV key 是資產、對應 KBDB 哪一列。**唯一**要人看懂的那張表。
- lib/durable-store.ts 讀=KV 先行、miss 回源 KBDB 並補快取;寫=先 KBDB 再 KV,
                       KBDB 失敗就拋錯(禁假綠);**列舉一律回源**——空 KV 列出來是
                       「零筆」而不是「查不到」,那正是東西消失的形狀。
- index.ts             入口把 WEBHOOKS/RECIPES 換成上面那層。逐處改寫一定會漏,
                       而漏掉的那一處就是下一次「東西不見了」的入口。
- routes/storage.ts    /storage/audit(搬前搬後各數一次)+ /storage/migrate-to-kbdb
                       (只增不刪、冪等、逐筆回報成敗)。
- kbdb                 migration 0005 seed 四列 template(零 schema 異動,手法同 0003/0004)
                       + PUT /entries/:id 指定 id 的整列 upsert(通用原語,不是為誰開特例)。
- 衍生資料(idx:*、cron-idx:_all)不進 KBDB,讀不到就從資產重算。

⚠️ 狀態=◐ 半通,**別因為程式碼看起來完整就先合併**。
已實測:5 份 migration 在本機 D1 全數套用(含 0005);兩顆 worker 都能以改動後的
程式碼在本機開起來;tsc 錯誤數 7→7(既有,未新增)。
**沒跑到**:「砍掉 KV、資產還在」那一次端到端驗證——本次施工環境的權限閘不放行
執行 vitest/node/curl。那一次已寫成 scripts/verify-kv-retirement.sh,
在能執行的機器上跑一次就是證據。建議順序:先跑腳本、綠了再合併。

規格層依 D35 走 pending-changes.md「P-KV」提案,等 leo confirm(現行 active SDD
是 workflow-discovery,本案不在它的 tasks 內,故不自建 SDD、不改 rules 那張儲存表)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 16:51:58 +08:00

46 lines
3.5 KiB
SQL
Raw 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.
-- arcrun 資產型別 template seed — KV 退休(Leo/Arcrun#16 + #17
--
-- 為什麼有這一檔(leo 2026-08-12 原話):
-- 「我要的是寫進 KBDB,不是 KV,他的 Recipes、Cypher 是一段話,文字,數據,一個 entry」
-- 「如果零件和工作流的 recipe 不見了,是很可怕的事情」
-- 同一天(2026-08-12)真的發作過:一次例行更新讓使用者的九支工作流在畫面上全部消失
-- (根因見 cli/src/lib/resource-resolver.ts 檔頭 Arcrun#97——舊 deploy 會照名字新建一顆空 KV
-- 再綁上去)。#97 修的是「不要再把 worker 綁到空的資源上」;本卷修的是更根本的一句:
-- **使用者的資產本來就不該只存在於一個會被換掉的暫存層裡。**
--
-- KBDB 鐵律(leo 2026-06-14D38):三張表打天下,永遠不加新 table,新資料類型一律用 template。
-- 本檔**零 schema 異動**——只 INSERT OR IGNORE 四列 template 定義,手法與同目錄
-- 0003_library_map.sql / 0004_execution_log_template.sql 完全相同。
--
-- 儲存精神比照 0004execution_log)與 recipe-stattemplate 只負責「schema 文件化 +
-- GET /templates 可發現」,實際一筆資產是 entries 表的**一列**——
-- entry_type = 'workflow_def' | 'api_recipe' | 'auth_recipe' | 'prompt_recipe'
-- owner_id = 租戶(workflow 才有;recipe 是整台實例共用的庫,故為 NULL)
-- page_name = 該型別的自然鍵(workflow 名 / recipe uuid / service 名)
-- content = 給人看也給語意搜尋看的一句描述
-- metadata_json = 定義本體(graph / endpoint / inject … 原樣 JSON
-- ——不走 entry_values 全展開的多列 record:一支 workflow 的 graph 是一整包巢狀 JSON
-- 拆成 slot 多列既不會變得比較好查,反而讓「一筆資產=一列」這件事不再成立
-- recipe_stat 與 execution_log 早已示範「template 存在 + entries 直接存」這個模式合法)。
--
-- 讀寫一律走 HTTP API/entries、/entries/:id),呼叫端是 cypher-executor 的
-- src/lib/durable-store.ts。牆外沒有任何一行 SQL。
INSERT OR IGNORE INTO templates (id, name, description, slots_json, created_by)
VALUES
('tpl-workflow-def', 'workflow_def',
'工作流定義本體(KV 退休 #17)。一支工作流=entries 一列;graph/config/cron_expr 打包進 metadata_jsonWEBHOOKS KV 降為可丟棄的快取',
'["name","description","graph","config","cron_expr","created_at"]', 'system'),
('tpl-api-recipe', 'api_recipe',
'API recipe 定義本體(KV 退休 #16)。一份 recipeentries 一列;endpoint/headers/body/auth 等打包進 metadata_jsonRECIPES KV 降為快取。idx:* 反查索引屬衍生資料,不進 KBDB,由 durable-store 從本型別重建',
'["uuid","canonical_id","hash_id","author","endpoint","method","auth_service","installed"]', 'system'),
('tpl-auth-recipe', 'auth_recipe',
'Auth recipe 定義本體(KV 退休 #16)。一個服務一列;primitive/base_url/required_secrets/inject 打包進 metadata_json。只存「怎麼認證」,不存任何密文(憑證明文在 CF Workers Secrets,見 .claude/rules/01-tech-stack.md',
'["service","primitive","base_url","version","required_secrets","inject"]', 'system'),
('tpl-prompt-recipe', 'prompt_recipe',
'Prompt recipe 定義本體(KV 退休 #16)。一份 prompt recipeentries 一列,定義打包進 metadata_json',
'["name","definition"]', 'system');