diff --git a/internal/cloud/user-billing-integration.test.ts b/internal/cloud/user-billing-integration.test.ts index e04b928a..41dbc4c1 100644 --- a/internal/cloud/user-billing-integration.test.ts +++ b/internal/cloud/user-billing-integration.test.ts @@ -207,6 +207,7 @@ test("cloud api accepts user-billing API keys and records Code Agent billing usa test("cloud api defers AgentRun Code Agent billing record until terminal result", async () => { const calls = []; const agentRunCalls = []; + let eventPolls = 0; let resultPolls = 0; const agentRunServer = createHttpServer(async (request, response) => { const url = new URL(request.url || "/", "http://127.0.0.1"); @@ -243,7 +244,8 @@ test("cloud api defers AgentRun Code Agent billing record until terminal result" }); } if (request.method === "GET" && url.pathname === "/api/v1/runs/run_billing_deferred/events") { - return send({ items: resultPolls > 0 ? [{ id: "evt_done", runId: "run_billing_deferred", seq: 1, type: "terminal_status", payload: { commandId: "cmd_billing_deferred", terminalStatus: "completed" }, createdAt: "2026-06-14T04:20:00.000Z" }] : [] }); + eventPolls += 1; + return send({ items: eventPolls > 1 ? [{ id: "evt_done", runId: "run_billing_deferred", seq: 1, type: "terminal_status", payload: { commandId: "cmd_billing_deferred", terminalStatus: "completed" }, createdAt: "2026-06-14T04:20:00.000Z" }] : [] }); } if (request.method === "GET" && url.pathname === "/api/v1/runs/run_billing_deferred/commands/cmd_billing_deferred/result") { resultPolls += 1; @@ -309,6 +311,7 @@ test("cloud api defers AgentRun Code Agent billing record until terminal result" HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1", HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567", HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601", + HWLAB_CODE_AGENT_AGENTRUN_PROJECTION_SYNC_POLL_INTERVAL_MS: "10", HWLAB_CODE_AGENT_AGENTRUN_SESSION_STORAGE: "metadata-only", HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "deepseek" }, @@ -710,7 +713,7 @@ test("cloud api proxies R4 admin billing plans and preserves plan updates", asyn } }); -test("cloud api maps R4 Code Agent entitlement denial to a user-facing 403", async () => { +test("cloud api maps R4 Code Agent entitlement denial to a user-facing async failure", async () => { const userBillingClient = { configured: true, async introspect(token) { @@ -737,11 +740,16 @@ test("cloud api maps R4 Code Agent entitlement denial to a user-facing 403", asy headers: { "content-type": "application/json", authorization: "Bearer hwl_user_billing_entitlement_denied", "x-trace-id": "trc_user_billing_entitlement_denied", prefer: "respond-async" }, body: JSON.stringify({ conversationId: "cnv_denied", sessionId: "ses_denied", shortConnection: true, message: "should be blocked by entitlement" }) }); - assert.equal(response.status, 403); - const payload = await response.json(); - assert.equal(payload.status, "not_entitled"); + assert.equal(response.status, 202); + const accepted = await response.json(); + assert.equal(accepted.accepted, true); + assert.equal(accepted.traceId, "trc_user_billing_entitlement_denied"); + const payload = await pollUserBillingAgentResult(port, "trc_user_billing_entitlement_denied", { authorization: "Bearer hwl_user_billing_entitlement_denied" }); + assert.equal(payload.status, "failed"); assert.equal(payload.error.code, "resource_not_entitled"); + assert.equal(payload.blocker.code, "resource_not_entitled"); assert.equal(payload.blocker.retryable, false); + assert.match(payload.finalResponse.text, /resource is not enabled/u); assert.equal(JSON.stringify(payload).includes("hwl_user_billing_entitlement_denied"), false); } finally { await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));