import { expect, test } from "bun:test"; import express from "express"; import { registerTaskQuestionBridge } from "../../src/routes/task-question-bridge.js"; import { removeRuntimeSessionContext, setRuntimeSessionContext } from "../../src/runtime/sessionContext.js"; test("task questions bind identity on the host and reject chat, readers, and forged targets", async () => { const calls: unknown[][] = []; const taskId = crypto.randomUUID(); for (const purpose of ["task_execution", "task_collaboration", "ordinary_chat"] as const) { setRuntimeSessionContext({ sessionId: purpose, clientSessionId: `client-${purpose}`, actorKey: "actor", projectKey: "project", traceId: "test", taskId, purpose }); } const app = express(); app.use(express.json()); registerTaskQuestionBridge(app, { internalToken: "test-token", client: { askTaskUser: async (...args) => { calls.push(args); return { question_request_id: crypto.randomUUID(), status: "pending", version: 1 }; } } }); const server = app.listen(0, "127.0.0.1"); await new Promise((resolve) => server.once("listening", resolve)); const body = { session_id: "task_execution", request_id: crypto.randomUUID(), questions: [{ question_id: "flow", title: "流量依据", body: "是否有流量记录?", options: [], mode: "single", allow_custom: true, required: true }] }; const post = (input = body, token = "test-token") => fetch(`http://127.0.0.1:${(server.address() as { port: number }).port}/internal/operational-task/questions`, { method: "POST", headers: { "content-type": "application/json", "x-agent-internal-token": token }, body: JSON.stringify(input) }); try { expect((await post(body, "wrong")).status).toBe(403); for (const session_id of ["task_collaboration", "ordinary_chat", "unregistered-reader"]) { expect((await post({ ...body, session_id })).status).toBe(403); } expect((await post({ ...body, task_id: "forged" } as typeof body)).status).toBe(400); expect((await post({ ...body, questions: [body.questions[0], body.questions[0]] })).status).toBe(400); expect(calls).toHaveLength(0); expect((await post()).status).toBe(200); expect(calls[0]).toEqual(["task_execution", taskId, { request_id: body.request_id, questions: body.questions, sourceSessionId: "client-task_execution" }]); } finally { ["task_execution", "task_collaboration", "ordinary_chat"].forEach(removeRuntimeSessionContext); await new Promise((resolve) => server.close(() => resolve())); } });