Pragmatic Ontology-Driven Design for TypeScript. Define your domain once, generate everything.
TypeScript + Zod instead of RDF/OWL/SHACL. Same goals: centralized knowledge, grounded reasoning, zero inference. One contract definition produces D1 migrations, Hono route handlers, typed SDK clients, OpenAPI specs, and test fixtures.
npm install @stackbilt/contracts zodDefine a contract:
import{z}from'zod';import{defineContract}from'@stackbilt/contracts';constTaskContract=defineContract({name: 'Task',version: '1.0.0',description: 'A work item with lifecycle management',schema: z.object({id: z.string().uuid(),userId: z.string(),title: z.string().min(1).max(200),status: z.enum(['open','in_progress','done']),createdAt: z.string().datetime(),}),operations: {create: {input: z.object({userId: z.string(),title: z.string().min(1).max(200),}),output: 'self',emits: ['task.created'],},complete: {input: z.object({id: z.string().uuid()}),output: 'self',transition: {from: 'in_progress',to: 'done'},emits: ['task.completed'],},},states: {field: 'status',initial: 'open',transitions: {open: {start: 'in_progress'},in_progress: {complete: 'done'},done: {},},},surfaces: {api: {basePath: '/api/tasks',routes: {create: {method: 'POST',path: '/'},list: {method: 'GET',path: '/'},get: {method: 'GET',path: '/:id'},complete: {method: 'POST',path: '/:id/complete'},},},db: {table: 'tasks',indexes: ['idx_task_user(user_id, status)'],},},authority: {create: {requires: 'authenticated'},list: {requires: 'public'},get: {requires: 'public'},complete: {requires: 'owner',ownerField: 'userId'},},});Generate everything from that single definition:
import{generateSQL,generateRoutes,generateSDK,generateOpenAPI,generateTests,}from'@stackbilt/contracts/generators';constsql=generateSQL(TaskContract);// CREATE TABLE DDLconstroutes=generateRoutes(TaskContract);// Hono handler bodiesconstsdk=generateSDK(TaskContract);// Typed fetch clientconstopenapi=generateOpenAPI(TaskContract);// OpenAPI 3.1 specconsttests=generateTests(TaskContract);// Vitest fixturesA contract is a single source of truth for a domain entity:
| Field | Purpose |
|---|---|
schema | Entity shape (Zod schema) |
operations | Valid actions with typed input/output |
states | State machine transitions (optional) |
surfaces | API routes + DB table mapping |
authority | Per-operation access control |
invariants | Runtime business rules (optional) |
version | Semver for schema evolution |
Pure declaration factory. No side effects. Returns the definition with full type inference.
import{defineContract}from'@stackbilt/contracts';constMyContract=defineContract({name: 'MyEntity',version: '1.0.0',description: '...',schema: z.object({ ... }),operations: { ... },surfaces: { ... },authority: { ... },});Cross-contract foreign key reference. Generators use the metadata for JOIN clauses and referential integrity.
import{ref}from'@stackbilt/contracts';
schema: z.object({userId: ref(UserContract,'id'),// FK to users.id})Contract inheritance. Creates a new contract with merged fields. Base contract remains untouched.
import{extend}from'@stackbilt/contracts';constAdminTaskContract=extend(TaskContract,{name: 'AdminTask',operations: {forceClose: {input: z.object({id: z.string().uuid(),reason: z.string()}),output: 'self',transition: {from: ['open','in_progress'],to: 'done'},},},authority: {forceClose: {requires: 'role',roles: ['admin']},},});All generators take a ContractDefinition and return a string (or object for OpenAPI).
Emits CREATE TABLE DDL for D1 (SQLite).
Options:
dropFirst— prependDROP TABLE IF EXISTSifNotExists— addIF NOT EXISTS(default:true)tableName— override table name
Output includes:
- Column types mapped from Zod (string -> TEXT, number.int -> INTEGER, number -> REAL, boolean -> INTEGER, enum -> TEXT with CHECK, array/object -> TEXT as JSON)
- NOT NULL for non-optional fields
- PRIMARY KEY detection
- CHECK constraints for enum fields
- UNIQUE constraints from
surfaces.db.uniqueColumns - DEFAULT values from
surfaces.db.columnOverrides - Foreign key comments from
ref()calls - Index definitions from
surfaces.db.indexes
Emits Hono HTTP handler bodies with D1 operations.
Options:
contractImport— import path for the contractappVar— Hono app variable nameincludeAuthImports— include auth middleware importsincludeEventImports— include event helper imports when operations declareemitseventImport— import path foremitContractEventeventSinkExpression— generated handler expression that resolves the caller-provided event sink
Output includes:
- Per-route handlers with try/catch error handling
- Input validation via
safeParse() - CRUD operations (INSERT, SELECT, UPDATE, DELETE)
ref()-awareLEFT JOINclauses for generated get/list SELECTs- State transition guards (checks current state before allowing transition, returns 409 on invalid state)
- Authority middleware (
requireAuth,requireOwner,requireRole) - Optional
emitContractEvent()calls after successful operations that declareemits - Proper HTTP status codes (201, 400, 404, 409, 500)
- Response envelope:
{ data }or{ error: { code, message } }
Emits a typed fetch client class.
Options:
contractImport— import pathclassName— class name override
Output includes:
- Client class with
baseUrl+headersconstructor - Per-operation methods with typed input/output
- Path parameter interpolation
- Error handling with descriptive messages
Returns an OpenAPI 3.1.0 specification object.
Options:
title— API title overrideversion— API version overrideserverUrl— server URL
Output includes:
- Paths from
surfaces.api.routes(:id->{id}conversion) - Request/response schemas from operations
- Security schemes for authenticated routes
- Component schemas for entity + operation inputs
Emits Vitest test fixtures and state machine validation tests.
Options:
contractImport— import pathrouteImport— import path for generated routesrouteExportName— exported generated route object nameincludeRouteIntegrationTests— include handler-level integration tests when an API surface exists
Output includes:
- Valid fixture generation with sensible defaults per type
- Enum validation tests (pass/fail for each value)
- State transition tests (allowed and blocked transitions)
- Handler-level integration harness for generated Hono routes
The Zod schema walker extracts metadata for code generation. Works with both Zod v3 and v4.
import{extractColumns,extractEnums,toSnakeCase}from'@stackbilt/contracts/introspect';constcolumns=extractColumns(MyContract.schema);// [{ name: 'id', sqlType: 'TEXT', nullable: false, isPrimaryKey: true, ... }, ...]constenums=extractEnums(MyContract.schema);// { status: ['open', 'in_progress', 'done'] }toSnakeCase('createdAt');// 'created_at'This package includes generic graded-run and benchmark/eval report schemas for private product eval suites that need shared validation without leaking product evidence. GradedRunReportSchema is the package-level canonical shape for measured case runs; benchmark reports compose the same aggregate count and latency primitives.
import{GradedRunReportSchema,BenchmarkReportSchema,PublicBenchmarkSummarySchema,}from'@stackbilt/contracts';constgradedRun=GradedRunReportSchema.parse({schemaVersion: 'graded-run-report.v1',run: {runId: '123e4567-e89b-12d3-a456-426614174000',runName: 'classifier-eval',runner: 'eval-runner@1.0.0',dataset: 'fixtures/classifier.jsonl',generatedAt: '2026-05-29T10:00:00.000Z',environment: 'ci',},counts: {total: 4,passed: 3,failed: 1,errored: 0,skipped: 0,},passRate: 0.75,latency: {unit: 'ms',min: 8,max: 80,mean: 31,p50: 24,p90: 48,p95: 62,},});constreport=BenchmarkReportSchema.parse({schemaVersion: 'benchmark-report.v1',run: {runId: '123e4567-e89b-12d3-a456-426614174000',benchmarkName: 'synthetic-routing-benchmark',benchmarkVersion: '1.0.0',generatedAt: '2026-05-29T10:00:00.000Z',environment: 'ci',},counts: {total: 4,passed: 3,failed: 1,errored: 0,skipped: 0,},latency: {unit: 'ms',min: 8,max: 80,mean: 31,p50: 24,p95: 62,p99: 77,},});constpublicSummary=PublicBenchmarkSummarySchema.parse({schemaVersion: 'public-benchmark-summary.v1',benchmarkName: report.run.benchmarkName,benchmarkVersion: report.run.benchmarkVersion,generatedAt: report.run.generatedAt,counts: report.counts,latency: report.latency,});Product-specific eval evidence belongs in private repos. Do not place golden cases, scorer weights, private thresholds, endpoint configuration, raw prompts, raw outputs, competitor transcripts, or product-specific corpus rows in this package. Public summaries should contain aggregate metrics and opaque artifact digests only.
interfaceColumnDef{name: string;// snake_case column namesqlType: string;// TEXT | INTEGER | REALnullable: boolean;defaultValue: string|null;checkConstraint: string|null;// SQL CHECK for enumsisPrimaryKey: boolean;isRef: boolean;// foreign key via ref()refTable: string|null;refField: string|null;}Contracts can declare state machines that enforce valid transitions:
states: {field: 'status',// which schema field holds stateinitial: 'draft',// state for new entitiestransitions: {draft: {publish: 'published',archive: 'archived',delete: null},published: {archive: 'archived'},archived: {},// terminal state},}nullas a target means deletion (terminal)- Empty
{}means no valid transitions (terminal state) - Route generator emits guards that check current state and return 409 on invalid transitions
Four authorization levels per operation:
authority: {list: {requires: 'public'},// no authcreate: {requires: 'authenticated'},// any logged-in userupdate: {requires: 'owner',ownerField: 'userId'},// entity owner onlyadmin: {requires: 'role',roles: ['admin']},// specific roles}Route generator emits the corresponding middleware calls.
Runtime business rules that guard operations:
invariants: [{name: 'min_ingredients',description: 'Published recipes need at least one ingredient',check: (entity)=>{conste=entityas{status: string;ingredients: string[]};if(e.status==='published'&&e.ingredients.length===0){return'Published recipes need at least one ingredient';}returntrue;},appliesTo: ['publish'],},]- Return
trueto pass, or a string error message to reject appliesTolists which operations trigger the check- Enforcement is delegated to your application code
See src/examples/recipe.contract.ts for a complete contract demonstrating schema, operations, state machine, surfaces, authority, and invariants.
import{RecipeContract}from'@stackbilt/contracts/examples';import{generateSQL,generateRoutes}from'@stackbilt/contracts/generators';console.log(generateSQL(RecipeContract));console.log(generateRoutes(RecipeContract));- Contracts are the source of truth. Schema, API, database, auth, and business rules in one place.
- Generate, don't handwrite. CRUD handlers, SQL migrations, SDKs, and tests derived from contracts.
- Zod over RDF. Same ontological rigor, developer-friendly, no external tooling required.
- Extend over modify.
extend()creates new contracts from existing ones without mutation. - Surfaces decouple shape from deployment. Same contract serves different API frameworks and databases.
- Authority is declarative. Per-operation access rules, generated as middleware.
- State machines are optional but powerful. Transitions enforce valid lifecycle changes at the route level.
Apache-2.0