import assert from "node:assert/strict"; import { test } from "bun:test"; import { createCloudApiServer } from "./server.ts"; import { DASHBOARD_SUMMARY_CONTRACT_VERSION } from "./server-dashboard-http.ts"; test("dashboard summary returns one typed bounded read model from real domain contracts", async () => { const sessionToken = "hws_dashboard_contract_secret"; const requestedNavIds: string[] = []; const auth = { ok: true, actor: { id: "usr_dashboard", username: "operator", displayName: "控制台操作员", role: "admin" }, authMethod: "user-billing-session", session: { id: "ses_dashboard" }, userBilling: { active: true, token: sessionToken, valuesRedacted: true } }; const userBillingClient = { configured: true, async billingSummary(token: string, options: { limit: number }) { assert.equal(token, sessionToken); assert.deepEqual(options, { limit: 5 }); return { ok: true, status: 200, body: { contractVersion: "user-billing-summary-v1", status: "ready", planId: "plan_team", plan: { id: "plan_team", displayName: "Team", status: "active" }, credits: { balance: 240, reserved: 20, available: 220 }, entitlements: [{ resourceType: "code-agent" }, { resourceType: "hwpod" }], reservations: { activeCount: 1 } } }; } }; const server = createCloudApiServer({ env: { HWLAB_PROJECT_MANAGEMENT_URL: "http://project-management.test", HWLAB_WORKBENCH_EMPTY_SESSION_GC_ENABLED: "0" }, accessController: dashboardAccessController(auth, userBillingClient, requestedNavIds), userBillingClient, hwpodNodeWsRegistry: dashboardHwpodRegistry(), dashboardDiscoverHwpodSpecs: async () => [dashboardHwpodSpec()], dashboardNow: () => "2026-07-13T12:00:00.000Z", fetchImpl: async (input: URL | RequestInfo) => projectManagementResponse(new URL(String(input))), kafkaEventBridge: disabledKafkaBridge() }); await listen(server); try { const response = await fetch(`http://127.0.0.1:${(server.address() as any).port}/v1/dashboard/summary`); assert.equal(response.status, 200); const body = await response.json(); assert.equal(body.contractVersion, DASHBOARD_SUMMARY_CONTRACT_VERSION); assert.equal(body.route, "/v1/dashboard/summary"); assert.equal(body.status, "ready"); assert.equal(body.actor.id, "usr_dashboard"); assert.deepEqual(body.sources.map((source: any) => [source.id, source.state]), [["work", "ready"], ["hwpod", "ready"], ["billing", "ready"]]); assert.equal(body.work.projectCount, 2); assert.deepEqual(body.work.taskCounts, { open: 2, inProgress: 1, blocked: 1 }); assert.deepEqual(body.work.continuations.map((task: any) => task.taskId), ["R2", "R1"]); assert.equal(body.work.continuations[0].href, "/projects/mdtodo/sources/source-main/files/file-main/tasks/R2"); assert.equal(body.hwpod.nodeCount, 1); assert.equal(body.hwpod.onlineNodeCount, 1); assert.equal(body.hwpod.availableDeviceCount, 1); assert.deepEqual(body.billing.plan, { id: "plan_team", displayName: "Team", status: "active" }); assert.deepEqual(body.billing.credits, { balance: 240, reserved: 20, available: 220 }); assert.equal(body.billing.entitlementCount, 2); assert.equal(body.billing.activeReservationCount, 1); assert.equal(body.issues.some((issue: any) => issue.code === "mdtodo_tasks_blocked" && issue.count === 1), true); assert.equal(JSON.stringify(body).includes(sessionToken), false); assert.equal(body.valuesRedacted, true); assert.equal(requestedNavIds.includes("user.dashboard"), true); } finally { await close(server); } }); test("dashboard summary keeps successful sections when upstreams are partial, stale, or restricted", async () => { const auth = { ok: true, actor: { id: "usr_dashboard_partial", username: "member", role: "user" }, authMethod: "user-billing-session", session: { id: "ses_dashboard_partial" }, userBilling: { active: true, token: "hws_dashboard_partial", valuesRedacted: true } }; const userBillingClient = { configured: true, async billingSummary() { return { ok: true, status: 200, body: { status: "stale", observedAt: "2026-07-12T12:00:00.000Z", planId: "default", credits: { available: 8 } } }; } }; const requestedNavIds: string[] = []; const accessController = dashboardAccessController(auth, userBillingClient, requestedNavIds, (navId) => navId !== "admin.hwpodGroups"); const server = createCloudApiServer({ env: { HWLAB_PROJECT_MANAGEMENT_URL: "http://project-management.test", HWLAB_WORKBENCH_EMPTY_SESSION_GC_ENABLED: "0" }, accessController, userBillingClient, hwpodNodeWsRegistry: dashboardHwpodRegistry(), dashboardDiscoverHwpodSpecs: async () => { throw new Error("restricted HWPOD discovery must not run"); }, dashboardNow: () => "2026-07-13T12:00:00.000Z", fetchImpl: async (input: URL | RequestInfo) => { const url = new URL(String(input)); if (url.searchParams.get("status") === "in_progress") return jsonResponse(503, { ok: false, error: { code: "projection_refreshing" } }); return projectManagementResponse(url); }, kafkaEventBridge: disabledKafkaBridge() }); await listen(server); try { const response = await fetch(`http://127.0.0.1:${(server.address() as any).port}/v1/dashboard/summary`); assert.equal(response.status, 200); const body = await response.json(); assert.equal(body.status, "partial"); assert.equal(body.work.state, "partial"); assert.equal(body.work.projectCount, 2); assert.equal(body.work.taskCounts.inProgress, null); assert.equal(body.hwpod.state, "restricted"); assert.equal(body.hwpod.nodeCount, null); assert.equal(body.billing.state, "stale"); assert.equal(body.billing.credits.available, 8); assert.equal(body.issues.some((issue: any) => issue.code === "work_summary_partial"), true); assert.equal(body.issues.some((issue: any) => issue.code === "billing_summary_stale"), true); assert.equal(body.issues.some((issue: any) => issue.domain === "hwpod"), false); assert.equal(body.sources.find((source: any) => source.id === "hwpod").reason, "当前身份无 HWPOD topology 访问权限"); assert.equal(requestedNavIds.includes("user.dashboard"), true); } finally { await close(server); } }); function dashboardAccessController(auth: any, userBilling: any, requestedNavIds: string[], allow: (navId: string) => boolean = () => true) { return { required: true, userBilling, async requireNavAccess(_request: unknown, _response: unknown, navId: string) { requestedNavIds.push(navId); return allow(navId) ? auth : null; }, async authenticate() { return auth; }, navAccessAllowed(_actor: unknown, navId: string) { return allow(navId); } }; } function projectManagementResponse(url: URL) { if (url.pathname === "/v1/project-management/projects") { return jsonResponse(200, { ok: true, contractVersion: "project-management-v1", projects: [{ projectId: "project_alpha", name: "Alpha", status: "active" }, { projectId: "project_beta", name: "Beta", status: "ready" }] }); } if (url.pathname === "/v1/project-management/mdtodo/tasks") { const status = url.searchParams.get("status"); const task = (taskId: string, taskStatus: string) => ({ taskRef: `mdtodo:source-main:file-main:${taskId}`, taskId, title: `Task ${taskId}`, status: taskStatus, projectId: "project_alpha", sourceId: "source-main", fileRef: "file-main", updatedAt: "2026-07-13T10:00:00.000Z" }); if (status === "in_progress") return jsonResponse(200, { ok: true, tasks: [task("R2", status)], page: { offset: 0, limit: 6, total: 1, hasMore: false } }); if (status === "open") return jsonResponse(200, { ok: true, tasks: [task("R1", status)], page: { offset: 0, limit: 6, total: 2, hasMore: true } }); if (status === "blocked") return jsonResponse(200, { ok: true, tasks: [task("R3", status)], page: { offset: 0, limit: 6, total: 1, hasMore: false } }); } return jsonResponse(404, { ok: false, error: { code: "not_found" } }); } function dashboardHwpodSpec() { return { ok: true, hwpodId: "hwpod-demo", name: "hwpod-demo", nodeId: "node-demo", authority: "test-registry", specPath: "/redacted/hwpod-spec.yaml", availability: { ok: true, status: "available", checkedAt: "2026-07-13T11:59:00.000Z" }, document: { spec: {} } }; } function dashboardHwpodRegistry() { return { describe() { return { mode: "hwpod-node-outbound-native-ws", pendingCount: 0, nodes: [{ nodeId: "node-demo", name: "Demo Node", status: "online", capabilities: ["node.health", "node.version", "node.inventory", "node.diagnostics"], inFlightCount: 0, maxInFlight: 1 }] }; } }; } function disabledKafkaBridge() { return { ready: Promise.resolve(), async stop() {}, describe() { return { status: "disabled" }; } }; } function jsonResponse(status: number, body: unknown) { return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } }); } async function listen(server: any) { await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); } async function close(server: any) { await new Promise((resolve, reject) => server.close((error: Error | null) => error ? reject(error) : resolve())); }