// SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-desktop-view-density. // SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-multi-web-probe-sentinel. // SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p10-monitor-web-aggregation. // SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-27-p11-monitor-web-observability-dashboard. // Responsibility: Static dashboard shell and asset serving for the web-probe sentinel frontend. import { readFileSync } from "node:fs"; import { rootPath } from "./config"; interface DashboardShellConfig { readonly node: string; readonly lane: string; readonly sentinelId: string; readonly plan: { readonly ok: boolean; readonly sentinels?: readonly Record[] }; readonly publicExposure: Record; } const DASHBOARD_ASSET_ROOT = "scripts/assets/web-probe-sentinel-dashboard"; const MONITOR_WEB_ASSET_ROOT = "scripts/assets/web-probe-sentinel-monitor-web"; const DASHBOARD_CONTRACT_VERSION = "draft-2026-06-27-p11-monitor-web-observability-dashboard"; export function renderWebProbeSentinelDashboardHtml(config: DashboardShellConfig): string { const publicOrigin = stringOrNull(config.publicExposure.publicBaseUrl) ?? ""; const basePath = publicBasePath(publicOrigin); const sentinels = sentinelRegistryRows(config); const bootstrap = { node: config.node, lane: config.lane, sentinelId: config.sentinelId, publicOrigin, basePath, configReady: config.plan.ok, contractVersion: DASHBOARD_CONTRACT_VERSION, sentinels, valuesRedacted: true, }; return ` HWLAB Web哨兵 monitor-web
加载 monitor-web...
`; } function sentinelRegistryRows(config: DashboardShellConfig): Array<{ readonly id: string; readonly enabled: boolean; readonly monitorRoot: boolean }> { return Array.isArray(config.plan.sentinels) ? config.plan.sentinels.map((item) => ({ id: stringOrNull(item.id) ?? "", enabled: item.enabled !== false, monitorRoot: item.monitorRoot === true, })).filter((item) => item.id.length > 0) : []; } function publicBasePath(publicBaseUrl: string): string { try { const path = new URL(publicBaseUrl).pathname.replace(/\/+$/u, ""); return path === "/" ? "" : path; } catch { return ""; } } export function webProbeSentinelDashboardAssetResponse(pathname: string): Response | null { if (pathname === "/dashboard/assets/dashboard.css") return textAsset(`${DASHBOARD_ASSET_ROOT}/dashboard.css`, "text/css; charset=utf-8"); if (pathname === "/dashboard/assets/dashboard.js") return textAsset(`${DASHBOARD_ASSET_ROOT}/dashboard.js`, "application/javascript; charset=utf-8"); if (pathname === "/monitor-web/assets/monitor-web.css") return textAsset(`${MONITOR_WEB_ASSET_ROOT}/monitor-web.css`, "text/css; charset=utf-8"); if (pathname === "/monitor-web/assets/monitor-web.js") return textAsset(`${MONITOR_WEB_ASSET_ROOT}/monitor-web.js`, "application/javascript; charset=utf-8"); if (pathname === "/monitor-web/assets/vendor/vue.esm-browser.prod.js") return textAsset(`${MONITOR_WEB_ASSET_ROOT}/vendor/vue.esm-browser.prod.js`, "application/javascript; charset=utf-8"); if (pathname === "/monitor-web/assets/vendor/VUE-LICENSE") return textAsset(`${MONITOR_WEB_ASSET_ROOT}/vendor/VUE-LICENSE`, "text/plain; charset=utf-8"); return null; } function textAsset(path: string, contentType: string): Response { return new Response(readFileSync(rootPath(path), "utf8"), { headers: { "cache-control": "no-store", "content-type": contentType, }, }); } function stringOrNull(value: unknown): string | null { return typeof value === "string" && value.length > 0 ? value : null; } function escapeHtml(value: string): string { return value.replace(/&/gu, "&").replace(//gu, ">").replace(/"/gu, """); } function escapeAttr(value: string): string { return escapeHtml(value).replace(/'/gu, "'"); } function jsonForScript(value: unknown): string { return JSON.stringify(value).replace(/