npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@contractspec/lib.contracts-spec

v6.4.0

Published

Spec definitions and registries for ContractSpec

Downloads

13,705

Readme

@contractspec/lib.contracts-spec

Core contract declarations, registries, and shared execution primitives for ContractSpec.

Website: https://contractspec.io/

Why this package exists

@contractspec/lib.contracts-spec is the foundation of the split from @contractspec/lib.contracts.

It gives you one place to define behavior before implementation:

  1. Declare specs (operations, events, forms, resources, policies).
  2. Bind handlers.
  3. Project the same contracts into REST, GraphQL, MCP, and React runtimes.

This spec-first flow improves determinism, regeneration safety, and multi-surface consistency.

Package boundary (important)

Use this package for:

  • Contract declarations (defineCommand, defineQuery, defineEvent, defineResourceTemplate, etc.).
  • Agent definition contracts (defineAgent, AgentRegistry, AgentSpec, AgentToolConfig).
  • Core registries (OperationSpecRegistry, EventRegistry, FormRegistry, ResourceRegistry).
  • Shared execution/runtime-neutral types (HandlerCtx, policy decision types, telemetry trigger types).
  • Typed success/failure/result contracts (ContractResult, ContractSuccess, ContractProblem, ContractSpecError) via @contractspec/lib.contracts-spec/results.
  • Contract installation helpers (installOp, op, makeEmit).

Do not use this package for framework adapters:

  • REST adapters -> @contractspec/lib.contracts-runtime-server-rest
  • GraphQL adapters -> @contractspec/lib.contracts-runtime-server-graphql
  • MCP adapters -> @contractspec/lib.contracts-runtime-server-mcp
  • React runtime rendering -> @contractspec/lib.contracts-runtime-client-react
  • Integration provider/secret catalogs -> @contractspec/lib.contracts-integrations

Installation

npm install @contractspec/lib.contracts-spec @contractspec/lib.schema
# or
bun add @contractspec/lib.contracts-spec @contractspec/lib.schema

Core concepts

  • defineCommand / defineQuery: typed operation specs with metadata, I/O schema, policy, transport hints, and side effects.
  • PolicyRequirement and SurfacePolicyRequirement: additive role/permission/flag/policy-ref requirements for operations, presentations, data views, forms, and knowledge access metadata.
  • defineAgent + AgentRegistry: typed agent-definition contracts that runtime packages execute, export, or adapt.
  • OperationSpecRegistry: registers specs, binds handlers, and executes with validation/policy/event guards.
  • ContractResult: canonical success/failure envelope used by operation, workflow, job, API, MCP, GraphQL, and React runtimes while preserving raw-response compatibility for adapters.
  • defineEvent + EventRegistry: typed event contracts and lookup.
  • defineResourceTemplate + ResourceRegistry: URI-template-based resource contracts.
  • FormRegistry: contract-first form declarations consumed by UI runtimes, including readonly, email, password, autocomplete, address, phone, number, percent, currency, date, time, datetime, duration, grouped array authoring, semantic legends/descriptions, grid layout hints, progressive layout.flow sections/steps, mobile-safe responsiveFormColumns(...), and text/textarea/email input-group addons through @contractspec/lib.contracts-spec/forms.
  • installOp: one-call helper to register + bind operation handlers.
  • makeEmit: typed helper for declared event emission in handlers.

FormSpec autocomplete fields support local option filtering or resolver-backed search through resolverKey, dependency paths, debounce, and minimum-query metadata. The contract stays transport-neutral: host renderers provide the resolver/fetcher, and value submission is controlled by valueMapping (scalar, object, or pick).

FormSpec phone fields support first-class country metadata. On a kind: "phone" field, use input to choose a single linked input or split country/national inputs, output to store a PhoneFormValue, one E.164 string, or split linked paths, and display/country to control flags, calling codes, default country, and automatic country detection.

Typed Results

