fix(portal-data): 圖譜 neighbors/overview 按庫過濾(庫級權限紅線)[cloud-worker]

/portal/data/graph/neighbors:executeWebhookGraph input 加 libraries
('*' 或逗號清單),由 tenant workflow 的 code node 濾。
/portal/data/graph/overview:直讀 records 迴圈內按 library 濾(server-side,
隨 cypher 部署即生效,不需重推 workflow)。語意鏡像已部署的 keyword 面
('*'=不濾/NULL→general);hasGraphAccess 對空庫集合 fail-closed(403)。

配套產品包 workflow 濾在 arcrun-rag work/b5-graph-library-filter-0726。
未部署、未 e2e(雲端做到產物就緒)。
portal-auth(active SDD)tasks.md「graph 逐節點/逐邊細粒度過濾」庫級粒度。
This commit is contained in:
Claude
2026-07-25 20:58:18 +00:00
parent 139d4c5ed1
commit 3de93c86bc
+6 -1
View File
@@ -214,7 +214,7 @@ portalDataRouter.get('/portal/data/graph/neighbors/:name', (c) =>
const result = await executeWebhookGraph(
c.env,
wfGraph,
{ node: c.req.param('name'), depth, namespace: tenant, owner: tenant },
{ node: c.req.param('name'), depth, namespace: tenant, owner: tenant, libraries: libraries.includes('*') ? '*' : libraries.join(',') },
'graph_neighbors',
tenant,
c.executionCtx,
@@ -252,6 +252,7 @@ portalDataRouter.get('/portal/data/graph/overview', (c) =>
if (!(await hasGraphAccess(c.env, libraries))) {
return c.json({ error: '無知識圖譜檢視權限' }, 403);
}
const allowAll = libraries.includes('*');
const tenant = portalTenant(c.env);
const res = await kbdbFetch(c.env, `/records/by-template/triplet?owner_id=${encodeURIComponent(tenant)}`);
if (!res.ok) {
@@ -270,6 +271,10 @@ portalDataRouter.get('/portal/data/graph/overview', (c) =>
const v = r && typeof r.values === 'object' && r.values ? r.values : null;
if (!v) continue;
if (v.status === 'deprecated') continue;
if (!allowAll) {
const lib = typeof v.library === 'string' && v.library.trim() ? v.library.trim() : 'general';
if (!libraries.includes(lib)) continue;
}
const s = typeof v.subject === 'string' ? v.subject.trim() : '';
const o = typeof v.object === 'string' ? v.object.trim() : '';
if (!s || !o) continue;