portal-auth P1(#24 #25):KBDB library filter 地基(不 merge,待總管審) #50

Merged
Leo merged 1 commits from portal-auth-p1-library-filter into main 2026-07-14 03:50:07 +00:00
Owner

portal-auth SDD P1(system-dev/docs/3-specs/portal-auth/,design §3.2/§3.3)。只動 kbdb/+SDD tasks.md,不碰 cypher-executor/portal。不 merge,待總管審。

Vectorize $in 核實結論(P1 開工第一件事)

支援,走主路徑 $in,不需 fan-out fallback。

  • 官方文件(developers.cloudflare.com/vectorize/reference/metadata-filtering/)明列 8 運算子 $eq/$ne/$in/$nin/$lt/$lte/$gt/$gte;「For $in and $nin, filter object values can be arrays of string, number, boolean, or null values」。
  • 本 repo @cloudflare/workers-types@4.20260702.1 原生 typing VectorizeVectorMetadataFilterCollectionOp = "$in" | "$nin"(index.d.ts:15782);wrangler 4.98.0。
  • 限制:metadata filtering 只對 2023-12-06 後建的 index 有效(本專案 index 皆是)。

改動

內容
kbdb/src/actions/entry-crud.ts listEntries/searchEntrieslibrary?: string[];謂詞 COALESCE(json_extract(metadata_json,'$.library'),'general') IN (…)(≡ design §3.3 OR 形狀,語意相同、單組佔位符)
kbdb/src/routes/entries.ts GET /entriesGET /entries/searchlibrary 逗號多值參數;空值→不過濾
kbdb/src/embed.ts upsert metadata 加 library寫入端正規化:未標記→'general',因 Vectorize filter 做不了 COALESCE);semanticSearch 支援 library filter $in;backfill/reindex 向量同步帶 library;SemanticHit 加 library 欄
kbdb/wrangler.toml 部署註解補 library metadata index 指令+reindex 提醒
kbdb/tests/library-filter.test.ts 新增 11 測試
SDD tasks.md P1 各項標 [x]、核實結論、部署清單附註

驗收證據(本機真跑)

  • tsc --noEmit exit 0;vitest 17/17 綠(新 11+既有 6)。
  • 獨立 kbdb dev instance(port 8799、獨立 persist state,8787/8788 demo 未動)+ wrangler d1 migrations apply --local,灌 5 筆(finance/hr/無 metadata/有 metadata 無 library/顯式 general):
