ceb7638d74
規格:system-dev/docs/3-specs/pending-changes.md「record 要有身分」v7 定稿(leo 2026-08-15 confirm)。 模型一句話(leo):「真身在 pool 的 entry 裡,所有的虛擬表虛擬欄位都是指向這個 entry 的指標。」 - 0007 migration:池上型別化指標欄(src/rel/dst)+一對方向 partial index+啟動常數 (sys_root/sys_belongs/sys_field_of)+templates 鏡射成 sheet/field entry+ 每筆 record 一顆身分 entry(id=原 record_id,引用不失效)+每格一條關係列 (id 由舊儲存格列 id 衍生 ⇒ INSERT OR IGNORE 天然冪等)+拆 entry_values (0006 墊表→搬→拆手法)。純 INSERT、value entries 一列不動(向量索引不失效)。 - record-crud 整份改寫到關係列(#128 指標語意/共用保護/N+1 批次/租戶過濾全數保留, 驗收測試 232→236 綠);library-map 四段縱轉橫 SQL、records triplet-stats 改查關係列。 - entry-crud:機制列隔離(未指定 entry_type 的列表/搜尋不回機制節點);deleteEntry 接手舊 entry_values FK 的不變量(dst 被指著→拒刪)。 - 孤兒偵測重設計(v7 §5 點名):新模型孤兒=指標指向不存在 id 的關係列, LEFT JOIN 斷鏈掃描(承接 2026-06-24 清理事故的 FK 形狀), GET /maintenance/relation-orphans 唯讀巡檢。 - cli deploy.ts:0007 逐句套用+容錯 duplicate column(SQLite 無欄位級 IF NOT EXISTS, 整檔送 /query 會在重跑時假紅)。 - 測試:tree-record-migration.test.ts 驗資料零漏/雙跑冪等/孤兒掃描; 釘死三表的斷言依 confirm 後規格改口(execution-log/credential-legacy 兩處)。 遷移期雙軌(第二刀收):templates 表仍是欄位定義真相源;六種 metadata_json 打包型 與 §7 減法封鎖(拿掉 entry_type/metadata_json 欄)留待第二刀。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
4.8 KiB
TypeScript
104 lines
4.8 KiB
TypeScript
// KBDB Base types. Base depends on D1 only.
|
||
// Optional modules add their own bindings (embed: VECTORIZE+AI). Base never references them.
|
||
|
||
export type Bindings = {
|
||
DB: D1Database;
|
||
ENVIRONMENT: string;
|
||
// Auth guard (t115 二修, fail-closed): provisioned by the installer automatically.
|
||
// NOT set → writes (POST/PATCH/DELETE/PUT) rejected 401; reads pass with a warning
|
||
// (upgrade-window grace so read-only workflows don't break before both workers are
|
||
// updated together).
|
||
// SET → all non-health routes require `Authorization: Bearer <token>`.
|
||
// cypher-executor sends this via kbdbBase(); portal/webhooks/recipes send it inline.
|
||
KBDB_INTERNAL_TOKEN?: string;
|
||
// Optional embed module (issue #7 / SDD T2.4). Present ONLY when the self-host opened
|
||
// semantic search (kbdb_embed:true → deploy injects [[vectorize]] + [ai]). Base never
|
||
// requires them; code checks `if (env.VECTORIZE && env.AI)` before touching embed.
|
||
VECTORIZE?: VectorizeIndex;
|
||
AI?: Ai;
|
||
// 嵌入模型(Arcrun#59)。未設=用 embed.ts 的預設。設成別的模型時,**Vectorize index 的
|
||
// dimensions 必須跟著對**(維度不合 upsert 會被 CF 拒絕),且換模型必須換 index:
|
||
// 不同模型的向量不可共存於同一個 index(比對出來是垃圾),詳見 embed.ts 檔頭。
|
||
EMBED_MODEL?: string;
|
||
// execution_log 每日軟上限(KV 額度事故修復,2026-08-07;A2 自我降級,見
|
||
// kbdb/src/actions/execution-log.ts DEFAULT_DAILY_LIMIT 說明)。未設 → 20000
|
||
// (D1 100,000 rows written/日的 20%,留 80% 給知識卡 entries)。
|
||
EXECUTION_LOG_DAILY_WRITE_LIMIT?: string;
|
||
// embed backfill 每日軟上限(D68,2026-08-11:補算向量照時間新到舊、且每天有額度上限)。
|
||
// backfill 與「寫入即嵌」「萃取」共用同一份 Workers AI 每日 10,000 免費 neurons(見頂層
|
||
// wiki ops-facts.md);backfill 是背景低優先動作,自設軟上限不把當天額度燒光。未設 → 見
|
||
// kbdb/src/embed.ts DEFAULT_BACKFILL_DAILY_LIMIT 說明(含選值算式,非拍腦袋)。
|
||
EMBED_BACKFILL_DAILY_LIMIT?: string;
|
||
// 背景維護寫入(reconcile 世代核對 + 標庫 backfill)共用的 D1 每日寫入軟上限
|
||
// (Arcrun#85 D69 修法,2026-08-11:兩者都是「多筆 D1 row write、不打 AI」的操作,
|
||
// 各自不設防都會單獨燒穿 D1 100,000 rows/日免費額度——reconcile 47 萬筆 candidate
|
||
// ≈ 4.7 倍全日額度,已在票上實測;標庫 backfill 同樣是逐筆 D1 write,若各管各的,
|
||
// 補標庫時會把 reconcile 的閘繞過去。兩者共用同一顆「今天還剩多少」計數器。
|
||
// 未設 → 見 kbdb/src/actions/maintenance-quota.ts DEFAULT_MAINTENANCE_DAILY_WRITE_LIMIT。
|
||
KBDB_MAINTENANCE_DAILY_WRITE_LIMIT?: string;
|
||
};
|
||
|
||
export type EntryType =
|
||
| 'block'
|
||
| 'value'
|
||
| 'template'
|
||
| 'slot'
|
||
| 'project'
|
||
| 'workflow'
|
||
| 'recipe_stat'
|
||
| 'execution_log'
|
||
| 'execution_log_usage'
|
||
| 'embed_backfill_usage'
|
||
| 'kbdb_maintenance_usage'
|
||
// 樹狀 record 模型(0007,v7 定稿 2026-08-15):機制節點與關係列。
|
||
// 誠實註記:entry_type 在 v7 §7 的白名單終局裡會整欄消失(型別只能由關係推導),
|
||
// 這裡先沿用它做遷移期的機制列標記——程式邏輯一律以指標欄(src_id IS NOT NULL)判斷
|
||
// 「是不是關係列」,不依賴這個標記。
|
||
| 'relation' // 一列關係:src ─rel→ dst(池上型別化指標欄)
|
||
| 'record' // record 的裸身分 entry(block 即 record 時身分是那顆 block,不是這個型別)
|
||
| 'sheet' // 一張表(template 在池中的身分,id 沿用 template id)
|
||
| 'field' // 一個欄位(欄名=關係的謂詞)
|
||
| 'system'; // 啟動常數(sys_root / sys_belongs / sys_field_of)
|
||
|
||
export interface Entry {
|
||
id: string;
|
||
content: string | null;
|
||
entry_type: EntryType | string;
|
||
owner_id: string | null;
|
||
parent_id: string | null;
|
||
page_name: string | null;
|
||
refs_json: string;
|
||
tags_json: string;
|
||
task_status: string | null;
|
||
content_hash: string | null;
|
||
is_embedded: number;
|
||
confidence: number | null;
|
||
metadata_json: string | null;
|
||
// 關係的物理載體(0007):池上型別化指標欄。內容 entry 三欄全 NULL;
|
||
// 關係列三欄全非 NULL(src ─rel→ dst)。紅線:指標永不塞回 content/JSON(D91)。
|
||
src_id: string | null;
|
||
rel_id: string | null;
|
||
dst_id: string | null;
|
||
created_at: number;
|
||
updated_at: number;
|
||
}
|
||
|
||
export interface Template {
|
||
id: string;
|
||
name: string;
|
||
description: string | null;
|
||
slots_json: string;
|
||
created_by: string | null;
|
||
created_at: number;
|
||
updated_at: number;
|
||
}
|
||
|
||
export interface EntryValue {
|
||
id: string;
|
||
record_id: string;
|
||
template_id: string;
|
||
slot_name: string;
|
||
entry_id: string;
|
||
created_at: number;
|
||
}
|