@contractspec/lib.contracts-spec/results is the canonical success/failure surface for operations, workflows, jobs, API adapters, MCP tools, GraphQL resolvers, and React clients.

Handlers can keep returning raw output for ordinary OK results. Use contractOk, contractAccepted, contractQueued, contractNoContent, contractPartial, and contractFail when an operation needs explicit status, headers, retry metadata, warnings, partial problems, or typed error args.

import {
  contractAccepted,
  createContractError,
  defineResultCatalog,
  failure,
  standardErrors,
  standardSuccess,
  success,
} from "@contractspec/lib.contracts-spec/results";

const results = defineResultCatalog({
  success: {
    ...standardSuccess.pick("OK", "CREATED"),
    QUEUED_FOR_REVIEW: success.queued<{ reviewId: string }>(),
  },
  errors: {
    ...standardErrors.pick("UNAUTHENTICATED", "FORBIDDEN"),
    INTENT_NOT_FOUND: failure.notFound<{ intentId: string }>({
      description: "The referenced intent does not exist.",
      gqlCode: "INTENT_NOT_FOUND",
    }),
  },
});

OperationSpecRegistry.executeResult(...) returns a ContractResult. Legacy execute(...) remains compatible: it unwraps success data and throws ContractSpecError on failure. Custom success and failure codes should be declared in spec.results or io.success/io.errors; undeclared custom failure codes normalize to INTERNAL_ERROR.

Adapter defaults:

  • REST/Fetch keeps raw success bodies by default and emits failures as application/problem+json; set resultEnvelope: true for { ok, data } success envelopes.
  • Next.js can use the injected NextResponse.json(...) helper from the REST runtime.
  • NestJS support is exposed as duck-typed exception filter/interceptor helpers without adding @nestjs/common as a hard dependency.
  • GraphQL keeps field success payloads unchanged by default; enable resultExtensions to collect success metadata, while failures use extensions.contractspec.problem.
  • MCP tools return normal content for success and isError: true with a safe problem payload for failures.
  • React runtime helpers normalize REST, GraphQL, MCP, workflow, job, and legacy error shapes into a ContractResult.

Migration note: prefer ContractSpecError, createContractError, and contractFail over @contractspec/lib.error/AppError. @contractspec/lib.error is kept as a compatibility bridge.

Validation And Authoring Entry Points

Recent authoring and setup flows use package-level validation APIs directly instead of relying on ad hoc template or registry assumptions.

  • @contractspec/lib.contracts-spec/app-config/validation
    • validateBlueprint
    • validateTenantConfig
    • validateResolvedConfig
    • assertBlueprintValid
    • assertTenantConfigValid
    • assertResolvedConfigValid
  • @contractspec/lib.contracts-spec/features/validation
    • validateFeatureSpec
    • assertFeatureSpecValid
    • validateFeatureTargetsV2
  • @contractspec/lib.contracts-spec/themes.validation
    • validateThemeSpec
    • assertThemeSpecValid

These entrypoints are the current public surface for workspace setup, CLI scaffolding, CI, and docs to verify app-config, feature, and theme authoring consistently.

Translation contracts and runtime i18n

@contractspec/lib.contracts-spec/translations is the canonical translation contract surface. Keep stable bundle identity in TranslationSpec.meta.key, keep locale variants in TranslationSpec.locale, and use optional metadata such as defaultLocale, supportedLocales, fallbacks, direction, and formatter to describe runtime behavior without making a UI framework canonical.

Production translation resolution lives in @contractspec/lib.translation-runtime. That package consumes TranslationSpec[] and provides locale negotiation, BCP 47 canonicalization, fallback chains, override layers, diagnostics, async catalog loading, compiled-message caching, and SSR snapshot serialization. Its default formatter is backed by FormatJS/intl-messageformat behind a small MessageFormatter abstraction so ContractSpec does not implement a custom ICU parser and can adopt MessageFormat 2 later.

import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
import { createTranslationRuntime } from "@contractspec/lib.translation-runtime";

