# wasm/handle-request ## Purpose Entry point for the wasm-tier surface. Receives a `SerializedRequest` (the WASI-stdio envelope payload), routes by method + URL pathname, and dispatches to a per-route handler that delegates every business decision to `src/domain/invoice-rules.ts`. The result is a `SerializedResponse` whose body is base64-url-no-pad encoded. The function is deliberately small — routing is a flat `if`-chain rather than a generic radix-tree matcher because the route set is stable and tiny. The shape-conformance test compares byte-for-byte against the trusted-tier handler for every overlapping route; the flat dispatch keeps the parity contract auditable at a glance. ## Features - Synchronous-style routing — no router dependency. - Domain delegation — every business decision goes through `domain/invoice-rules.ts`. - Base64-url-no-pad body encoding (JSON-clean wire shape). - `SuaveplanError` throws propagate to the ABI shim (NOT caught here). - RBAC via `SerializedRequest.capabilities`. ## Usage: Basic ```ts import { plugin } from "@suaveplan/api-plugin-example/wasm"; const res = await plugin.handleRequest({ url: "http://t/example/health", method: "GET", headers: [], bodyBase64: "", principalId: null, tenantId: null, capabilities: [], requestId: "r-1", timestamp: Date.now(), }); console.log(res.status); // 200 ``` ## Usage: Advanced ```ts import { plugin } from "@suaveplan/api-plugin-example/wasm"; function encode(body: object): string { const bytes = new TextEncoder().encode(JSON.stringify(body)); let binary = ""; for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i] ?? 0); return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); } const res = await plugin.handleRequest({ url: "http://t/example/invoices", method: "POST", headers: [["content-type", "application/json"]], bodyBase64: encode({ customerId: "c", amountCents: 1, currency: "USD" }), principalId: null, tenantId: null, capabilities: ["example:write"], requestId: "r-2", timestamp: Date.now(), }); ``` ## API Reference - `handleRequest(req: SerializedRequest): Promise` — entry point. - Dispatches to: `/example/public/ping`, `/example/health`, `/example/invoices` (GET list, GET by id, POST create), `/example/invoices/:id/finalise`, `/example/rate-limited`, `/example/subscription-required`, `/_/test/fail-response`. Unknown routes return 404 with `code: ROUTE_NOT_FOUND`. ## Implementation Notes The `await Promise.resolve()` inside `finaliseInvoice` mirrors the trusted tier's microtask yield. The trusted tier uses it to keep its `example.stripe.call_duration_ms` histogram observation above zero; the wasm tier has no histogram to record but keeps the yield so control-flow timing remains identical for the parity test. Base64-url-no-pad encoding uses `btoa` / `atob` — the wasm-tier runtime (Javy/QuickJS) ships both. The encoder replaces `+` with `-`, `/` with `_`, and strips trailing `=` padding.