import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http"; import { afterAll, beforeAll, expect } from "vitest"; import { test } from "@openwork/testkit"; import type { RemoteSessionExecuteDeps, RemoteSessionRuntime, RemoteSessionToolResult, } from "../../ee/apps/den-api/src/mcp/remote-session-capabilities.js"; type RemoteSessionModule = typeof import("../../ee/apps/den-api/src/mcp/remote-session-capabilities.js"); /** * The module reads den-api env at import time (db wiring for its default * runtime resolver). Seed placeholder env before the dynamic import; every * test here injects its own runtime resolver, so no database is touched. */ function seedRequiredEnv() { process.env.DATABASE_URL = process.env.DATABASE_URL ?? "mysql://root:password@127.0.0.1:3306/openwork_test"; process.env.DEN_DB_ENCRYPTION_KEY = process.env.DEN_DB_ENCRYPTION_KEY ?? "x".repeat(32); process.env.BETTER_AUTH_SECRET = process.env.BETTER_AUTH_SECRET ?? "y".repeat(32); process.env.BETTER_AUTH_URL = process.env.BETTER_AUTH_URL ?? "http://127.0.0.1:8790"; process.env.DEN_API_PUBLIC_URL = process.env.DEN_API_PUBLIC_URL ?? "http://127.0.0.1:8790"; } let DEFAULT_REMOTE_SESSION_DEPS: RemoteSessionModule["DEFAULT_REMOTE_SESSION_DEPS"]; let executeRemoteSessionCapability: RemoteSessionModule["executeRemoteSessionCapability"]; let searchRemoteSessionCapabilities: RemoteSessionModule["searchRemoteSessionCapabilities"]; /** * A witness openwork-server: the exact native OpenCode routes the * headless-threads client speaks through `/workspace/:id/opencode`, * recording every request so assertions observe the real wire traffic the * `remote-session:*` capabilities produce — not a stubbed client. */ const WORKSPACE_ID = "ws_witness"; const CLIENT_TOKEN = "witness-client-token"; const HOST_TOKEN = "witness-host-token"; type WitnessRequest = { method: string; path: string; authorization: string | undefined; hostToken: string | undefined; body: unknown; }; type WitnessSession = { id: string; title: string; prompts: string[]; }; const witness = { requests: [] as WitnessRequest[], sessions: new Map(), nextSessionId: 1, }; function readBody(request: IncomingMessage): Promise { return new Promise((resolve) => { const chunks: Buffer[] = []; request.on("data", (chunk: Buffer) => chunks.push(chunk)); request.on("end", () => { const text = Buffer.concat(chunks).toString("utf8"); if (!text) return resolve(undefined); try { resolve(JSON.parse(text)); } catch { resolve(text); } }); }); } function json(response: ServerResponse, status: number, payload: unknown) { response.writeHead(status, { "Content-Type": "application/json" }); response.end(JSON.stringify(payload)); } function snapshotWire(session: WitnessSession) { const messages = session.prompts.flatMap((prompt, index) => [ { info: { id: `msg_user_${index}`, role: "user", time: { created: index * 2 } }, parts: [{ id: `part_user_${index}`, type: "text", text: prompt }], }, { info: { id: `msg_assistant_${index}`, role: "assistant", parentID: `msg_user_${index}`, time: { created: index * 2 + 1 } }, parts: [{ id: `part_assistant_${index}`, type: "text", text: `witness reply to: ${prompt}` }], }, ]); return { session: { id: session.id, title: session.title, directory: null, time: { created: 1 } }, messages, todos: [], status: { type: "idle" }, }; } async function handle(request: IncomingMessage, response: ServerResponse) { const path = request.url ?? ""; const method = request.method ?? "GET"; const body = await readBody(request); witness.requests.push({ method, path, authorization: request.headers.authorization, hostToken: typeof request.headers["x-openwork-host-token"] === "string" ? request.headers["x-openwork-host-token"] : undefined, body, }); const prefix = `/workspace/${WORKSPACE_ID}/opencode/session`; if (method === "POST" && path === prefix) { const title = typeof body === "object" && body !== null && typeof (body as Record).title === "string" ? String((body as Record).title) : "Untitled"; const session: WitnessSession = { id: `ses_witness_${witness.nextSessionId++}`, title, prompts: [], }; witness.sessions.set(session.id, session); return json(response, 200, snapshotWire(session).session); } const messagesMatch = path.match(new RegExp(`^${prefix}/([^/]+)/message$`)); if (method === "GET" && messagesMatch) { const session = witness.sessions.get(decodeURIComponent(messagesMatch[1] ?? "")); if (!session) return json(response, 404, { code: "not_found", message: "session not found" }); return json(response, 200, snapshotWire(session).messages); } if (method === "GET" && path === `${prefix}/status`) { return json(response, 200, {}); } const sessionMatch = path.match(new RegExp(`^${prefix}/([^/]+)$`)); if (method === "GET" && sessionMatch) { const session = witness.sessions.get(decodeURIComponent(sessionMatch[1] ?? "")); if (!session) return json(response, 404, { code: "not_found", message: "session not found" }); return json(response, 200, snapshotWire(session).session); } const todoMatch = path.match(new RegExp(`^${prefix}/([^/]+)/todo$`)); if (method === "GET" && todoMatch) { const session = witness.sessions.get(decodeURIComponent(todoMatch[1] ?? "")); if (!session) return json(response, 404, { code: "not_found", message: "session not found" }); return json(response, 200, snapshotWire(session).todos); } const promptMatch = path.match(new RegExp(`^${prefix}/([^/]+)/prompt_async$`)); if (method === "POST" && promptMatch) { const session = witness.sessions.get(decodeURIComponent(promptMatch[1] ?? "")); if (!session) return json(response, 404, { code: "not_found", message: "session not found" }); const parts = typeof body === "object" && body !== null ? (body as Record).parts : undefined; const text = Array.isArray(parts) && typeof parts[0] === "object" && parts[0] !== null ? String((parts[0] as Record).text ?? "") : ""; session.prompts.push(text); return json(response, 200, {}); } return json(response, 404, { code: "not_found", message: `no witness route for ${method} ${path}` }); } let server: Server; let runtime: RemoteSessionRuntime; let deps: RemoteSessionExecuteDeps; beforeAll(async () => { seedRequiredEnv(); const module = await import("../../ee/apps/den-api/src/mcp/remote-session-capabilities.js"); DEFAULT_REMOTE_SESSION_DEPS = module.DEFAULT_REMOTE_SESSION_DEPS; executeRemoteSessionCapability = module.executeRemoteSessionCapability; searchRemoteSessionCapabilities = module.searchRemoteSessionCapabilities; server = createServer((request, response) => { void handle(request, response); }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); const address = server.address(); if (address === null || typeof address === "string") throw new Error("witness server did not report a port"); runtime = { workerId: "worker_witness", baseUrl: `http://127.0.0.1:${address.port}`, workspaceId: WORKSPACE_ID, clientToken: CLIENT_TOKEN, hostToken: HOST_TOKEN, }; deps = { resolveRuntime: async () => ({ ok: true, runtime }), createClient: DEFAULT_REMOTE_SESSION_DEPS.createClient, }; }); afterAll(async () => { await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve()))); }); // DenTypeId<"organization"> is the template-literal type `org_${string}`. const ORGANIZATION_ID = "org_witness_fixture"; function input(action: "create" | "send" | "read", body: unknown, hasWriteScope = true) { return { action, organizationId: ORGANIZATION_ID, userId: "user_witness", hasWriteScope, body }; } function payload(result: RemoteSessionToolResult): Record { return JSON.parse(result.content[0]?.text ?? "{}") as Record; } test("remote-session capabilities drive a real openwork-server wire with scoped guardrails", async ({ evidence }) => { const matches = searchRemoteSessionCapabilities("send a chat to my cloud web session", 10); expect(matches.map((match) => match.name)).toContain("remote-session:send"); expect(matches.every((match) => match.invocation?.argumentsField === "body")).toBe(true); evidence.recordAssertionEvidence( "Discovery precedes execution", "search_capabilities-shaped matches expose remote-session names with body-argument invocation metadata.", true, ); const created = await executeRemoteSessionCapability( input("create", { title: "Witness handoff", prompt: "start working" }), deps, ); expect(created.isError).toBeUndefined(); const createdBody = payload(created); const sessionId = String(createdBody.sessionId); expect(sessionId.startsWith("ses_witness_")).toBe(true); expect(createdBody.workspaceId).toBe(WORKSPACE_ID); expect(createdBody.started).toBe(true); const createRequest = witness.requests.find( (request) => request.method === "POST" && request.path === `/workspace/${WORKSPACE_ID}/opencode/session`, ); expect(createRequest).toBeDefined(); expect(createRequest?.authorization).toBe(`Bearer ${CLIENT_TOKEN}`); expect(createRequest?.hostToken).toBe(HOST_TOKEN); evidence.recordAssertionEvidence( "Create reaches the worker's native OpenCode route with worker credentials", "remote-session:create produced POST /workspace/:id/opencode/session on the witness with the collaborator bearer token and host token header, returning the native session id.", true, ); const sent = await executeRemoteSessionCapability( input("send", { sessionId, prompt: "and now summarize" }), deps, ); expect(sent.isError).toBeUndefined(); expect(payload(sent).state).toBe("accepted"); const promptRequest = witness.requests.findLast( (request) => request.method === "POST" && request.path.includes("/prompt_async"), ); expect(promptRequest).toBeDefined(); const promptParts = (promptRequest?.body as { parts?: { text?: string }[] }).parts; expect(promptParts?.[0]?.text).toBe("and now summarize"); evidence.recordAssertionEvidence( "Send routes through the native prompt mount asynchronously", "remote-session:send posted the prompt to /workspace/:id/opencode/session/:id/prompt_async and returned an acceptance receipt without waiting for a reply.", true, ); const read = await executeRemoteSessionCapability(input("read", { sessionId, limit: 3 }, false), deps); expect(read.isError).toBeUndefined(); const readBody = payload(read); expect(readBody.status).toBe("idle"); expect(readBody.messageCount).toBe(4); expect((readBody.messages as unknown[]).length).toBe(3); expect(String(readBody.finalAssistantText)).toBe("witness reply to: and now summarize"); evidence.recordAssertionEvidence( "Read returns a bounded transcript from the worker snapshot", "remote-session:read (read scope only) returned session status, total message count 4, a limit-bounded slice of 3 messages, and the final assistant text from the witness snapshot.", true, ); // Guardrail: a session id absent from the caller's own worker. const foreign = await executeRemoteSessionCapability( input("read", { sessionId: "ses_of_someone_else" }), deps, ); expect(foreign.isError).toBe(true); const foreignBody = payload(foreign); expect(foreignBody.error).toBe("unknown_session"); expect(foreignBody.retryable).toBe(false); evidence.recordAssertionEvidence( "Member scoping degrades to unknown_session", "A session id absent from the caller's own worker (including another member's session id) returns unknown_session rather than leaking existence or data.", true, ); // Guardrail: no cloud runtime resolved for the member. const requestsBeforeNoRuntime = witness.requests.length; const noRuntime = await executeRemoteSessionCapability(input("create", { title: "no runtime" }), { resolveRuntime: async () => ({ ok: false, error: "needs_cloud_setup", message: "No OpenWork Cloud workspace is available for your account yet.", retryable: false, }), createClient: DEFAULT_REMOTE_SESSION_DEPS.createClient, }); expect(noRuntime.isError).toBe(true); expect(payload(noRuntime).error).toBe("needs_cloud_setup"); expect(witness.requests.length).toBe(requestsBeforeNoRuntime); evidence.recordAssertionEvidence( "Runtime resolution gates all worker traffic", "When the member has no cloud runtime, the capability returns the actionable needs_cloud_setup result and zero requests reach the worker.", true, ); // Guardrail: mcp:write gates mutations before any side effect. const requestsBeforeScope = witness.requests.length; const createdWithoutScope = await executeRemoteSessionCapability(input("create", {}, false), deps); const sentWithoutScope = await executeRemoteSessionCapability( input("send", { sessionId, prompt: "x" }, false), deps, ); expect(createdWithoutScope.isError).toBe(true); expect(sentWithoutScope.isError).toBe(true); expect(payload(createdWithoutScope).error).toBe("insufficient_mcp_scope"); expect(payload(sentWithoutScope).error).toBe("insufficient_mcp_scope"); expect(witness.requests.length).toBe(requestsBeforeScope); evidence.recordAssertionEvidence( "mcp:write gates mutations", "Without the write scope, create and send fail with insufficient_mcp_scope and no request reaches the worker; read remains available with read scope.", true, ); }); test("remote-session capability accepts a JSON-stringified body", async ({ evidence }) => { const created = await executeRemoteSessionCapability( input("create", JSON.stringify({ title: "Stringified handoff" })), deps, ); expect(created.isError).toBeUndefined(); expect(payload(created).sessionId).toMatch(/^ses_witness_/); expect(witness.requests.findLast( (request) => request.method === "POST" && request.path === `/workspace/${WORKSPACE_ID}/opencode/session`, )?.body).toMatchObject({ title: "Stringified handoff" }); evidence.recordAssertionEvidence( "JSON-stringified capability body is normalized", "remote-session:create accepted a JSON-stringified body and passed its title to the native session route.", true, ); });