const messages = defineTranslation({
  meta: {
    key: "commerce.cart.messages",
    version: "1.0.0",
    domain: "commerce",
    owners: ["platform"],
  },
  locale: "en-US",
  defaultLocale: "en-US",
  supportedLocales: ["en-US", "ar-EG", "zh-Hans"],
  messages: {
    "cart.items": {
      value: "{count, plural, =0 {No items} one {One item} other {{count} items}}",
      placeholders: [{ name: "count", type: "plural" }],
    },
  },
});

const runtime = createTranslationRuntime({
  defaultLocale: "en-US",
  requestedLocales: ["en-US"],
  specs: [messages],
});

runtime.tUnknown("cart.items", { count: 3 }); // "3 items"

Migration notes

  • Prefer meta.key: "bundle.messages" plus locale: "fr-FR" over keys like bundle.messages.fr-FR.
  • Existing createI18nFactory helpers remain available for legacy/simple package catalogs, but new production integrations should use @contractspec/lib.translation-runtime.
  • i18next adapter support lives downstream at @contractspec/lib.translation-runtime/i18next. It projects ContractSpec specs/snapshots to i18next resources and metadata manifests, but ContractSpec specs remain canonical.
  • Do not encode locale in i18next namespaces or stable translation keys. Use TranslationSpec.locale for the language and TranslationSpec.meta.key (or an explicit namespace strategy) for the namespace.
  • ICU messages are exported intact for i18next. Configure an ICU-capable i18next format plugin when using i18next to render ContractSpec ICU plural/select/selectordinal messages.
  • For SSR, create a runtime per request, preload required catalogs, serialize runtime.snapshot(), and hydrate the client from the same snapshot before doing client-side locale detection.
  • For React Native, the core runtime uses no DOM APIs; hosts are responsible for locale detection and any required Intl polyfills.

Agent Definitions

Agent declarations now live in @contractspec/lib.contracts-spec/agent.

import { AgentRegistry, defineAgent } from "@contractspec/lib.contracts-spec/agent";

const SupportBot = defineAgent({
  meta: {
    key: "support.bot",
    version: "1.0.0",
    description: "Customer support assistant",
    owners: ["support"],
    tags: ["support"],
    stability: "experimental",
  },
  instructions: "Resolve tickets and escalate low-confidence cases.",
  tools: [{ name: "support.resolve" }],
});

const registry = new AgentRegistry().register(SupportBot);

Runtime execution, exporters, MCP bridges, and provider adapters stay in @contractspec/lib.ai-agent.

Workspace Config Notes

@contractspec/lib.contracts-spec/workspace-config now includes first-class setup support for:

  • connect configuration
  • connect.adoption configuration for local catalog paths, workspace scan rules, family toggles, and verdict thresholds
  • builder configuration with runtimeMode: "managed" | "local" | "hybrid"
  • canonical Builder bootstrap presets:
    • managed_mvp
    • local_daemon_mvp
    • hybrid_mvp
  • Builder API fields:
    • builder.api.baseUrl
    • builder.api.controlPlaneTokenEnvVar
  • Builder local runtime fields:
    • builder.localRuntime.runtimeId
    • builder.localRuntime.grantedTo
    • builder.localRuntime.providerIds
  • Published typed entrypoints:
    • @contractspec/lib.contracts-spec/workspace-config
    • @contractspec/lib.contracts-spec/workspace-config/contractsrc-schema
    • @contractspec/lib.contracts-spec/workspace-config/contractsrc-types

Those settings are consumed by the shared setup layer used by the CLI, VS Code extension, and JetBrains plugin.

Current Authoring Workflow

  • Use defineTheme(...) plus contractspec create theme for first-class theme scaffolding; keep tokens as the default/light-compatible bag and add modes.dark.tokens for dark-mode overlays.
  • Theme color tokens may carry format metadata such as oklch, with CSS color strings passed through to design-system bridges.
  • Route app-config, feature, and theme checks through the package-level validators above when building setup, editor, or CI automation.
  • Use connect.adoption and the broader authoring-target discovery flows when the CLI or editors should prefer existing workspace or ContractSpec surfaces before scaffolding new code.
  • Use knowledge.mutation.evaluateGovernance when provider-backed knowledge writes need a contracted dry-run, approval, idempotency, audit-evidence, or outbound-send decision surface before runtime mutation.

