{"_id":"@aivanta/control-sdk","name":"@aivanta/control-sdk","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@aivanta/control-sdk","version":"0.1.0","description":"Official server-side TypeScript SDK for Aivanta Control approvals","type":"module","sideEffects":false,"engines":{"node":">=20"},"publishConfig":{"access":"public"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./webhooks/node":{"types":"./dist/webhooks-node.d.ts","import":"./dist/webhooks-node.js"}},"scripts":{"build":"tsc -p tsconfig.json","prepack":"npm run build","typecheck":"tsc -p tsconfig.json --noEmit","test":"tsx --test tests/*.test.ts","lint":"tsc -p tsconfig.json --noEmit"},"devDependencies":{"@types/node":"^22.10.1","tsx":"^4.19.2","typescript":"^5.7.2"},"license":"MIT","gitHead":"fdeeb6a8652d4751aa759b6f2bb0998ac1bd28c6","_id":"@aivanta/control-sdk@0.1.0","_nodeVersion":"25.6.1","_npmVersion":"11.19.0","dist":{"integrity":"sha512-8ihtwG3ZoDXfIdhYjA11NUTld23dFboNHtMyljC0VQaNPCzyTxUODn56ILPc2CZshbbtPk6RynDSs31BQy2brg==","shasum":"cdd43b548e29cd3bcd26932db64e36bb84c5c6c7","tarball":"https://registry.npmjs.org/@aivanta/control-sdk/-/control-sdk-0.1.0.tgz","fileCount":39,"unpackedSize":86820,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDfECxRey6QxzA0b7iG+44ZBnHod4uinThv/8P8E5IxdgIhAL4YOYTmlNWFZ+x0rtukH69rA1KY6AVombOyCkzjAUEt"}]},"_npmUser":{"name":"kkoenen93","email":"k.koenen93@gmail.com"},"directories":{},"maintainers":[{"name":"kkoenen93","email":"k.koenen93@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/control-sdk_0.1.0_1787755378429_0.18887756668943023"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-26T14:42:58.275Z","0.1.0":"2026-08-26T14:42:58.577Z","modified":"2026-08-26T14:42:58.780Z"},"maintainers":[{"name":"kkoenen93","email":"k.koenen93@gmail.com"}],"description":"Official server-side TypeScript SDK for Aivanta Control approvals","license":"MIT","readme":"# @aivanta/control-sdk\n\nServer-side TypeScript SDK (Node.js 20+) for Aivanta Control.\n\n```bash\nnpm install @aivanta/control-sdk\n```\n\n```ts\nimport {\n  AivantaControlClient,\n  isExecutableApproval,\n} from \"@aivanta/control-sdk\";\n\nconst client = new AivantaControlClient({\n  apiKey: process.env.AIVANTA_CONTROL_API_KEY!,\n  baseUrl: \"https://control.example.com\",\n});\nconst result = await client.approvals.createAndWait(\n  {\n    title: \"Send quote\",\n    summary: \"Send quote OFF-104 to the customer.\",\n    riskLevel: \"HIGH\",\n    proposedAction: { type: \"email.send\", quoteId: \"OFF-104\" },\n  },\n  { idempotencyKey: \"offer-OFF-104-send-v1\" },\n);\n\nif (isExecutableApproval(result)) await execute(result.approvedAction);\n```\n\nNever execute `proposedAction`. Execute only `approvedAction` when status is `APPROVED`,\n`executable` is exactly `true`, and `approvedAction` is non-null. The SDK never executes actions.\n\n`DENIED` is a final policy block; `REJECTED` is a human rejection. `EXPIRED` and\n`APPROVED_WITH_EDITS` are also final, but remain non-executable through the SDK. A `reasonCode` is\na machine code for branching, metrics, and translation—do not display it directly to users.\n\nIdempotency keys identify one exact business action. The client binds a key to the canonical\npayload in a bounded per-instance registry. On `409`, it never creates a replacement key.\n`fetch-existing` works only if the server supplies the documented\n`error.details.existingRequestId` together with a matching canonical\n`error.details.payloadFingerprint`; otherwise an `IdempotencyConflictError` is thrown. The local\nregistry complements, but never replaces, server-side idempotency.\n\nPolling is authoritative and independent of webhook delivery. Reads retry only bounded transient\nfailures; permanent authentication, authorization, and not-found responses fail immediately.\nCreate does not hide retries or create keys. Cancel is server-idempotent for an already-cancelled\nrequest, but the SDK currently leaves retry decisions explicit.\n\nWebhook verification is a Node/server-only subpath:\n\n```ts\nimport {\n  verifyAndParseWebhook,\n  MemoryWebhookReplayStore,\n} from \"@aivanta/control-sdk/webhooks/node\";\n```\n\nAlways pass the unmodified raw body. The memory replay store is for development/tests; production\nmust use a shared, atomic store such as Redis. Additive envelope fields and policy fields are\ndiscarded. Required public policy fields remain strict.\n\nThe SDK logs nothing by default and rejects client initialization in a browser so an API key\ncannot accidentally be used from browser code.\n","readmeFilename":"README.md","_rev":"1-ceaa211ce1275859439136e74ce6a810"}