启动自检 issuer 不一致拒绝启动;路由覆盖 fail-closed;Keycloak 配置解析测试(ADR-012)

上一个任务把统一鉴权中心接上了,但缺配置照常起、issuer 配错也照常起 ——
每个请求都 401 还查不出原因。boot() 开头补两道保险:缺
KEYCLOAK_URL/REALM/CLIENT_ID 直接拒绝启动;配了就拉一次
.well-known/openid-configuration 核对 issuer,不一致同样拒绝启动
(话里带期望/实际/KC_HOSTNAME,照后端接入手册第 5 步)。

另加路由覆盖 it 测试:Hono 里每条注册路由都必须能在 appRouteRegistry()
里查到归属,查不到就是一个没人管的权限口子。真库跑通,96 条路由全部
有归属、0 条查不到——把上一个任务里人工核对的结论固化成测试。
This commit is contained in:
xcs
2026-08-25 18:04:21 +08:00
parent 8dc71db9d8
commit 61622f94d5
5 changed files with 185 additions and 0 deletions
+15
View File
@@ -5,6 +5,7 @@
import { serve } from '@hono/node-server';
import { loadConfig } from './config.ts';
import { createContainer } from './container.ts';
import { checkKeycloakConnection } from './keycloak-check.ts';
import { createServer } from './server.ts';
import { createConsumers } from './workers/consumers.ts';
import { dispatchOnce, startDispatcher } from './workers/dispatcher.ts';
@@ -13,6 +14,20 @@ import { registerPulse } from './workers/pulse.ts';
export async function boot(): Promise<void> {
const config = loadConfig();
if (config.keycloak === undefined) {
process.stderr.write(
'✗ 缺 KEYCLOAK_URL / KEYCLOAK_REALM / KEYCLOAK_CLIENT_ID —— 统一鉴权中心是唯一的登录途径,缺了谁也进不来(ADR-012)\n',
);
process.exit(1);
}
try {
const info = await checkKeycloakConnection(config.keycloak);
process.stdout.write(`✓ Keycloak 连通 · issuer=${info.issuer} · client=${info.clientId}\n`);
} catch (error) {
// 配置错了就别启动,免得跑起来每个请求都 401 还查不出原因(手册第 5 步)
process.stderr.write(`✗ Keycloak 连不上或配置有误:${error instanceof Error ? error.message : String(error)}\n`);
process.exit(1);
}
const container = await createContainer(config);
await container.org.ensureSeeded();