feat(console): Mira Console 完整版——8 頁紙感定稿視覺 SPA (Arcrun#3 console 系)

依 claude design 定稿(紙感暖黑 2a)+ brief 8 頁資訊架構重寫 /console:
- 單檔 HTML+原生 JS hash routing,零外部資源;紙紋底/明體標題/琥珀強調/
  呼吸球嵌「安/趕/滯」;手機優先 390px + ≥1024px 側欄 + 底部五 tab
- 頁1 登入/首次設定(沿 console-auth v1)|頁2 駕駛艙(dashboard-data,60s 刷新;
  /console/dashboard 免登入獨立頁同步換視覺)|頁3 總庫搜尋(entry_type chips=
  KBDB 真能篩的欄位、共 N 筆中命中 M(誠實 total)、語意未啟用誠實降級 banner)|
  頁4 卡片詳頁+關聯(Markdown 渲染 + kbdb-graph-plugin 鄰居放射圖,經新 proxy
  /kbdb/graph/neighbors/:name;無 triplet →「尚無關聯資料」)|頁5 工作流
  (/webhooks/named list+手動觸發+最近執行;釘選 localStorage;v0 零件/recipes
  查詢收進本頁折疊區不砍功能)|頁6 憑證(新 GET /credentials/catalog D1 目錄
  唯讀,絕不回密文;新增/替換走既有端點;刪除未接 D1(T9)標「即將開通」)|
  頁7 收件匣(新 GET /console/inbox-data,session 鎖——訊息原文屬機敏)|
  頁8 設定(vectorize 狀態探測讀 search 降級訊號、開關標「即將開通」、
  /console/setup/reset 換帳密、系統資訊)

驗證:tsc exit 0;vitest 26/27(1 失敗 stash 複驗 pre-existing);wrangler
deploy --dry-run 打包過;inline JS 求值後 node --check + esc/mdRender/parseAtMs
純函式行為測試全過(含 XSS escape)。未部署,留總管接手。
This commit is contained in:
uncle6me-web
2026-07-04 17:49:49 +08:00
parent 5174ed6821
commit f9e44abc59
6 changed files with 1364 additions and 376 deletions
+25
View File
@@ -205,6 +205,31 @@ credentialsRouter.delete('/credentials/:name', async (c) => {
return c.json({ success: true, name });
});
// GET /credentials/catalog — D1 目錄唯讀 listMira Console 完整版,Arcrun#3 console 系)。
// 只回 metadataname/service/sensitivity/created_at/last_used_at),**絕不回密文值**——
// 密文在 Workers Secrets,本 worker 自己也讀不回(D19「擁有目錄,不擁有內容物」)。
// 與舊 GET /credentialsKV 名稱清單)並存:這裡是新制 D1 目錄;舊 KV 寫入的看不到(T5 已知誠實缺口)。
// 註冊須在 GET /credentials/:name 類 route 之前?本檔無 :name GET route,無攔截問題。
credentialsRouter.get('/credentials/catalog', async (c) => {
const apiKey = c.req.header('X-Arcrun-API-Key');
if (!apiKey) {
return c.json({ error: '缺少 X-Arcrun-API-Key header' }, 401);
}
try {
const rows = await c.env.CREDENTIALS_DB
.prepare(
`SELECT name, service, sensitivity, created_at, last_used_at
FROM credentials WHERE api_key = ? ORDER BY created_at DESC`,
)
.bind(apiKey)
.all<{ name: string; service: string | null; sensitivity: string; created_at: number; last_used_at: number | null }>();
return c.json({ success: true, credentials: rows.results ?? [], total: (rows.results ?? []).length });
} catch (e) {
// 誠實回報:D1 未建表 / migration 未跑(不假綠回空陣列裝沒事)
return c.json({ success: false, error: e instanceof Error ? e.message : String(e) }, 502);
}
});
// GET /credentials — 列出 credential 名稱(不含值)(未動:仍是舊 KV 路徑,T9 範圍)
credentialsRouter.get('/credentials', async (c) => {
const apiKey = c.req.header('X-Arcrun-API-Key');