Migration Note

If you previously imported agent-definition contracts from @contractspec/lib.ai-agent/spec, migrate to:

  • @contractspec/lib.contracts-spec/agent
  • @contractspec/lib.contracts-spec/agent/spec
  • @contractspec/lib.contracts-spec/agent/registry

Bundle requires alignment

When using @contractspec/lib.surface-runtime, bundle specs declare required features via ModuleBundleSpec.requires (e.g. { key: 'ai-chat', version: '1.0.0' }). These entries should match FeatureModuleSpec.meta from defineFeature. Register features (e.g. AiChatFeature from @contractspec/module.ai-chat) in a FeatureRegistry when validating bundle requirements. The bundle runtime can call registry.get(key) to verify each required feature exists before resolution.

Canonical self-contained examples by contract type

Use these example packages when you want one focused, importable reference per contract layer. knowledge and type are covered through the exported knowledge bindings/source configs and schema models. agent definitions now live directly in this package via @contractspec/lib.contracts-spec/agent.

Data table contract example

The canonical data-table example lives in @contractspec/example.data-grid-showcase and starts with a declarative DataViewSpec in this package:

DataView filters now distinguish user-editable filters from scoped constraints. Use view.filterScope.initial to seed removable filters and view.filterScope.locked for constraints that always apply but are not serialized into URL state. Locked filters render as disabled chips by default so embedded views, such as a category-scoped posts list, stay explainable while reusing the same base DataView contract.

Table fields and columns can declare overflow as truncate, wrap, expand, hideColumn, or none. Column overflow overrides field overflow, and unspecified values use type-aware defaults: markdown wraps, while text, badges, numbers, currency, percentages, dates, times, durations, and booleans truncate. expand keeps the compact cell but adds the field to row expansion; hideColumn starts the column hidden when column visibility is enabled.

Collection data views (list, grid, and table) can now share production listing defaults under view.collection. Use collection.viewModes to declare which modes a renderer may project between, collection.pagination.pageSize to seed query generation, collection.toolbar to describe search/filter/view-mode controls, collection.density for cross-mode spacing defaults, and collection.dataDepth for summary/standard/detailed/exhaustive field projection. Fields can declare visibility.minDataDepth so richer fields are available to detailed experiences without forking the base spec. The authored view.kind remains the canonical shape; renderers derive alternate collection projections without mutating the source spec. Table density remains supported as a permanent compatibility alias.

import { defineDataView } from '@contractspec/lib.contracts-spec/data-views';
import { ListDataGridShowcaseRowsQuery } from '@contractspec/example.data-grid-showcase/contracts/data-grid-showcase.operation';

