feat: KBDB-graph 插件獨立 — 全面改寫成走基本盤 API(API-as-Wall)
按 leo 鐵律(2026-06-14)把插件從「直接 SQL 操作基本盤表」改寫成 「只透過基本盤 arcrun/kbdb HTTP API 讀寫」。零建表、零 migration、零 SQL。 - 新增 src/lib/kbdb-client.ts:唯一對外通道,封裝 entries/templates/records API - 新增 src/lib/templates.ts:triplet/entity template 定義(替代建表) - 改寫 21 個違規 action(triplet/graph/entity/search)→ 走 client,圖在插件層記憶體組裝 - 移除所有 migrations、D1/Vectorize/AI 綁定;embedding/語意搜尋歸基本盤 optional 模組 - index.ts 只掛 triplets/graph/entities/search 路由;基本盤路由歸 arcrun/kbdb - 測試改走 mock client(純 node);裁剪 CLAUDE.md 只留 graph 插件 + 鐵律 - 修正 SDD design.md「讀現狀推翻鐵律」的錯誤判斷(共用 D1 → API-as-Wall) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# BUG: PATCH /blocks/:id 回 403 "block belongs to different org"(同一把 key 能 create/get/delete 卻不能 patch)
|
||||
|
||||
> 回報日期:2026-05-29
|
||||
> 回報來源:arcrun Phase 2(把 kbdb_* 零件降級成 recipe,逐個驗收時發現)
|
||||
> 嚴重度:中高 —— PATCH endpoint 對「自己剛建、且能刪的 block」拒絕更新,等於 update 能力全壞
|
||||
> 影響:任何「查→改」或 upsert 流程(先 GET 找到 block,再 PATCH 更新)都無法完成
|
||||
|
||||
---
|
||||
|
||||
## 症狀
|
||||
|
||||
用**同一把 API key**、對**同一個 block**,四個操作的結果不一致:
|
||||
|
||||
| 操作 | endpoint | HTTP | 結果 |
|
||||
|---|---|---|---|
|
||||
| 建立 | `POST /blocks` | **201** | ✅ 建出 block,回 id |
|
||||
| 讀取 | `GET /blocks/:id` | **200** | ✅ 讀得到 |
|
||||
| **更新** | **`PATCH /blocks/:id`** | **403** | ❌ `{"error":"block belongs to different org"}` |
|
||||
| 刪除 | `DELETE /blocks/:id` | **200** | ✅ `{"deleted":true}` |
|
||||
|
||||
**矛盾點**:同一把 key 能 create / get / delete 這個 block —— 代表 KBDB 認定我擁有它(org 一致)。但 PATCH 卻說「belongs to different org」。**create 寫進去的 org 判定,和 patch 讀出來比對的 org 判定不一致**,這是 KBDB 內部 org 歸屬邏輯的 bug。
|
||||
|
||||
## 重現(裸 curl,不經 arcrun)
|
||||
|
||||
為排除是 arcrun 注入問題,直接用裸 curl + Bearer token 打 `https://kbdb.finally.click`:
|
||||
|
||||
```bash
|
||||
TOKEN="Bearer ak_402d…" # 同一把 key,全程不變
|
||||
BASE=https://kbdb.finally.click
|
||||
|
||||
# 1. 建立 → 201
|
||||
curl -X POST $BASE/blocks -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
|
||||
-d '{"content":"...","type":"note","page_name":"kbdb_bug_repro","source":"...","user_id":"arcrun_phase2"}'
|
||||
# → {"id":"f39ea877-...","action":"created"} HTTP 201
|
||||
|
||||
# 2. 讀取 → 200
|
||||
curl $BASE/blocks/f39ea877-... -H "Authorization: $TOKEN"
|
||||
# → HTTP 200
|
||||
|
||||
# 3. 更新 → 403 ★ BUG
|
||||
curl -X PATCH $BASE/blocks/f39ea877-... -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
|
||||
-d '{"content":"patched"}'
|
||||
# → {"error":"block belongs to different org"} HTTP 403
|
||||
|
||||
# 4. 刪除 → 200(證明我擁有此 block)
|
||||
curl -X DELETE $BASE/blocks/f39ea877-... -H "Authorization: $TOKEN"
|
||||
# → {"deleted":true} HTTP 200
|
||||
```
|
||||
|
||||
經 arcrun(cypher-executor → auth_static_key 注入同一把 token → recipe 轉發)也是完全相同結果,所以**確定是 KBDB server 端 PATCH 路徑的問題,不是 client / arcrun 的問題**。
|
||||
|
||||
## 推測方向(給 KBDB 排查)
|
||||
|
||||
create / get / delete 的 org 判定路徑,和 PATCH 的 org 判定路徑不一致。可能:
|
||||
|
||||
1. **PATCH 用了不同的 org 解析來源**:例如 create 用 token → org_id 的某種映射寫入 block,但 PATCH 的 org-check 從另一個欄位 / 另一張表讀,兩邊算出的 org 不同。
|
||||
2. **block 落地時的 org_id 與 token 的 org_id 不一致**:create 時可能用了 default org 或 null org 寫入,PATCH 的 ownership 檢查卻嚴格比對 token org,導致「自己建的卻不是自己 org」。
|
||||
3. **org-check 是 PATCH 獨有、其他三個 verb 沒做**:所以只有 PATCH 露出這個不一致。
|
||||
|
||||
建議從「create 時 block 實際寫入的 org_id」對比「PATCH org-check 讀的 org_id」兩個值下手,它們應該相等卻不等。
|
||||
|
||||
## 對 arcrun 的影響(已隔離,不阻擋 arcrun Phase 2)
|
||||
|
||||
- arcrun 已把 `kbdb_patch_block` 降級成 recipe,recipe 的轉發 + auth 注入經驗證**正確無誤**(請求成功打到 KBDB 的 PATCH handler,非 401)。
|
||||
- 403 屬 KBDB 端行為,依 arcrun 原則「能不能打通由發 key 的服務裁決」,這不是 recipe 的 bug。
|
||||
- 但 arcrun 的 `kbdb_upsert_block`(GET 查找 → 分支 PATCH/POST)會用到 PATCH,**此 bug 未解前,upsert 的 PATCH 分支無法驗收 2xx**。arcrun 端會把該分支標「未驗收:阻擋於 KBDB PATCH 403」。
|
||||
|
||||
KBDB 修好後請通知 arcrun,重跑 `kbdb_patch_block` recipe 驗收即可。
|
||||
Reference in New Issue
Block a user