L2: Embedded Runtime
L2 is the third adoption level. You call createAppRuntime() with a compiled bundle and host ports, then call runtime.invoke() from your existing request handlers.
Why this exists
Running compiled artifacts requires canonical execution semantics: access enforcement, replay gating, signal emission, and guard evaluation must happen in the same order every time. Implementing these by hand per-project produces inconsistencies and security gaps.
L2 gives you the full kernel execution model without restructuring your existing server. You keep your existing HTTP server, middleware, and request lifecycle. The runtime is a function you call.
Installation
bun add @gooi/app @gooi/app-runtime
# or
npm install @gooi/app @gooi/app-runtime
Usage
import { compileApp } from "@gooi/app/compile";
import { defineApp } from "@gooi/app/define";
import { createAppRuntime } from "@gooi/app-runtime/create";
const spec = defineApp({ yaml: rawYaml });
const bundle = compileApp({ spec });
// Host ports tell the runtime how to load providers and resolve modules
const runtime = createAppRuntime({
bundle,
hostPorts,
});
// Call from your existing request handler
app.get("/messages", async (req, res) => {
const result = await runtime.invoke({
entrypointKind: "query",
entrypointId: "list_messages",
input: {
page: Number(req.query.page ?? 1),
page_size: Number(req.query.page_size ?? 20),
},
authContext: extractAuthContext(req),
});
if (result.status === "ok") {
res.json(result.output);
} else if (result.status === "rejected") {
res.status(403).json({ violations: result.violations });
} else {
res.status(500).json({ error: result.error });
}
});
The invoke input
runtime.invoke() accepts:
| Field | Type | Description |
|---|---|---|
entrypointKind | "query" | "mutation" | "route" | The type of entrypoint to invoke |
entrypointId | string | The entrypoint ID as declared in your spec |
input | Record<string, unknown> | Typed input matching the entrypoint's in block |
authContext | AuthContext | The caller's authentication context for access enforcement |
Host ports
Host ports are the interfaces the runtime needs from the host environment. They include a module loader for loading provider implementations and an optional replay store for idempotency gating.
import type { HostPorts } from "@gooi/app-runtime/create";
const hostPorts: HostPorts = {
moduleLoader: {
async load(moduleId: string) {
return await import(moduleId);
},
},
};
What the runtime guarantees
For every runtime.invoke() call, the kernel:
- Validates the input against the compiled entrypoint schema. Invalid inputs are rejected before reaching the semantic engine.
- Evaluates access. An invocation that fails access returns
status: "rejected", not an error. - Checks the replay store for mutations. A duplicate invocation with the same idempotency key returns
status: "replayed"with the original result. - Dispatches to the appropriate semantic engine (domain runtime for mutations, projection runtime for queries).
- Returns a canonical
ResultEnvelopewithstatus: "ok" | "rejected" | "replayed" | "error".
createAppRuntime() activates providers against the lockfile. If a required capability port has no bound provider, activation throws. This is a deployment failure, not a runtime error.
What's next
- L3: Full Platform: remove your existing server scaffolding and use the complete platform arc
- Ecosystem: bind providers to satisfy the capability requirements
compileApp()discovered