export const DataGridShowcaseDataView = defineDataView({
  meta: {
    key: 'examples.data-grid-showcase.table',
    version: '1.0.0',
    entity: 'account',
    title: 'Data Grid Showcase Table',
    description:
      'Declarative DataViewSpec for the ContractSpec table showcase.',
    domain: 'examples',
    owners: ['@platform.core'],
    tags: ['examples', 'table', 'data-grid'],
    stability: 'experimental',
  },
  source: {
    primary: {
      key: ListDataGridShowcaseRowsQuery.meta.key,
      version: ListDataGridShowcaseRowsQuery.meta.version,
    },
  },
  view: {
    kind: 'table',
    collection: {
      viewModes: {
        defaultMode: 'table',
        allowedModes: ['list', 'grid', 'table'],
      },
      pagination: { pageSize: 20 },
      toolbar: {
        search: true,
        viewMode: true,
        filters: true,
        density: true,
        dataDepth: true,
      },
      density: 'comfortable',
      dataDepth: 'standard',
      personalization: {
        enabled: true,
        persist: {
          viewMode: true,
          density: true,
          dataDepth: true,
        },
      },
    },
    executionMode: 'client',
    selection: 'multiple',
    columnVisibility: true,
    columnResizing: true,
    columnPinning: true,
    rowExpansion: {
      fields: ['notes', 'renewalDate', 'lastActivityAt'],
    },
    initialState: {
      pageSize: 4,
      hiddenColumns: ['notes'],
      pinnedColumns: {
        left: ['account'],
      },
      sorting: [{ field: 'arr', desc: true }],
    },
    fields: [
      { key: 'account', label: 'Account', dataPath: 'account', sortable: true },
      { key: 'owner', label: 'Owner', dataPath: 'owner', sortable: true },
      { key: 'status', label: 'Status', dataPath: 'status', sortable: true },
      { key: 'notes', label: 'Notes', dataPath: 'notes', overflow: 'expand' },
    ],
    columns: [
      { field: 'account' },
      { field: 'owner' },
      { field: 'status', overflow: 'truncate' },
      { field: 'notes', overflow: 'hideColumn' },
    ],
  },
});

See the live example in /docs/examples/data-grid-showcase and the browser sandbox in /sandbox?template=data-grid-showcase.

Full contract inventory (explicit map)

The package currently exposes 397 total exports in package.json, including the root . barrel and 396 subpath exports. This summary is kept here for high-context navigation and AI grounding.

1) Registry-level contract types (semantic model)

From src/types.ts, ContractSpecType currently includes:

  • agent
  • app-config
  • capability
  • data-view
  • event
  • example
  • experiment
  • feature
  • form
  • harness-scenario
  • harness-suite
  • integration
  • job
  • knowledge
  • knowledge-space
  • migration
  • operation
  • policy
  • presentation
  • product-intent
  • telemetry
  • test-spec
  • theme
  • translation
  • type
  • visualization
  • workflow

2) Export/file artifact kinds (suffix-based, subpaths only)

These are the concrete contract artifact kinds visible in package exports:

  • .capability (17)
  • .feature (10)
  • .command (34)
  • .event (28)
  • .query (26)
  • .form (6)
  • .presentation (6)
  • .dataView (11)
  • .docs (0)
  • .contracts (1)
  • .docblock (0)

3) Category -> kinds matrix

  • acp: capability(1), feature(1), command(7), plain(5)
  • agent: capability(1), feature(1), command(3), event(4), query(2), form(1), presentation(1), dataView(1), plain(12)
  • app-config: capability(1), feature(1), contracts(1), plain(9)
  • capabilities: plain(7)
  • context: capability(1), feature(1), command(1), event(1), query(2), form(1), presentation(1), dataView(1), plain(10)
  • contract-registry: plain(3)
  • control-plane: capability(5), feature(1), command(15), event(10), query(8), plain(16)
  • data-views: plain(8)
  • database: capability(1), feature(1), query(4), dataView(1), plain(6)
  • docs: capability(1), feature(1), command(2), event(2), query(2), form(1), presentation(2), dataView(3), plain(15)
  • events: plain(1)
  • examples: plain(6)
  • experiments: plain(3)
  • features: plain(6)
  • forms: form(1), plain(2)
  • harness: capability(4), feature(1), command(3), event(8), query(5), presentation(1), dataView(3), plain(11)
  • install: plain(1)
  • jobs: plain(4)
  • jsonschema: plain(1)
  • knowledge: capability(1), feature(1), plain(12)
  • llm: plain(4)
  • markdown: plain(1)
  • migrations: plain(1)
  • model-registry: plain(1)
  • onboarding-base: plain(1)
  • openapi: plain(1)
  • operations: plain(5)
  • ownership: plain(1)
  • policy: plain(8)
  • presentations: plain(4)
  • product-intent: plain(16)
  • prompt: plain(1)
  • promptRegistry: plain(1)
  • provider-ranking: capability(1), feature(1), command(3), event(3), query(3), form(2), presentation(1), dataView(2), plain(10)
  • regenerator: plain(7)
  • registry: plain(1)
  • registry-utils: plain(1)
  • release: plain(1)
  • resources: plain(1)
  • schema-to-markdown: plain(1)
  • serialization: plain(3)
  • telemetry: plain(4)
  • tests: plain(3)
  • themes: plain(1)
  • themes.validation: plain(1)
  • translations: plain(7)
  • types: plain(1)
  • utils: plain(1)
  • versioning: plain(7)
  • visualizations: plain(4)
  • workflow: plain(14)
  • workspace-config: plain(3)

