import { createWasmSandbox } from "@suaveplan/api-sandbox-wasm"; import type { PluginManifest } from "@suaveplan/api-types/manifest"; import { describe, expect, it } from "@suaveplan/testing/runner"; import { SAND_WASM_BRIDGE_CODES, SandboxWasmBridgeError, } from "../../src/error-codes/error-codes.js"; import { createSandboxedWasmPluginModule } from "../../src/index.js"; import { buildFixtureWasm, WITNESS_OFFSET } from "../fixtures/build-wasm.js"; const MANIFEST: PluginManifest = { name: "full-flow", version: "0.1.0", apiHost: "@suaveplan/api-host@0", isolation: "sandboxed", trustLevel: "third-party", requiredCapabilities: [], }; const ALLOW = { checkCapability: () => ({ allow: true as const }) }; async function buildInstall( fixture: Parameters[0] = {} ) { const sandbox = await createWasmSandbox({ pluginName: MANIFEST.name, policy: { fs: [], fetch: [], budgets: {} }, capabilities: [], checker: ALLOW, wasmBytes: buildFixtureWasm(fixture), }); return createSandboxedWasmPluginModule({ sandbox, manifest: MANIFEST }); } function ctx(method: string, path: string, body?: string): never { const url = `https://app.example.com${path}`; const request = body === undefined ? new Request(url, { method }) : new Request(url, { method, body, headers: { "content-type": "application/json" }, }); return { request, principal: null, tenant: null, capabilities: {}, requestId: "rid", } as never; } describe("full-flow integration", () => { it("WASM-exported routes register with the host", { timeout: 30000, }, async () => { const routesJson = JSON.stringify([ { method: "GET", path: "/items" }, { method: "POST", path: "/items" }, ]); const install = await buildInstall({ routesJson }); try { expect(install.routes.map((r) => r.method)).toEqual([ "GET", "POST", ]); expect(install.routes.map((r) => r.path)).toEqual([ "/items", "/items", ]); expect(install.routes.every((r) => r.plugin === "full-flow")).toBe( true ); } finally { install.module.stop(); } }); it("1 KiB body round-trips through WASM bridge", { timeout: 30000, }, async () => { const install = await buildInstall(); try { install.module.start(); const route = install.routes[0]; if (route === undefined) throw new Error("no route"); // Build a 1 KiB body of ASCII bytes — easy to assert against. const body = "x".repeat(1024); const response = (await route.handler( ctx("POST", "/hello", body) )) as Response; expect(response.status).toBe(200); // Handler observed the bytes: witness range carries the // marshalled JSON which embeds the base64 body. We verify the // serialised JSON reached the guest by scanning for the URL. const memory = install.sandbox.instance.exports .memory as WebAssembly.Memory; const witness = new TextDecoder().decode( new Uint8Array(memory.buffer, WITNESS_OFFSET, 1024) ); expect(witness).toContain('"url":"https://app.example.com/hello"'); expect(witness).toContain('"method":"POST"'); // Response body reached the caller intact. expect(await response.text()).toBe("ok"); } finally { install.module.stop(); } }); it("WASM unreachable instruction surfaces HANDLER_TRAPPED", { timeout: 30000, }, async () => { const install = await buildInstall({ handlerTraps: true }); try { install.module.start(); const route = install.routes[0]; if (route === undefined) throw new Error("no route"); await expect( route.handler(ctx("GET", "/hello")) ).rejects.toMatchObject({ code: SAND_WASM_BRIDGE_CODES.HANDLER_TRAPPED, context: { trapKind: "unreachable" }, }); } finally { install.module.stop(); } }); it("denied capability surfaces SAND_PERM.DENIED through bridge", { timeout: 30000, }, async () => { const responseJson = JSON.stringify({ status: 403, headers: [], bodyBase64: "", errorCode: "SAND_PERM.DENIED", errorMessage: "fs.write denied", }); const install = await buildInstall({ responseJson }); try { install.module.start(); const route = install.routes[0]; if (route === undefined) throw new Error("no route"); await expect( route.handler(ctx("GET", "/hello")) ).rejects.toMatchObject({ code: "SAND_PERM.DENIED", }); } finally { install.module.stop(); } }); it("ABI validator rejects missing __suaveplan_handle_request at bridge-init", { timeout: 30000, }, async () => { try { await buildInstall({ dropExports: ["__suaveplan_handle_request"] }); throw new Error("expected throw"); } catch (err) { expect(err).toBeInstanceOf(SandboxWasmBridgeError); const e = err as SandboxWasmBridgeError; expect(e.code).toBe(SAND_WASM_BRIDGE_CODES.INVALID_PLUGIN_SURFACE); } }); });