Skip to content

@substrat-run/kernel

The kernel's behavioral seams in pure TypeScript. This package imports no platform APIs — Cloudflare specifics live only in adapters, and every adapter must pass the same conformance suite.

sh
pnpm add @substrat-run/kernel @substrat-run/contracts

Scope host (scope-host.ts)

The adapter seam. Full semantics in Operations & the scope host.

ExportKindPurpose
ScopeHostinterfacegetScope, provisionScope, registerModule, defineOperation, admin, close
ScopeStubinterfacethe capability — the only way code outside a scope reaches it
OperationContextinterfacewhat a handler sees: ambient tenantId/scopeId/principal, sql, emit, check, link
OperationHandler<I, O>type(ctx, input) => O | Promise<O>
ConsumerHandlertypeevent consumer; at-least-once, must be idempotent
ModuleRegistrationinterfacemanifest + migrations + operations + consumers
SqlMigrationinterface{ version, sql } — ordered, journaled per module
ScopedSql, SqlValuetypessynchronous scope-local SQL: query<T>(), exec()
HostAdmininterfaceenforcement-input writes: defineRole, assignRole, grant, grantToOrg, addMember
ProvisionScopeInputinterfacetenant, scope, optional shape + jurisdiction

Permission checker (permission-checker.ts)

The evaluation seam — the model is kernel-owned, the engine is swappable. See Permissions.

ExportPurpose
PermissionCheckercheck(principal, permission, node, entity?) → Promise<Decision>
assertAllowed(decision)throws PermissionDenied unless allowed; the standard first line of an operation. Narrows the type to the proof-carrying allow.
PermissionDeniedthe error class
denyAllCheckersecure default — denies everything
UNSAFE_allowAllCheckertest-only; grants everything via a synthetic proof tuple. The name is the warning.

ulid()

A dependency-free ULID generator — the ID scheme used everywhere (ids in @substrat-run/contracts).

ts
import { ulid } from '@substrat-run/kernel';
const id = ulid(); // '01JZX6ZH2E...'

Guarantees adapters must uphold

Any ScopeHost implementation must provide — verified by @substrat-run/contract-tests:

  • Strict serialization per scope — one operation at a time, to completion.
  • Structured-clone boundary — inputs/results cloned both directions, even in-process.
  • Kernel-stamped events — id, timestamp, tenant, scope, actor stamped below the API surface.
  • Fail-closed addressing — mismatched (tenantId, scopeId) throws, never resolves elsewhere.
  • PII invariant at emit — PII-classed events without subjectId are rejected.

The hard parts, hosted.