Reference
Contracts Reference
TypeScript contracts shared by Runlane packages and adapter authors.
@runlane/contracts is the package every Runlane runtime, adapter, lane, and test helper builds on. It owns public shapes, stable enum values, validators, defaults, and adapter interfaces.
It does not own runtime behavior. Reducers, workers, schedules, retries, releases, cancellation, and task execution live in @runlane/core.
When To Start Here
| You are building | Start here | Then read |
|---|---|---|
| A storage or transport adapter | Capability types, adapter interfaces, conflict semantics, outbox publishing, and error vocabulary | Adapter Authoring |
| A lane package | Lane, LaneCapabilities, createLane(), lifecycle ordering, and capability reporting | Lanes, Storage, And Transport |
| Operator tooling | RunFilter, RunEventFilter, pagination, sort fields, pruning filters, and failure codes | Operator APIs |
| Runtime-facing code | task, queue, schedule, delivery, duration, and id/key contracts re-exported by @runlane/core | Concepts |
| Adapter or lane tests | reusable fixtures plus storage, transport, and lane conformance suites | Testing Package |
Page Map
| Page | Read it when |
|---|---|
| Vocabulary | You need stable enum values, IDs, persisted status strings, error codes, sort fields, or worker/delivery result values. |
| Core Reducer | You need to project append-only run events into the RunRecord that storage persists. |
| Adapter Authoring | You are implementing StorageAdapter, TransportAdapter, or a reusable lane package from contract types alone. |
| Local Adapters | You need direct in-memory storage or transport primitives for tests and local experiments. |
| Postgres Storage | You are using or operating the first-party durable Postgres storage adapter. |
| Postgres SQS Lane | You want the first-party production lane composed from Postgres storage and SQS wakeups. |
| SQS Transport | You are binding Runlane queues to Amazon SQS and choosing a producer or consumer path. |
| Testing Package | You need fixtures, deterministic clocks, observation helpers, or executable adapter conformance suites. |
Small Example
Use contract types to describe capabilities honestly:
import type { StorageCapabilities } from '@runlane/contracts'
export const postgresStorageCapabilities = {
claimsScheduleOccurrences: true,
durableState: true,
enforcesIdempotency: true,
enforcesQueueConcurrency: true,
enforcesSingleton: true,
leasesRuns: true,
persistsOutbox: true,
processLocalState: false,
prunesRuns: true,
readsRunHistory: true,
} satisfies StorageCapabilitiesUse contract validators at boundaries:
import { ErrorCode, jsonValueSchema, RunlaneError } from '@runlane/contracts'
const validation = await jsonValueSchema['~standard'].validate({
reason: 'provider_not_ready',
})
if (validation.issues) {
throw new RunlaneError({ code: ErrorCode.ValidationFailed })
}Export Map
| Area | What it owns | Primary exports |
|---|---|---|
| JSON | JSON-safe payload, metadata, and failure detail boundaries | JsonValue, JsonObject, isJsonValue, jsonValueSchema |
| Schemas | Validator-agnostic task payload contracts | Schema, SchemaInput, SchemaOutput |
| Errors | Stable framework, adapter, task, and transport failures | ErrorCode, RunlaneError, StorageConflictKind |
| IDs | Opaque branded ids and public id/key validation | Id, IdKind, RunlaneIdInput, asId, createRunlaneIdValueSchema |
| Identity | Durable environment, actor, and trace context scoping | Environment, environmentKey, Actor, ActorType, TraceCarrier |
| Defaults | Shared defaults for queues, retry, leases, maintenance, pruning, pagination, and operators | contractDefaults |
| Queues | Provider-neutral routing and durable capacity policy | QueueDefinition, QueueName, queueDefinitionSchema, isBoundedQueue |
| Time | Public duration strings and executable millisecond values | DurationString, DurationUnit, DurationValue, durationSchema, Clock |
| Runs | Durable run projections and visible run state | RunRecord, RunSummary, RunStatus, RunFailure |
| Run scans | Shared status groups and due-work predicates for adapters | runStatusValues, getRunRunnableAvailableAt, getRunDispatchAvailableAt, and related availability helpers |
| Events | Replayable run history | RunEventType, RunEvent, RunEventRecord |
| Tasks | User work, retry policy, release values, and handler context | TaskDefinition, TaskContext, TaskRelease, RetryPolicy |
| Schedules | Task-colocated schedules and durable occurrence state | ScheduleDefinition, ScheduleOccurrence, ScheduleType |
| Delivery | Outbox rows and transport wakeups | DeliveryIntent, DeliveryMessage, deliveryMessageSchema, OutboxFailureRecord, OutboxMessage, OutboxMessageStatus |
| Storage | Atomic durable truth, operator reads, leases, outbox mutation, idempotency, singleton, and pruning commands | StorageAdapter, AppendRunEventsCommand, ClaimRunLeaseCommand, PruneRunsCommand |
| Transport | Wakeup publishing, indexed publish outcomes, and provider acknowledgement data | TransportAdapter, publishWakeupsCommandSchema, parsePublishWakeupsResult, WakeupPublishOutcomeType |
| Lanes | Contract-only storage and transport composition | Lane, LaneCapabilities, createLane, laneSchema |
| Operators | Cursor-backed reads and retention commands | PaginationParams, Page, RunFilter, RunEventFilter, PruneRunsFilter |
| Capabilities | Public promises made by storage, transport, and lanes | StorageCapabilities, TransportCapabilities, LaneCapabilities |
Boundary Map
| Boundary | Owns | Must not own |
|---|---|---|
| Contracts | Shapes, defaults, validators, enums, adapter interfaces | Worker loops, reducer transitions, task execution |
| Core | Runtime behavior, reducer semantics, event projection, acquisition paths | Database-specific storage, provider-specific transport |
| Storage adapter | Atomic durable truth, conflicts, indexes, leases, idempotency, singleton, outbox rows | Recomputed reducer behavior or wakeup delivery |
| Transport adapter | Minimal wakeup publish and provider-specific delivery plumbing | Task payloads, run state, schedule truth |
| Lane package | Adapter composition, capability reporting, lifecycle order | New runtime semantics or capability emulation |
Non-Negotiables
| Rule | Why it matters |
|---|---|
| Storage persists core-projected events and run state atomically. | Reducer behavior stays in core while storage remains the conflict authority. |
RunEventRecord results must be the exact records persisted to history. | Callers cannot reconcile one event id in storage with another in memory. |
Transport messages carry only environment, runId, queue, request time, and trace context. | Duplicate or delayed wakeups stay safe because workers re-read storage. |
Publish outcomes are indexed: outcomes[index] belongs to command.attempts[index]. | Maintenance can mark claimed outbox rows published, failed, or dead-lettered without guessing. |
| Capabilities are promises. | Unsupported methods fail fast instead of creating hidden no-ops. |
Public IDs and keys are opaque and must not contain :. | Adapters can compose internal keys without turning public ids into parse contracts. |
| Cursors are opaque. | Storage owns pagination encoding, filter state, and ordering semantics. |
Defaults And Validation
| Surface | Contract rule |
|---|---|
| Task schemas | Runtime APIs accept Standard Schema-compatible validators through Schema. |
| JSON metadata | Use jsonValueSchema or isJsonValue; do not persist raw provider responses or cyclic objects. |
| Durations | Use durationSchema or createDurationSchema(message); valid values include 500ms, 30s, 5m, 1h, and 7d. |
| Retry default | contractDefaults.retry.backoff applies when retry.maxAttempts exists without an explicit backoff. |
| Lease default | contractDefaults.lease.duration applies to worker attempts and direct execution unless overridden. |
| Maintenance bounds | contractDefaults.maintenance bounds each tick() phase. |
| Pruning batch | contractDefaults.pruning.batchLimit applies when a prune command omits limit. |
Errors
Runlane failures use RunlaneError with stable ErrorCode values. Public code should branch on error.code, not parse raw driver messages.
Persisted failure summaries follow the same rule:
| Field | Contract |
|---|---|
RunFailure.code | Always a Runlane-owned ErrorCode. Unknown handler throws become ErrorCode.TaskFailed. |
RunFailure.meta | JSON-safe domain or provider detail, such as request ids or provider codes. |
OutboxFailureRecord.code | Always a Runlane-owned ErrorCode, not a provider namespace. |
cause | Server-side diagnostic detail only; not the public contract. |
See Error Codes for the full vocabulary.