Skip to main content

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:

FieldTypeDescription
entrypointKind"query" | "mutation" | "route"The type of entrypoint to invoke
entrypointIdstringThe entrypoint ID as declared in your spec
inputRecord<string, unknown>Typed input matching the entrypoint's in block
authContextAuthContextThe 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:

  1. Validates the input against the compiled entrypoint schema. Invalid inputs are rejected before reaching the semantic engine.
  2. Evaluates access. An invocation that fails access returns status: "rejected", not an error.
  3. Checks the replay store for mutations. A duplicate invocation with the same idempotency key returns status: "replayed" with the original result.
  4. Dispatches to the appropriate semantic engine (domain runtime for mutations, projection runtime for queries).
  5. Returns a canonical ResultEnvelope with status: "ok" | "rejected" | "replayed" | "error".
warning

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