@aivanta/control-sdk
v0.1.0
Published
Official server-side TypeScript SDK for Aivanta Control approvals
Readme
@aivanta/control-sdk
Server-side TypeScript SDK (Node.js 20+) for Aivanta Control.
npm install @aivanta/control-sdkimport {
AivantaControlClient,
isExecutableApproval,
} from "@aivanta/control-sdk";
const client = new AivantaControlClient({
apiKey: process.env.AIVANTA_CONTROL_API_KEY!,
baseUrl: "https://control.example.com",
});
const result = await client.approvals.createAndWait(
{
title: "Send quote",
summary: "Send quote OFF-104 to the customer.",
riskLevel: "HIGH",
proposedAction: { type: "email.send", quoteId: "OFF-104" },
},
{ idempotencyKey: "offer-OFF-104-send-v1" },
);
if (isExecutableApproval(result)) await execute(result.approvedAction);Never execute proposedAction. Execute only approvedAction when status is APPROVED,
executable is exactly true, and approvedAction is non-null. The SDK never executes actions.
DENIED is a final policy block; REJECTED is a human rejection. EXPIRED and
APPROVED_WITH_EDITS are also final, but remain non-executable through the SDK. A reasonCode is
a machine code for branching, metrics, and translation—do not display it directly to users.
Idempotency keys identify one exact business action. The client binds a key to the canonical
payload in a bounded per-instance registry. On 409, it never creates a replacement key.
fetch-existing works only if the server supplies the documented
error.details.existingRequestId together with a matching canonical
error.details.payloadFingerprint; otherwise an IdempotencyConflictError is thrown. The local
registry complements, but never replaces, server-side idempotency.
Polling is authoritative and independent of webhook delivery. Reads retry only bounded transient failures; permanent authentication, authorization, and not-found responses fail immediately. Create does not hide retries or create keys. Cancel is server-idempotent for an already-cancelled request, but the SDK currently leaves retry decisions explicit.
Webhook verification is a Node/server-only subpath:
import {
verifyAndParseWebhook,
MemoryWebhookReplayStore,
} from "@aivanta/control-sdk/webhooks/node";Always pass the unmodified raw body. The memory replay store is for development/tests; production must use a shared, atomic store such as Redis. Additive envelope fields and policy fields are discarded. Required public policy fields remain strict.
The SDK logs nothing by default and rejects client initialization in a browser so an API key cannot accidentally be used from browser code.
