diff --git a/extensions/qa-channel/src/bus-client.test.ts b/extensions/qa-channel/src/bus-client.test.ts index cfeb0cfee85a..9a6249c84237 100644 --- a/extensions/qa-channel/src/bus-client.test.ts +++ b/extensions/qa-channel/src/bus-client.test.ts @@ -1,8 +1,26 @@ // Qa Channel tests cover bus client plugin behavior. import { createServer, type Server } from "node:http"; -import { afterEach, describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { buildQaTarget, getQaBusState, parseQaTarget, pollQaBus } from "./bus-client.js"; +const guardedFetchCalls = vi.hoisted( + () => + [] as Array< + Parameters[0] + >, +); + +vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + fetchWithSsrFGuard: (params: Parameters[0]) => { + guardedFetchCalls.push(params); + return actual.fetchWithSsrFGuard(params); + }, + }; +}); + const OVERSIZED_RESPONSE_BYTES = 18 * 1024 * 1024; async function startJsonServer( @@ -134,6 +152,7 @@ describe("qa-bus client", () => { afterEach(async () => { await Promise.all(stops.splice(0).map((stop) => stop())); + guardedFetchCalls.length = 0; }); it("roundtrips explicit group targets", () => { @@ -251,6 +270,10 @@ describe("qa-bus client", () => { messages: [], events: [], }); + expect(guardedFetchCalls.at(-1)).toMatchObject({ + auditContext: "qa-channel.bus-state", + timeoutMs: 10_000, + }); }); it("bounds oversized qa-bus state responses", async () => { diff --git a/extensions/qa-channel/src/bus-client.ts b/extensions/qa-channel/src/bus-client.ts index 0ac45e6d1372..610c42d933fa 100644 --- a/extensions/qa-channel/src/bus-client.ts +++ b/extensions/qa-channel/src/bus-client.ts @@ -38,6 +38,8 @@ export type { type JsonResult = Promise; const QA_BUS_JSON_RESPONSE_MAX_BYTES = 16 * 1024 * 1024; +/** Total deadline for local qa-bus state requests. */ +const QA_BUS_STATE_TIMEOUT_MS = 10_000; function buildQaBusUrl(baseUrl: string, path: string): URL { const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`; @@ -304,6 +306,7 @@ export async function getQaBusState(baseUrl: string): Promise