4) DocBlock coverage map (for AI context retrieval)

DocBlocks are authored as same-file exports in their owner modules and loaded through generated manifests, not standalone *.docblock package exports.

End-to-end quick start

1) Define schema models and specs

import { SchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
import {
  defineCommand,
  defineEvent,
  defineQuery,
} from "@contractspec/lib.contracts-spec";

const WorkspaceInput = new SchemaModel({
  name: "WorkspaceInput",
  fields: {
    workspaceId: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
  },
});

const WorkspaceOutput = new SchemaModel({
  name: "WorkspaceOutput",
  fields: {
    workspaceId: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
    name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
  },
});

const WorkspaceCreatedPayload = new SchemaModel({
  name: "WorkspaceCreatedPayload",
  fields: {
    workspaceId: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
  },
});

export const WorkspaceCreated = defineEvent({
  meta: {
    key: "workspace.created",
    version: "1.0.0",
    title: "Workspace created",
    description: "Emitted after a workspace is created.",
    stability: "stable",
    owners: ["platform.core"],
    tags: ["workspace", "event"],
  },
  payload: WorkspaceCreatedPayload,
});

export const GetWorkspace = defineQuery({
  meta: {
    key: "workspace.get",
    version: "1.0.0",
    title: "Get workspace",
    description: "Returns workspace metadata for the current tenant.",
    goal: "Expose read-only workspace state to the UI.",
    context: "Used by dashboard bootstrap.",
    stability: "stable",
    owners: ["platform.core"],
    tags: ["workspace", "query"],
  },
  io: { input: WorkspaceInput, output: WorkspaceOutput },
  policy: { auth: "user" },
});

Operations can also declare stronger policy requirements without replacing the legacy `auth`, `flags`, or `pii` fields:

```ts
export const ReadInvoice = defineQuery({
  // ...meta and io...
  policy: {
    auth: "user",
    permissions: { any: ["invoice.read"] },
    roles: { any: ["billing.viewer", "billing.admin"] },
    fieldPolicies: [
      { field: "internalNotes", actions: ["read"], permissions: ["invoice.notes.read"] },
    ],
  },
});

OperationSpecRegistry.execute() normalizes those requirements and passes them to ctx.decide with subject, resource, tenant/workspace, policy refs, and field-policy context before the handler runs. UI surfaces may reuse the same requirement shape for adaptation, but authoritative enforcement belongs in the runtime decider or server-side RBAC engine.

export const CreateWorkspace = defineCommand({ meta: { key: "workspace.create", version: "1.0.0", title: "Create workspace", description: "Creates a new workspace.", goal: "Provision a workspace for a tenant.", context: "Triggered by onboarding flows.", stability: "stable", owners: ["platform.core"], tags: ["workspace", "command"], }, io: { input: WorkspaceInput, output: WorkspaceOutput }, policy: { auth: "admin" }, sideEffects: { emits: [{ ref: WorkspaceCreated.meta, when: "after_create" }] as const, }, });


### 2) Register specs and bind handlers

```ts
import {
  EventRegistry,
  installOp,
  makeEmit,
  OperationSpecRegistry,
} from "@contractspec/lib.contracts-spec";
import {
  CreateWorkspace,
  GetWorkspace,
  WorkspaceCreated,
} from "./workspace.spec";

export const events = new EventRegistry().register(WorkspaceCreated);
export const operations = new OperationSpecRegistry();

installOp(operations, GetWorkspace, async (input) => ({
  workspaceId: input.workspaceId,
  name: "Acme Workspace",
}));

installOp(operations, CreateWorkspace, async (input, ctx) => {
  const result = {
    workspaceId: input.workspaceId,
    name: "Acme Workspace",
  };

  const emit = makeEmit(CreateWorkspace, ctx);
  await emit.ref(WorkspaceCreated, { workspaceId: input.workspaceId });
  return result;
});

3) Execute from runtime context

