D38:credential 目錄改走 KBDB API(零原生 SQL)+舊表退場;測試刻意留紅燈

存取層:credentials.ts / auth-dispatcher.ts / portal.ts 全改走 kbdbBase()+fetch
到 /entries(照 execution-logger.ts 既有慣例),.prepare/.exec/.batch 命中 0。
資料層:0005 seed credential template;0006 把舊表資料搬進 entries 後拆表;
0002 標退役、deploy.ts 不再套用(加 kbdb-sql-ok 留痕,純歷史對照)。

總管親驗四項(不聽 agent 自評):
1 三個檔 .prepare/.exec/.batch 命中 0;六個檔全部通過 kbdb-api-wall-guard
2 0006 的 INSERT 欄位(id/entry_type/owner_id/page_name/metadata_json/
  created_at/updated_at)與 0001_base 的 entries 表逐一對得上
3 不可逆風險查官方:D1 batch 是 transaction、任一句失敗整批 rollback;
  exec 出錯則「執行停止、後續不執行」=> 兩種語意下 INSERT 失敗都不會跑到
  DROP TABLE,用戶 credential 目錄不會遺失
4 0006 搬在拆之前、冪等(NOT EXISTS 防重複)、豁免標記有留痕且理由正當
  (拆表是牆內施工,API 不提供也不該提供拆表)

🔴 抓到一個假綠並修正:agent 中途被中斷,把 111 行的 credentials.test.ts
砍成一行「// placeholder — see edit below」,那個 edit 從來沒發生,
且 setup.ts 被刪。vitest 對這種檔案回報「Tests: no tests」,
很容易被讀成「沒失敗=通過」——正是 CP 記過的
「這條 route 曾整條消失過沒人發現」同型。
處置:還原 setup.ts/vitest.config.ts,credentials.test.ts 改成
**刻意會失敗的紅燈**並在檔頭列出要補的五項。空檔會被誤認為綠,紅燈不會。

未部署。本批要先上 stage 驗過才進 prod(leo 08-07 定)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-08-07 17:27:18 +08:00
parent 60688c3108
commit 7ba78552a4
7 changed files with 343 additions and 244 deletions
+4 -7
View File
@@ -27,7 +27,7 @@ import { hashPassword, verifyPassword, randomHex, generatePassword } from '../li
import { PORTAL_TEMPLATE_SEEDS } from '../lib/portal-seeds';
// arcrun-rag#10/portal/admin/ai 存 Gemini key 走 credentials.ts 的**唯一**寫入路徑,
// 不在 portal 這層另造第二套儲存(D36:值進 Workers SecretD1 只留 ref)。
import { storeCredential } from './credentials';
import { storeCredential, hasCredential } from './credentials';
export const portalRouter = new Hono<{ Bindings: Bindings }>();
@@ -1170,13 +1170,10 @@ portalRouter.get('/portal/admin/ai', (c) =>
const tenantSlug = portalTenant(c.env);
let hasKey = false;
try {
const row = await c.env.CREDENTIALS_DB
.prepare('SELECT 1 FROM credentials WHERE api_key = ? AND name = ? LIMIT 1')
.bind(tenantSlug, 'gemini_api_key')
.first();
hasKey = !!row;
// D38 圍牆修復(2026-08-07):改走 credentials.ts 的 KBDB 目錄查詢,不直連 D1。
hasKey = await hasCredential(c.env, tenantSlug, 'gemini_api_key');
} catch {
// D1 未就緒 ⇒ 當作沒設定(不擋頁面),但也不假裝有
// KBDB 不可達 ⇒ 當作沒設定(不擋頁面),但也不假裝有
hasKey = false;
}