Pair one computer
Create a one-time pairing on your trusted server, redeem it on the customer’s computer, then send and observe one bounded test task.
Install and import
npm install @tabworker/sdk
The package root preserves the Review Queue API and also exports TabWorkerBrainHttpClient, the customer-device Node client and HTTP transport, and the transport-injected BodyRuntime.
1. Create pairing and work on your server
Construct TabWorkerBrainHttpClient only in a trusted server process. Its application key can create pairings and work but must never enter a browser bundle, extension, desktop body, payload, or log.
import { TabWorkerBrainHttpClient } from "@tabworker/sdk";
declare const applicationKey: string;
declare const nodeId: string;
const brain = new TabWorkerBrainHttpClient({
baseUrl: "https://your-test-node-endpoint.example/api/v1/node",
applicationKey,
});
const pairing = await brain.createPairing({ topology: "pinned" });
// Show pairing.pairing_code once to the intended customer. Never log it.
const imported = await brain.importWork({
source_kind: "task",
source_id: "customer-task-1",
capability: { namespace: "com.example", name: "browser_task", version: "1" },
summary: "Check one page on the customer's computer",
payload: { url: "https://example.com" },
topology: "pinned",
pinned_node_id: nodeId,
execution_mode: "customer_local",
reward_cents: 0,
currency: "USD",
});
const work = await brain.getWork(imported.work_id);
await brain.cancelWork({
work_id: work.work_id,
reason: "Customer cancelled",
idempotency_key: `cancel-${work.work_id}-0001`,
});
createPairing returns the pairing code once. Deliver it through your existing trusted product flow. importWork sends only bounded, secret-free context. getWork reads the current status and optional result; cancelWork uses a caller-supplied idempotency key.
2. Pair and run on the customer’s computer
The body creates TabWorkerNodeHttpTransport without an application key, then passes it to TabWorkerNodeClient. The transport keeps the redeemed Node credentials in memory and refreshes once after an authorization failure.
import {
TabWorkerNodeClient,
TabWorkerNodeHttpTransport,
type LocalAuthorizationAcknowledgement,
} from "@tabworker/sdk";
declare const baseUrl: string;
declare const applicationId: string;
declare const nodeId: string;
declare const pairingCode: string;
declare const authorization: LocalAuthorizationAcknowledgement;
const transport = new TabWorkerNodeHttpTransport({ baseUrl });
const node = new TabWorkerNodeClient({
descriptor: {
nodeId,
applicationId,
environment: "test",
capabilities: [
{ namespace: "com.example", name: "browser_task", version: "1" },
],
},
transport,
});
await node.connect({ idempotencyToken: "connect:local-1" });
await node.pair({ pairingReference: pairingCode, idempotencyToken: "pair:local-1" });
const work = await node.receivePinnedWork();
if (!work) throw new Error("No pinned work");
await node.claimPinnedWork({ work, idempotencyToken: `claim:${work.workId}` });
await node.authorize({ authorization, idempotencyToken: `authorize:${work.workId}` });
await node.start({ idempotencyToken: `start:${work.workId}` });
await node.heartbeat();
await node.progress({ sequence: 1, progress: { stage: "running" } });
await node.complete({
result: { status: "completed" },
proof: { reference: "local-proof:result-1" },
idempotencyToken: `complete:${work.workId}`,
});
await node.disconnect();
3. Keep product execution local
BodyRuntime is the higher-level customer-device runner for wrappers that already have a typed paired session. It obtains local authorization, chooses a registered capability executor, emits heartbeat and ordered progress, creates a proof reference, and stops on cancellation or revocation. It accepts a BodySessionConnector; it is not silently layered over TabWorkerNodeHttpTransport.
Use the direct Node client for the current Core HTTP lifecycle, or adapt an existing paired session to BodyRuntime. In both cases, browser/CDP commands, sessions, vault access, and private workflow logic stay in the wrapper body.
Local authorization
The SDK checks that locallyAuthorized and consentAcknowledged are exactly true, and that the acknowledgement time and opaque reference are non-empty. Your wrapper decides how approval is obtained and stores the authoritative local record.
Use isolated staging
Construct both HTTP clients with the Node base URL supplied by the TabWorker test operator. Give the application key only to the server-side Brain client. The customer body receives only the one-time pairing code and its own Node credentials.
api.tabworker.com, and it does not enable live dispatch, payouts, or production customer traffic.