案例 結果
/entries?q=P1TEST(不帶 library) 5/5 全回(向後相容硬驗收
?library=finance 只回 finance 1 筆
?library=finance,hr 2 筆
?library=general 3 筆=未標記 2+顯式 general 1(NULL→general fallback
?library=nonexistent 0 筆
/entries/search?q=…(不帶) 5/5
search?library=hrlibrary=general,finance 1 筆/4 筆
search?mode=semantic&library=finance(無 Vectorize) 誠實降級 keyword+requested_mode:semanticlibrary 仍 enforce(1 筆)
search?owner_id=t1&entry_type=block 舊參數組合 5/5 不變

誠實邊界

  • semantic 線上路徑未驗(本機無 Vectorize runtime):code 完成+mock 測試綠,$in 實跑待雲端排練。

部署清單(待雲端排練驗)

  1. wrangler vectorize create-metadata-index arcrun-kbdb-embed --property-name library --type string
  2. POST /embed/backfill {"reindex":true} 分批到 remaining=0(metadata index 只收建立後 upsert 的向量,不 reindex 則帶 library filter 一律 0 命中)
  3. 驗收抽查:semantic 帶 library= 命中正確;不帶行為不變
  4. 掛號:cli/src/lib/deploy.ts ensureVectorizeMetadataIndexes() 待補 library(cli/ 屬本次派工範圍外)

範圍矛盾註記(給總管)

tasks.md P1 原含「cypher kbdb-proxy 透傳 library」,與派工紅線「只動 kbdb」矛盾——照窄範圍執行,該項留 [ ] 順延(一行 query 透傳,建議隨 P3 動 cypher 時一併)。

portal-auth SDD P1(`system-dev/docs/3-specs/portal-auth/`,design §3.2/§3.3)。只動 `kbdb/`+SDD tasks.md,不碰 cypher-executor/portal。**不 merge,待總管審。** ## Vectorize `$in` 核實結論(P1 開工第一件事) **支援,走主路徑 `$in`,不需 fan-out fallback。** - 官方文件(developers.cloudflare.com/vectorize/reference/metadata-filtering/)明列 8 運算子 `$eq/$ne/$in/$nin/$lt/$lte/$gt/$gte`;「For $in and $nin, filter object values can be arrays of string, number, boolean, or null values」。 - 本 repo `@cloudflare/workers-types@4.20260702.1` 原生 typing `VectorizeVectorMetadataFilterCollectionOp = "$in" | "$nin"`(index.d.ts:15782);wrangler 4.98.0。 - 限制:metadata filtering 只對 2023-12-06 後建的 index 有效(本專案 index 皆是)。 ## 改動 | 檔 | 內容 | |---|---| | `kbdb/src/actions/entry-crud.ts` | `listEntries`/`searchEntries` 加 `library?: string[]`;謂詞 `COALESCE(json_extract(metadata_json,'$.library'),'general') IN (…)`(≡ design §3.3 OR 形狀,語意相同、單組佔位符) | | `kbdb/src/routes/entries.ts` | `GET /entries`、`GET /entries/search` 接 `library` 逗號多值參數;空值→不過濾 | | `kbdb/src/embed.ts` | upsert metadata 加 `library`(**寫入端正規化**:未標記→`'general'`,因 Vectorize filter 做不了 COALESCE);`semanticSearch` 支援 `library` filter `$in`;backfill/reindex 向量同步帶 library;`SemanticHit` 加 library 欄 | | `kbdb/wrangler.toml` | 部署註解補 library metadata index 指令+reindex 提醒 | | `kbdb/tests/library-filter.test.ts` | 新增 11 測試 | | SDD `tasks.md` | P1 各項標 [x]、核實結論、部署清單附註 | ## 驗收證據(本機真跑) - `tsc --noEmit` exit 0;vitest **17/17 綠**(新 11+既有 6)。 - 獨立 kbdb dev instance(port 8799、獨立 persist state,8787/8788 demo 未動)+ `wrangler d1 migrations apply --local`,灌 5 筆(finance/hr/無 metadata/有 metadata 無 library/顯式 general): | 案例 | 結果 | |---|---| | `/entries?q=P1TEST`(不帶 library) | **5/5 全回(向後相容硬驗收 ✅)** | | `?library=finance` | 只回 finance 1 筆 | | `?library=finance,hr` | 2 筆 | | `?library=general` | 3 筆=未標記 2+顯式 general 1(**NULL→general fallback ✅**) | | `?library=nonexistent` | 0 筆 | | `/entries/search?q=…`(不帶) | 5/5 | | `search?library=hr`/`library=general,finance` | 1 筆/4 筆 | | `search?mode=semantic&library=finance`(無 Vectorize) | 誠實降級 keyword+`requested_mode:semantic`,**library 仍 enforce**(1 筆) | | `search?owner_id=t1&entry_type=block` 舊參數組合 | 5/5 不變 | ## 誠實邊界 - **semantic 線上路徑未驗**(本機無 Vectorize runtime):code 完成+mock 測試綠,`$in` 實跑待雲端排練。 ## 部署清單(待雲端排練驗) 1. `wrangler vectorize create-metadata-index arcrun-kbdb-embed --property-name library --type string` 2. `POST /embed/backfill {"reindex":true}` 分批到 `remaining=0`(metadata index 只收建立後 upsert 的向量,不 reindex 則帶 library filter 一律 0 命中) 3. 驗收抽查:semantic 帶 `library=` 命中正確;不帶行為不變 4. 掛號:`cli/src/lib/deploy.ts` `ensureVectorizeMetadataIndexes()` 待補 `library`(cli/ 屬本次派工範圍外) ## 範圍矛盾註記(給總管) tasks.md P1 原含「cypher `kbdb-proxy` 透傳 library」,與派工紅線「只動 kbdb」矛盾——照窄範圍執行,該項留 `[ ]` 順延(一行 query 透傳,建議隨 P3 動 cypher 時一併)。
Leo added 1 commit 2026-07-14 03:46:16 +00:00
- /entries 與 /entries/search 加 library 多值參數(逗號分隔);不帶=行為一字不變(向後相容)
- D1:COALESCE(json_extract(metadata_json,'$.library'),'general') IN (…)(≡ design §3.3 OR 形狀;
  未標記舊資料歸 general)
- semantic:Vectorize upsert metadata 加 library(寫入端正規化 general);查詢 filter $in 主路徑
  (官方文件+workers-types 4.20260702.1 核實支援,fan-out fallback 不需)
- 測試:library-filter.test.ts 11 項+既有 6 項全綠;tsc exit 0;本機 miniflare local D1 十案例實跑全過
- semantic 線上路徑(metadata index+reindex backfill)=部署清單,待雲端排練驗(本機無 Vectorize)
- cypher kbdb-proxy 透傳順延(P1 派工紅線只動 kbdb,tasks.md 已註)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Leo merged commit 7f409646e5 into main 2026-07-14 03:50:07 +00:00
Sign in to join this conversation.