fix(t115 🔴🔴🔴 三修): kbdb 認證完全 fail-closed——沒金鑰一律 401(含讀取)

leo 實證的洞=「知道網址即可讀走全部知識」;一修 fail-open(沒設 secret 就不擋)、
二修仍放行讀取=洞沒補。三修(總管手改):無 token→全部 401(health 豁免),
老實例升級路徑=重跑安裝器(同時注入金鑰與新 workflow),不以繼續外洩換相容。
+結構閘測試:斷言 src/index.ts 的無 token 分支不得有 return next()——
擋「測試複本與真實作漂移」那類假綠(本輪正是它抓到二修的複本沒同步)。
kbdb vitest 60/60 全綠(總管親跑)。
This commit is contained in:
uncle6me-web
2026-07-28 23:52:43 +08:00
parent 2ff36962be
commit f6728974ea
5 changed files with 239 additions and 0 deletions
+21
View File
@@ -14,6 +14,27 @@ import { mapRoutes } from './routes/map';
const app = new Hono<{ Bindings: Bindings }>();
// t115 global auth guard(三修=總管手改,fail-closed 到底).
// 為什麼不留讀取的寬容窗口:leo 07-28 實證的洞就是「知道網址即可讀走全部知識」——
// 讀取放行等於洞沒補。老實例的升級路徑是「重跑安裝器」(會同時注入 token 與新 workflow),
// 那條路本來就存在(t103 連動提示會叫用戶更新),不需要以繼續外洩為代價換相容。
// Health/ 與 /health)永遠豁免:daemon 的雲端版本偵測與監控要打得到。
app.use('*', async (c, next) => {
const path = new URL(c.req.url).pathname;
if (path === '/' || path === '/health') return next();
const token = c.env.KBDB_INTERNAL_TOKEN;
if (!token) {
// 沒有 token=這個實例還沒封口。一律拒絕(含讀取),並在訊息裡告訴維運怎麼修。
console.warn('[kbdb] KBDB_INTERNAL_TOKEN 未設定——全部請求拒絕,請重跑安裝器以注入金鑰');
return c.json({ error: 'Unauthorized', detail: 'kbdb 尚未設定內部金鑰,請重跑安裝器' }, 401);
}
const auth = c.req.header('Authorization');
if (!auth || auth !== `Bearer ${token}`) {
return c.json({ error: 'Unauthorized' }, 401);
}
return next();
});
app.get('/', (c) => c.json({ service: 'arcrun-kbdb', tier: 'base', status: 'ok' }));
app.get('/health', (c) => c.json({ ok: true }));