補上合併漏收的修改檔(t189/t181/CIS portal 本體)

上一筆 5d78806 我只 add 了新增檔(favicon 三件套),四個修改檔沒收進去
⇒ 合併內容只推了一半,t189 的 tenant 比對修復其實還躺在工作區。

本次補上(實測與已刪分支 HEAD 23f2fd4 逐檔相同):
· cypher-executor/src/routes/portal.ts      +81(t181 /portal/daemon/extract、t189 tenant)
· cypher-executor/src/routes/portal-data.ts +21
· console-ui/public/portal/index.html      +169(CIS 視覺、版本卡)
· cypher-executor/tests/portal-admin.test.ts +45

教訓:merge --no-commit 後要 git add -A,不能只 add status 裡看到的第一類。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-08-05 13:31:57 +08:00
parent 5d78806806
commit 6c5706ba7d
4 changed files with 284 additions and 32 deletions
@@ -629,3 +629,48 @@ describe('GET /portalP4 admin 頁 HTML 殼)', () => {
});
});
// t131/t122 測試已隨 main 的 t176(刪除雲端下發 LLM 設定)一併移除;
// 此處只保留 t181daemon 走 Workers AI)的守衛。
describe('POST /portal/daemon/extractt181Workers AI 萃卡,免金鑰)', () => {
// 認證=X-Arcrun-API-Key(=namespacewrangler.test.toml CONSOLE_TENANT=leo),
// **不是帳密**:daemon 密碼不落地(連線精靈用完即丟),背景萃取拿不到密碼。
const KEY = { 'X-Arcrun-API-Key': 'leo' };
it('沒帶 API Key → 401', async () => {
const res = await json('POST', '/portal/daemon/extract', { page_name: 'x', text: 'y' });
expect(res.status).toBe(401);
});
// 🔴 t189:這則原本是「API Key 錯 → 401(租戶隔離)」,**是錯的,而且害我看到假綠**。
//
// 它假設「daemon 的 api_key 實例的 CONSOLE_TENANT」,但實測不成立:
// geek6688tenant=ckxt8yr9、daemon api_key=yuga3bse ⇒ 真用戶**永遠 401**、萃不了
// youlin :兩者碰巧相同 ⇒ 我這邊測起來都對
// 舊測試只證明「符合我的假設」,不證明「假設是對的」——
// **把錯誤假設寫成測試,就是把假綠焊死。**
//
// 翻轉成守衛:**key 與 tenant 不同也要能萃**(這正是 leo 撞到的情境)。
// 若哪天有人又加回等值比對,這則會紅。
it('key 與實例 tenant 不同也要能用(t189:多帳號 daemon 的常態)', async () => {
const res = await json('POST', '/portal/daemon/extract',
{ page_name: 'x', text: 'y' }, { 'X-Arcrun-API-Key': 'another-tenant-key' });
expect(res.status).not.toBe(401);
});
it('缺 page_name 或 text → 400(不打 AI、不假裝成功)', async () => {
const res = await json('POST', '/portal/daemon/extract', {}, KEY);
expect(res.status).toBe(400);
const d = (await res.json()) as { error?: string };
expect(String(d.error)).toContain('page_name');
});
// 🔴 回歸守衛:這條路**不得**要求任何 Gemini/API 金鑰——免金鑰正是它存在的理由。
// 若哪天有人把它改回打 Google,錯誤訊息會出現 credential/gemini_api_key ⇒ 這則會紅。
it('錯誤訊息不得要求任何金鑰(免金鑰是本端點存在的理由)', async () => {
const res = await json('POST', '/portal/daemon/extract', {}, KEY);
const raw = await res.text();
expect(raw).not.toContain('gemini_api_key');
expect(raw).not.toContain('credential');
});
});