import type { HandlerCtx } from "@contractspec/lib.contracts-spec";
import { operations, events } from "./registry";

const ctx: HandlerCtx = {
  actor: "admin",
  channel: "web",
  eventSpecResolver: events,
  eventPublisher: async (envelope) => {
    console.log("published", envelope.key, envelope.version);
  },
};

const output = await operations.execute(
  "workspace.create",
  "1.0.0",
  { workspaceId: "wk_123" },
  ctx
);

console.log(output);

Execution behavior (why this is AI-friendly)

OperationSpecRegistry.execute(...) runs predictable steps:

  1. Resolve spec/version.
  2. Parse input.
  3. Apply policy hooks when provided (ctx.decide, ctx.rateLimit).
  4. Guard event emission against declared side effects.
  5. Execute handler.
  6. Parse output when output is a schema model.
  7. Emit telemetry when configured.

This deterministic contract -> runtime flow is a strong base for code generation and AI-driven refactors.

AI assistant guidance

When writing code:

  • Start here when asked to "add a new operation/event/form/resource contract".
  • Keep meta.key stable and increment versions for behavior changes.
  • Define spec first, then bind handler, then expose transport.

When reading code:

  • Treat <meta.key, meta.version> as the canonical identity.
  • Expect one operation contract to project into multiple transports.

Split migration from deprecated monolith

  • @contractspec/lib.contracts -> @contractspec/lib.contracts-spec
  • @contractspec/lib.contracts/operations/* -> @contractspec/lib.contracts-spec/operations/*
  • @contractspec/lib.contracts/events -> @contractspec/lib.contracts-spec/events
  • @contractspec/lib.contracts/resources -> @contractspec/lib.contracts-spec/resources
  • @contractspec/lib.contracts/forms/* -> @contractspec/lib.contracts-spec/forms/*

Runtime packages moved out:

  • REST runtime -> @contractspec/lib.contracts-runtime-server-rest
  • GraphQL runtime -> @contractspec/lib.contracts-runtime-server-graphql
  • MCP runtime -> @contractspec/lib.contracts-runtime-server-mcp
  • React runtime -> @contractspec/lib.contracts-runtime-client-react
  • Integration contracts -> @contractspec/lib.contracts-integrations

PWA Update Contracts

Use @contractspec/lib.contracts-spec/pwa to declare app-level PWA update policy and the pwa.update.check query. defaultUpdatePolicy sets the application behavior, while each release can override it for required/blocking updates or heavily offline-compatible optional updates.

The contract standardizes update decisions and prompt telemetry; host apps still own service worker registration and activation.

Monorepo environment configuration

Use @contractspec/lib.contracts-spec/workspace-config/environment to declare logical environment variables for monorepos before framework-specific materialization.

  • EnvironmentVariableDefinition separates logical keys, sensitivity, lifecycle, allowed surfaces, defaults, value sources, and aliases.
  • AppEnvironmentTarget maps a logical app/package target to a framework such as Next, Expo, Node, or worker runtimes.
  • EnvVariableAlias maps one logical variable to concrete names such as NEXT_PUBLIC_API_URL or EXPO_PUBLIC_API_URL.
  • Validation rejects secret/sensitive variables exposed through public client aliases or Next config bundle env.

Raw secrets still belong behind secret references and providers, never in .contractsrc.json.