fix(portal): 讀不到就說讀不到——總圖不再把「讀不到」畫成「你沒有」(Arcrun#100)

leo 2026-08-12 打開總圖看到:「0 個實體 · 0 條關聯/知識庫還沒有任何關聯——
上傳文件後 AI 會自動織網」。**而他庫裡有 1854 條三元組。**
那句話會叫他去做一件不需要做的事。

三個獨立的洞疊起來才變成那句謊:
  ① console-dashboard.ts 打 kbdb-graph-plugin 沒帶認證(同段落打 kbdb 的兩支都有帶)
  ② 那顆 worker 不在更新的部署清單裡 ⇒ token 一換它就落單
  ③ **畫面把 null 畫成 0**——後端已經誠實回 null 了,是前端把它變成謊話

為什麼一直沒被發現:graph plugin 原本身上沒有 token ⇒ 門開著 ⇒ 沒帶也進得去。
2026-08-12 輪替後它有了 token,門關上,401 才浮出來。

📍 repo:matrix/arcrun(cypher-executor/src/routes/、console-ui/public/)
📍 票:Leo/Arcrun#100
This commit is contained in:
uncle6me-web
2026-08-12 13:33:53 +08:00
parent e69d6bbc03
commit a5e4caf5cb
9 changed files with 410 additions and 28 deletions
+16 -2
View File
@@ -223,13 +223,27 @@ export function graphBase(env: Bindings): string {
return `https://kbdb-graph-plugin.${env.WORKER_SUBDOMAIN}.workers.dev`;
}
/**
* kbdb-graph-plugin 的 internal headers。**打 plugin 一律用這支,不要各自手拼**Arcrun#100)。
*
* plugin 端(kbdb-graph-plugin/src/index.ts)對 `/triplets` `/graph` `/search` `/entities`
* 四個前綴掛了 Bearer 閘:設了 KBDB_INTERNAL_TOKEN 就必須帶,否則一律 401。
* 原本三處手拼(本檔 neighbors、portal-data neighbors、console-dashboard 兩支 stats),
* 前兩處帶了、後兩處漏了 → `/triplets/stats` 永遠 401 → 前端「三元組 0」。
* 收斂成一支函式=新的呼叫點不可能再漏(漂移的根,不是那兩行本身)。
*/
export function graphHeaders(env: Bindings): Record<string, string> {
const headers: Record<string, string> = {};
if (env.KBDB_INTERNAL_TOKEN) headers['Authorization'] = `Bearer ${env.KBDB_INTERNAL_TOKEN}`;
return headers;
}
// GET /kbdb/graph/neighbors/:name — 查某節點(entity/卡片名)的鄰居 + 邊。
// 查無 triplet 資料時 plugin 回空陣列——前端據此顯示「尚無關聯資料」(誠實,不編造關聯)。
kbdbProxyRouter.get('/kbdb/graph/neighbors/:name', async (c) => {
if (!tenant(c)) return c.json(NEED_KEY, 401);
const base = graphBase(c.env);
const headers: Record<string, string> = {};
if (c.env.KBDB_INTERNAL_TOKEN) headers['Authorization'] = `Bearer ${c.env.KBDB_INTERNAL_TOKEN}`;
const headers = graphHeaders(c.env);
try {
const res = await fetch(`${base}/graph/neighbors/${encodeURIComponent(c.req.param('name'))}`, { headers });
return new Response(res.body, { status: res.status, headers: { 'Content-Type': 'application/json' } });