SDK

@orcher/sdk

A thin typed client over the control plane. It wraps the nine callable operations with proper types and adds a polling helper — nothing more. What you see is what runs.

Install

# The SDK is a single file with no dependencies.
# Copy it into your app next to your Supabase client:
cp node_modules/@orcher/sdk/orcher.ts src/lib/orcher.ts
# (or download it from your organization's Settings page)

Quick start

import { createClient } from "@supabase/supabase-js";
import { createOrcherClient, pollUntil } from "./lib/orcher";

const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);
// sign in as a member of your organization first, then:
const orcher = createOrcherClient(supabase);

// 1. Capture a directive in the sandbox
const directiveId = await orcher.submitDirective({
  tenantId: TENANT_ID,
  text: "Reconcile yesterday's card settlements and flag mismatches over $500.",
});

// 2. Record an interpretation (or let the console's AI propose one)
const version = await orcher.recordInterpretation(directiveId, {
  source: "human",
  action: "Reconcile card settlements and flag mismatches",
  systems: ["Core banking"],
  dataClasses: ["financial"],
  risk: "medium",
  summary: "Read-only reconciliation with a reporting threshold.",
});

// 3. Bind it — this routes the directive to authority
const status = await orcher.confirmInterpretation(directiveId, version);
// status === "awaiting_authority" — an approver now decides in the console

// 4. Wait for the decision (poll the directives table)
const directive = await pollUntil(
  async () => {
    const { data } = await supabase.from("directives").select("status").eq("id", directiveId).single();
    return data!;
  },
  (d) => d.status === "authorized" || d.status === "rejected",
);

// 5. Verify the ledger at any time
const chain = await orcher.verifyLedger(TENANT_ID, "sandbox");
console.log(chain.intact, chain.count);

Source, not a package

The SDK ships as a single TypeScript file you copy into your codebase. There is nothing to install and no version drift — you can read every line it runs.

Identity is yours

The SDK never handles credentials. It rides on your existing Supabase client, so row-level security and role checks apply exactly as they do in the console.

Errors are typed

Every failure throws an OrcherError naming the operation that failed, so catch blocks can route on err.fn.

Polling helper

pollUntil waits for any condition — most often a directive leaving 'awaiting_authority' — with a configurable interval and timeout.