diff --git a/kbdb/src/actions/record-crud.ts b/kbdb/src/actions/record-crud.ts index 4e9664c..f0c7589 100644 --- a/kbdb/src/actions/record-crud.ts +++ b/kbdb/src/actions/record-crud.ts @@ -107,14 +107,28 @@ export async function getRecord(db: D1Database, recordId: string): Promise { const tpl = await getTemplate(db, template); if (!tpl) return []; - const res = await db - .prepare(`SELECT DISTINCT record_id FROM entry_values WHERE template_id = ? ORDER BY created_at DESC LIMIT ?`) - .bind(tpl.id, Math.min(limit, 500)) - .all<{ record_id: string }>(); + // owner_id 過濾在 SQL 做:record 的歸屬存在底層 entries.owner_id(createRecord 寫入時帶)。 + // 給了 owner_id → JOIN entries 限定該 owner(租戶隔離,cypher proxy 強制注入); + // 沒給 → 不限(內部/全域查詢)。先前 `|| true` 是 stub,會洩漏跨租戶資料(2026-06-14 修)。 + const cap = Math.min(limit, 500); + const res = owner_id + ? await db + .prepare( + `SELECT DISTINCT ev.record_id as record_id FROM entry_values ev + JOIN entries e ON ev.entry_id = e.id + WHERE ev.template_id = ? AND e.owner_id = ? + ORDER BY ev.created_at DESC LIMIT ?`, + ) + .bind(tpl.id, owner_id, cap) + .all<{ record_id: string }>() + : await db + .prepare(`SELECT DISTINCT record_id FROM entry_values WHERE template_id = ? ORDER BY created_at DESC LIMIT ?`) + .bind(tpl.id, cap) + .all<{ record_id: string }>(); const out: RecordResult[] = []; for (const { record_id } of res.results ?? []) { const rec = await getRecord(db, record_id); - if (rec && (!owner_id || true)) out.push(rec); + if (rec) out.push(rec); } return out; }