Runtimes

TypeScript Runtime

The TypeScript runtime is an independent implementation of the AppTheory contract — not a port of the Go runtime. It executes the 275 generic runner fixtures in the 287-vector corpus, including the SP09 MCP fixture tier for JSON-RPC, registries, sessions, Streamable HTTP, resumable SSE, task stores, the SP12 OAuth tier, and the SP13 objectstore tier. The TypeScript suite also loads the shared MCP route-algebra expectations table and the M2 auth-facade acceptance tables and the two M3a provider/store conformance tables (JWKS validator, OIDC discovery bootstrap, route challenge, provider conformance, and store conformance); the CDK-TS package separately consumes the remaining facade route-inventory, route-model, and transport-posture vectors.

Install

Distribution is GitHub Releases only. The npm registry is not used; AppTheory does not publish to it. Pin the release asset and verify its checksum before installing it:

VERSION=1.14.0
TAG="v${VERSION}"
REPO="theory-cloud/AppTheory"

gh release download "${TAG}" --repo "${REPO}" \
  --pattern "theory-cloud-apptheory-${VERSION}.tgz" \
  --pattern "SHA256SUMS.txt" \
  --clobber
grep " theory-cloud-apptheory-${VERSION}.tgz$" SHA256SUMS.txt | sha256sum -c -
npm install "./theory-cloud-apptheory-${VERSION}.tgz"

The package is ESM and ships TypeScript declarations. Node.js 22+ is required. The floor is pinned by ts/package.json, ts/package-lock.json, the pinned TableTheory GitHub Release tarball metadata, and CI. Do not document a different Node.js runtime floor unless scripts/verify-runtime-floor-claims.sh passes with a CI matrix that includes both the floor and Node.js 24.

Module layout

Import path Purpose
@theory-cloud/apptheory All public TypeScript runtime exports: createApp, Context, request/response helpers, event builders, testkit helpers, jobs-ledger primitives, rate limiter classes, logging profiles, and sanitization helpers.

The package exports only the root import path above; there are no documented TypeScript subpath exports for MCP, OAuth, jobs, or rate limiting. See api-snapshots/ts.txt for the exact exported surface — that file is the release gate.

Minimal app

import { createApp, text } from "@theory-cloud/apptheory";

const app = createApp();

app.get("/ping", () => text(200, "pong"));

export const handler = async (event: unknown, ctx: unknown) =>
  app.handleLambda(event, ctx);

handleLambda is the single Lambda entrypoint for every AWS event shape. See Event Shape Dispatch for the dispatch table.

Tier selection

import { createApp } from "@theory-cloud/apptheory";

const app = createApp({ tier: "p0" });

TypeScript tiers are string literals: "p0", "p1", or "p2".

See HTTP Runtime for what each tier includes.

Deterministic tests

import {
  buildAPIGatewayV2Request,
  createTestEnv,
  text,
} from "@theory-cloud/apptheory";

test("ping", async () => {
  const env = createTestEnv({ now: new Date("2026-01-01T00:00:00Z") });
  env.ids.queue("req-1");

  const app = env.app();
  app.get("/ping", () => text(200, "pong"));

  const event = buildAPIGatewayV2Request("GET", "/ping");
  const resp = await env.invokeAPIGatewayV2(app, event);

  expect(resp.statusCode).toBe(200);
});

Route registration

app.handle("GET", "/users/{id}", handler);
app.get("/users/{id}", handler);

Normal fluent registration fails closed on invalid patterns, duplicates, and undefined handlers. handleStrict remains as a deprecated compatibility wrapper for callers that still need the old helper shape.

HTTP error format

import { createApp, HTTP_ERROR_FORMAT_FLAT_LEGACY } from "@theory-cloud/apptheory";

const app = createApp({ httpErrorFormat: HTTP_ERROR_FORMAT_FLAT_LEGACY });

Applies to HTTP error serialization only.

Object-store dependency posture

The TypeScript package intentionally declares @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner as hard dependencies because createS3ObjectStore imports the S3 client and the presigner at module load. This keeps the packaged S3 helper deterministic for GitHub Release consumers while still exposing only the bounded AppTheory ObjectStore contract plus the bounded upload grant (ObjectStoreUploadGranter#presignPut) — no raw client, list, presigned GET, generic presign, or multipart escape hatches.

The presigner is configured so that content-length, content-type, and x-amz-checksum-sha256 are signed request headers and are never hoisted into unsigned query parameters; the S3 implementation re-verifies the presigned URL and fails closed if that ever stops being true.

Lambda Function URL streaming

The TypeScript runtime ships first-class support for Lambda Function URL response streaming — useful for SSE and HTML streaming:

import {
  createApp,
  createLambdaFunctionURLStreamingHandler,
  htmlStream,
} from "@theory-cloud/apptheory";

const app = createApp();
app.get("/stream", () => htmlStream(200, ["<!doctype html>"]));

export const handler = createLambdaFunctionURLStreamingHandler(app);

Use this when latency-to-first-byte matters more than buffered responses; the standard handleLambda export does not stream.

The buffered Function URL adapter (the standard handleLambda path) never silently drops a streaming body: it drains a terminating stream into the buffered response (bounded to 4 MiB / 5 seconds) and fails closed with HTTP 500 and a JSON error body when the stream does not terminate in time, exceeds the budget, or errors — the same semantics as the HTTP API v2 adapter.

CDK constructs (jsii)

CDK constructs live in the separate @theory-cloud/apptheory-cdk package (jsii). The TS source under cdk/lib/ is the canonical implementation; Go bindings under cdk-go/ are generated.

See CDK Getting Started.

What’s verified

The TypeScript runtime passes all 275 generic runner fixtures in the 287-vector corpus on every commit. The runner includes the SP09 MCP, SP12 OAuth, and SP13 objectstore tiers; the TypeScript suite also loads the shared MCP route-algebra expectations table and the M2 auth-facade acceptance tables and the two M3a provider/store conformance tables, while CDK-TS tests load the facade route-inventory, route-model, and transport-posture tables directly. The ts/dist/ build output is checked in and gated by make rubric.

Next reads