Brain and body

Put scheduling and product policy in the brain; keep authorization, credentials, browser sessions, and execution on the customer’s body.

Brain runtime

BrainRuntime adapts wrapper jobs, tracks durable assignment state, and sends typed messages through an injected BrainWireTransport. In pinned mode each job names one node. In pool mode it chooses an eligible connected node by capability and concurrency.

Trusted server HTTP client

TabWorkerBrainHttpClient is the small application-side Core client. It creates pinned or pool pairings, imports work, reads the bounded work/result projection, and cancels application-owned work. It uses an application key and therefore belongs only on a trusted server. It is not a transport for BrainRuntime and never returns Node access or refresh credentials.

Body runtime

BodyRuntime connects and pairs through an injected BodySessionConnector, checks local authorization, resolves a registered executor, emits heartbeat and ordered progress, creates a proof reference, and safely handles cancel, reconnect, and revoke.

Core HTTP transport

TabWorkerNodeHttpTransport is the implemented customer-device Core adapter for TabWorkerNodeClient. It covers pairing redemption, work retrieval, claim, authorization, start, heartbeat, progress, completion, cancellation, disconnect, and credential refresh. TabWorkerBrainHttpClient handles the separate server-side pairing and work operations.

Application work status

TabWorkerBrainHttpClient.getWork uses the application’s exact node:work:read scope. The response contains only the work ID, status, revision, source kind, source ID, and an optional structured result. It never returns the assigned payload, Node credentials, or another application’s work.

Application work cancellation

TabWorkerBrainHttpClient.cancelWork uses node:work:write, a bounded reason, and an idempotency key. Cancellation propagates atomically through active offers, claims, Node leases, and optional worker leases. An identical retry returns the original response; a changed retry conflicts. Completed work cannot be cancelled.

Existing callback transport

Use HandlerWrapperNodeTransport when existing functions already perform pairing, work retrieval, local execution coordination, or persistence. Every callback has the exact signature from WrapperNodeTransport.

import {
  HandlerWrapperNodeTransport,
  TabWorkerNodeClient,
  type NodeDescriptor,
  type PinnedWorkItem,
} from "@tabworker/sdk";

declare const descriptor: NodeDescriptor;
declare const nextPinnedWork: () => Promise<PinnedWorkItem | null>;
declare const localPair: (reference: string) => Promise<string>;

const transport = new HandlerWrapperNodeTransport({
  connect: async () => ({ connectionId: "local-session" }),
  pair: async ({ pairingReference }) => ({
    pairingId: await localPair(pairingReference),
  }),
  receivePinnedWork: nextPinnedWork,
  claimPinnedWork: async ({ work }) => ({ claimId: `claim:${work.workId}`, work }),
  authorize: async ({ authorization }) => {
    if (!authorization.locallyAuthorized) throw new Error("Local approval required");
  },
  start: async () => {},
  heartbeat: async () => {},
  progress: async ({ sequence }) => console.log("progress", sequence),
  complete: async ({ result, proof }) => console.log(result, proof.reference),
  cancel: async ({ reason }) => console.log("cancelled", reason),
  disconnect: async () => {},
});

export const node = new TabWorkerNodeClient({ descriptor, transport });

Custom transport

Implement WrapperNodeTransport directly when one object needs to preserve an existing paired channel or state machine. Use BrainRuntime and BodyRuntime for a shared typed session with pinned or pool scheduling.

Idempotency

The client passes caller-provided idempotencyToken values through unchanged. The transport decides how to persist and replay them. Receiving pinned work is read-only and has no token in the current API.

Errors

Errors thrown by transport callbacks become NodeSdkError with code transport_error, the failing operation, the original cause, and a retryable flag when the thrown value supplies retryable: true. Errors already expressed as NodeSdkError pass through unchanged.

Secret boundary

Keep credentials in the transport. Do not put bearer tokens, cookies, proxy credentials, browser sessions, API keys, vault values, or private customer context in descriptors, pinned inputs, progress, results, or proof references.

The shared runtime rejects common secret-shaped fields, but that is a guardrail—not a vault. Wrappers remain responsible for minimization, encryption, secure local storage, and log redaction.