{"_id":"@chaos-scheduler/sdk","_rev":"5-04274b8068ee4d20e581a35339f677e6","name":"@chaos-scheduler/sdk","dist-tags":{"latest":"1.1.0"},"versions":{"0.3.0":{"name":"@chaos-scheduler/sdk","version":"0.3.0","keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"license":"MIT","_id":"@chaos-scheduler/sdk@0.3.0","maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"dist":{"shasum":"8e37d192093b8460e2994d48da467069dbfa3649","tarball":"https://registry.npmjs.org/@chaos-scheduler/sdk/-/sdk-0.3.0.tgz","fileCount":12,"integrity":"sha512-RMXgfkjc2MmZxFd37AH0QHTpadY3eYfvVT9yhoNQdBJZ3iBOkd7M6jSG7rYAjgAQJHev+igwwNTKBKoAHlcAaw==","signatures":[{"sig":"MEUCIQCUKa1tdqe5QkMlPC2cgBDDcM2H9tRWzYD8UNq/EEOcpQIgEvA+Lbb/tdt90ay+ojltIPWZ87vxIlwzm9K2zUd9dHI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@chaos-scheduler%2fsdk@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":170847},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"6bad1c55bff5e4f4bd8a745b0450e938906eeff6","scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"},"repository":{"url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","type":"git","directory":"packages/sdk-ts"},"_npmVersion":"10.9.8","description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.9","typescript":"^6.0.3","@types/node":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.3.0_1783303312934_0.9473626058406368","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@chaos-scheduler/sdk","version":"0.4.0","keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"license":"MIT","_id":"@chaos-scheduler/sdk@0.4.0","maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"dist":{"shasum":"6bb8765e6bff32060e2e77e4b3b56cb43da5a89d","tarball":"https://registry.npmjs.org/@chaos-scheduler/sdk/-/sdk-0.4.0.tgz","fileCount":12,"integrity":"sha512-9R+1udmF79FXY56ql4oc4+16I8NN3Ie+ahThBRUk7B7/p8ks+5M0jKrWe93l4tZv1xv5g2IyEERMJFBhAS1ZNA==","signatures":[{"sig":"MEYCIQDQOnVjvCg2J4Lm01J5u2Usygx9U0hf4juSMyG9NJxTSQIhAIt3NbT6GN0Ul5NWU8KJuV8aKYPFOSseEVHca5gUGtNX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@chaos-scheduler%2fsdk@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":189559},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"8d96f76a28d920289534d39f64953bf7c7f95a18","scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"},"repository":{"url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","type":"git","directory":"packages/sdk-ts"},"_npmVersion":"10.9.8","description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.9","typescript":"^6.0.3","@types/node":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.4.0_1783359958097_0.07584952727970418","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@chaos-scheduler/sdk","version":"1.0.0","keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"license":"MIT","_id":"@chaos-scheduler/sdk@1.0.0","maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"dist":{"shasum":"17970f578736dbbaa87ecd41489d9d97726471ff","tarball":"https://registry.npmjs.org/@chaos-scheduler/sdk/-/sdk-1.0.0.tgz","fileCount":12,"integrity":"sha512-HvPKMNUD1s4cywimJF1pGhknFV5uqANTcKRZLgv+dRWd8XOIJVs4oJhs5yngaioCQiw6X9Yr3o0xu5RpQShDhg==","signatures":[{"sig":"MEUCIBlgOxvSB8dHBh8japA2F3UZ5RzYt47QS/YCVrzdsg82AiEAnL1qYbRepospoc2mcnj5RbM4105x6G4blb/I/uxGdqk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@chaos-scheduler%2fsdk@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":189733},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"7886c9bbf11d2e939864932f71fc9bd135eb2ff8","scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"},"overrides":{"esbuild":"^0.28.1"},"repository":{"url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","type":"git","directory":"packages/sdk-ts"},"_npmVersion":"10.9.8","description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.9","esbuild":"^0.28.1","typescript":"^6.0.3","@types/node":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.0_1783416500623_0.21118686095482153","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@chaos-scheduler/sdk","version":"1.0.1","keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"license":"MIT","_id":"@chaos-scheduler/sdk@1.0.1","maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"dist":{"shasum":"efaf5c836f2253e965ed857e460cb1096a8d9aca","tarball":"https://registry.npmjs.org/@chaos-scheduler/sdk/-/sdk-1.0.1.tgz","fileCount":12,"integrity":"sha512-h0KwOJ+lplx07Ape/nf3Ff6rey1V1L1KCeGMSJi3pm7Oy+9P/AIGDca/zSHfjE7OlN51cwqsHUb6Jcz0mQf7sg==","signatures":[{"sig":"MEQCIEYUlEQSNI0KPg3ItVFCxvQVzctpBt77u5tbfIQNoWa+AiAbA7rMMRxDC10v9ph/xHCObDoV4q+1bvR2d6XW5Xzerw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@chaos-scheduler%2fsdk@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":190209},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"21ebd24b8838011c72ee1fd1895521b6fd1537cc","scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"},"overrides":{"esbuild":"^0.28.1"},"repository":{"url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","type":"git","directory":"packages/sdk-ts"},"_npmVersion":"10.9.8","description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.9","esbuild":"^0.28.1","typescript":"^6.0.3","@types/node":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/sdk_1.0.1_1783420651543_0.9394028859625807","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@chaos-scheduler/sdk","version":"1.1.0","description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","directory":"packages/sdk-ts"},"homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","clean":"rm -rf dist"},"keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"engines":{"node":">=18"},"publishConfig":{"access":"public","provenance":true},"devDependencies":{"@types/node":"^26.1.0","esbuild":"^0.28.1","tsup":"^8.5.1","typescript":"^6.0.3","vitest":"^4.1.9"},"overrides":{"esbuild":"^0.28.1"},"_id":"@chaos-scheduler/sdk@1.1.0","gitHead":"19cc5ae44082de50b2475ae3cd79766b112f353a","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-7AUs8NtDUeho3oEbOSqDVT7vsN6/Y8gaYQqQ95Upp9Utk/azRCWMrHW3qpWdRvksWNEqYHmpPv9blkbaGL0dXA==","shasum":"3458a22502c107128ad7626c746fb07cfb86280c","tarball":"https://registry.npmjs.org/@chaos-scheduler/sdk/-/sdk-1.1.0.tgz","fileCount":12,"unpackedSize":192679,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@chaos-scheduler%2fsdk@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDNWTcbLga4dx26nJPK301RAxO3fYEulBlJVCngV60noQIgFuzUOoMLHnX9yBs3D/V7MyigD97WtCDGUpCvVfhQVeo="}]},"_npmUser":{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"},"directories":{},"maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_1.1.0_1783884134189_0.7530207632956081"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-06T02:01:52.727Z","modified":"2026-07-12T19:22:14.616Z","0.3.0":"2026-07-06T02:01:53.069Z","0.4.0":"2026-07-06T17:45:58.243Z","1.0.0":"2026-07-07T09:28:20.770Z","1.0.1":"2026-07-07T10:37:31.678Z","1.1.0":"2026-07-12T19:22:14.325Z"},"bugs":{"url":"https://github.com/KleinPerkins/chaos-scheduler/issues"},"license":"MIT","homepage":"https://github.com/KleinPerkins/chaos-scheduler/tree/main/packages/sdk-ts#readme","keywords":["chaos-scheduler","scheduler","sdk","rest","webhook","workflow"],"repository":{"type":"git","url":"git+https://github.com/KleinPerkins/chaos-scheduler.git","directory":"packages/sdk-ts"},"description":"TypeScript SDK for the Chaos Scheduler REST API (/api/v1) — register environments/workflows, run/enqueue on demand, poll runs, and verify webhook signatures.","maintainers":[{"name":"kleinperkins","email":"awake_sloes5j@icloud.com"}],"readme":"# @chaos-scheduler/sdk\n\nTyped TypeScript client for the **Chaos Scheduler** REST API (`/api/v1`), plus\nwebhook signature helpers. It is the foundation for the\n[`@chaos-scheduler/mcp-server`](../mcp-server) and for any external system that\nregisters workflows, triggers runs on demand, polls results, or receives result\nwebhooks.\n\n- Zero runtime dependencies (uses the global `fetch` and `node:crypto`).\n- Ships ESM + CJS + `.d.ts`.\n- Wire types are hand-derived from the Rust backend — see\n  [Source of truth](#source-of-truth).\n\n## Install\n\n```bash\nnpm install @chaos-scheduler/sdk\n```\n\nRequires Node.js ≥ 18 (for global `fetch`). Pass a `fetch` implementation in the\noptions for older runtimes.\n\n## Quick start\n\n```ts\nimport { ChaosSchedulerClient } from \"@chaos-scheduler/sdk\";\n\nconst client = new ChaosSchedulerClient({\n  baseUrl: \"http://127.0.0.1:9618\", // the scheduler's loopback API\n  apiKey: process.env.CHAOS_SCHEDULER_API_KEY, // \"<id>.<secret>\"\n});\n\n// 1) Register an externally-managed workflow (scope: write)\nconst wf = await client.registerWorkflow({\n  name: \"Nightly digest\",\n  script_path: \"scripts/digest.py\",\n  cron_schedule: \"0 6 * * *\",\n  environment: \"production\",\n});\n\n// 2) Enqueue a run, safely retryable via an idempotency key (scope: write)\nconst outcome = await client.enqueueWorkflow(wf.id, {\n  idempotencyKey: crypto.randomUUID(),\n});\n\n// 3) Poll the run to completion (read)\nif (!(\"workflow_id\" in outcome)) {\n  // duplicate replay — nothing new started\n} else if (outcome.run_id) {\n  const run = await client.waitForRun(outcome.run_id);\n  console.log(run.status, run.exit_code);\n}\n```\n\n## Authentication\n\nThe API authenticates with **scoped API keys** minted in the Scheduler UI\n(Integrations screen) or via Tauri commands. A token is `\"<id>.<secret>\"` and is\nsent as `Authorization: Bearer <id>.<secret>`. Scopes:\n\n| Scope   | Grants                                       |\n| ------- | -------------------------------------------- |\n| `read`  | list/get environments, workflows, runs       |\n| `write` | create/register/delete, run/enqueue/dispatch |\n| `admin` | superuser (implies `read` + `write`)         |\n\n`write` and `admin` keys are local-code-execution credentials: a holder can\nregister or run workflows that execute commands on the scheduler host. Store\nthem in a secret manager, rotate/revoke aggressively, and avoid putting them in\nlogs, prompts, or issue trackers.\n\nProtected environments default to `prod,production`. Backend write paths refuse\nto create, edit, delete, or execute workflows in those environments unless the\nscheduler process is started with\n`CHAOS_SCHEDULER_ALLOW_PROTECTED_WRITES=1`. Override the protected-name list with\n`CHAOS_SCHEDULER_PROTECTED_ENVIRONMENTS=prod,production,...`.\n\n`getHealth()` and `getVersion()` need no key.\n\n> **Note:** API-key creation/listing is **not** exposed over REST; keys are\n> managed inside the desktop app. The SDK therefore has no key-management\n> methods.\n\n## Idempotency\n\n`runWorkflow`, `enqueueWorkflow`, `dispatchWorkflow`, and `rerunWorkflow` accept an\n`idempotencyKey`. Reusing a key returns the original result as\n`{ status: \"duplicate\", run_id, queued_run_id }`. Queued dispatches replay with `queued_run_id`; admitted dispatches replay with `run_id`. Use the `isDuplicateDispatch` guard:\n\n```ts\nimport { isDuplicateDispatch } from \"@chaos-scheduler/sdk\";\n\nconst res = await client.enqueueWorkflow(id, { idempotencyKey: key });\nif (isDuplicateDispatch(res)) {\n  // replay: res.run_id or res.queued_run_id points at the first request\n} else {\n  // fresh dispatch: res.status is admitted/queued/skipped, res.run_id is new\n}\n```\n\n## Inbound webhook trigger (signed)\n\n`POST /api/v1/workflows/{id}/dispatch` accepts a raw body forwarded to the\nworkflow's `webhook` trigger. If an inbound secret is configured, sign the\n**canonical** payload (not raw-body HMAC):\n\n```\nMETHOD\\nPATH\\nTIMESTAMP\\nSHA256_HEX(body) → hex(HMAC_SHA256(secret, canonical))\n```\n\nThe client sets `X-Chaos-Timestamp`, `X-Chaos-Event-Id`, and `X-Chaos-Signature`\nwhen you pass `signatureSecret`:\n\n```ts\nawait client.dispatchWorkflow(id, {\n  payload: JSON.stringify({ event: \"push\", ref: \"main\" }),\n  signatureSecret: process.env.INBOUND_SECRET,\n  // optional: timestamp, eventId for pinned replays\n});\n```\n\nHelpers: `computeInboundDispatchSignature`, `inboundDispatchHeaders`,\n`verifyInboundDispatchSignature`. Vectors: `packages/test-fixtures/webhook-vectors.v1.json`.\n\n## Verifying outbound result webhooks\n\nThe scheduler's `webhook` action POSTs the run result to your endpoint with:\n\n- `X-Chaos-Event: run.succeeded | run.failed`\n- `X-Chaos-Signature: sha256=<hex HMAC-SHA256 of the raw body>`\n\nVerify it over the **raw** request body (never a re-serialized object):\n\n```ts\nimport { verifyWebhookSignature } from \"@chaos-scheduler/sdk\";\nimport express from \"express\";\n\nconst app = express();\napp.post(\n  \"/chaos-webhook\",\n  express.raw({ type: \"application/json\" }),\n  (req, res) => {\n    const ok = verifyWebhookSignature(\n      req.body, // Buffer of raw bytes\n      req.header(\"x-chaos-signature\"),\n      process.env.WEBHOOK_SECRET!,\n    );\n    if (!ok) return res.status(401).end();\n    const result = JSON.parse(req.body.toString(\"utf8\"));\n    // handle result…\n    res.status(200).end();\n  },\n);\n```\n\nThe signature scheme (`hex(HMAC_SHA256(secret, raw_body))`) is verified in the\nSDK's test suite against a cross-implementation vector shared with the backend.\n\n> **Case sensitivity:** `verifyWebhookSignature` accepts uppercase hex digests,\n> but the scheduler's **inbound** webhook verifier (`api.rs::verify_inbound_webhook`)\n> compares signatures case-sensitively. Emit lowercase `sha256=<hex>` when calling\n> the scheduler API.\n\n## API surface\n\nClient methods (all return typed models):\n\n| Method                                   | Endpoint                                    | Scope |\n| ---------------------------------------- | ------------------------------------------- | ----- |\n| `getHealth()`                            | `GET /api/v1/health`                        | —     |\n| `getVersion()`                           | `GET /api/v1/version`                       | —     |\n| `listEnvironments()`                     | `GET /api/v1/environments`                  | read  |\n| `createEnvironment(input)`               | `POST /api/v1/environments`                 | write |\n| `listWorkflows()`                        | `GET /api/v1/workflows`                     | read  |\n| `getWorkflow(id)`                        | `GET /api/v1/workflows/{id}`                | read  |\n| `registerWorkflow(input)`                | `POST /api/v1/workflows`                    | write |\n| `deleteWorkflow(id)`                     | `DELETE /api/v1/workflows/{id}`             | write |\n| `setWorkflowSpec(id, spec)`              | `POST /api/v1/workflows/{id}/spec`          | write |\n| `runWorkflow(id, opts)`                  | `POST /api/v1/workflows/{id}/run`           | write |\n| `enqueueWorkflow(id, opts)`              | `POST /api/v1/workflows/{id}/enqueue`       | write |\n| `dispatchWorkflow(id, opts)`             | `POST /api/v1/workflows/{id}/dispatch`      | write |\n| `listRuns(id)`                           | `GET /api/v1/workflows/{id}/runs`           | read  |\n| `getRun(id)`                             | `GET /api/v1/runs/{id}`                     | read  |\n| `getRunLogs(id)`                         | `GET /api/v1/runs/{id}/logs`                | read  |\n| `getRunTasks(id)`                        | `GET /api/v1/runs/{id}/tasks`               | read  |\n| `getRunMetrics(id)`                      | `GET /api/v1/runs/{id}/metrics`             | read  |\n| `listQueues()`                           | `GET /api/v1/queues`                        | read  |\n| `listQueuedRuns()`                       | `GET /api/v1/queued-runs`                   | read  |\n| `updateWorkflow(id, input)`              | `PATCH /api/v1/workflows/{id}`              | write |\n| `rerunWorkflow(id, opts)`                | `POST /api/v1/workflows/{id}/rerun`         | write |\n| `listEmailProfiles()`                    | `GET /api/v1/email-profiles`                | read  |\n| `createEmailProfile(input)`              | `POST /api/v1/email-profiles`               | write |\n| `updateEmailProfile(id, in)`             | `PATCH /api/v1/email-profiles/{id}`         | write |\n| `deleteEmailProfile(id)`                 | `DELETE /api/v1/email-profiles/{id}`        | write |\n| `setWorkflowEmailProfile(id, profileId)` | `POST /api/v1/workflows/{id}/email-profile` | write |\n| `waitForRun(runId, opts)`                | polls `GET /api/v1/runs/{id}`               | read  |\n\n> **Deprecated:** `runWorkflow` (`POST /api/v1/workflows/{id}/run`) is an alias of\n> `enqueueWorkflow`. Manual runs are admission-controlled — `/run` does **not**\n> execute immediately or bypass the queue, it shares the same admission path as\n> `/enqueue` — so prefer `enqueueWorkflow`. `runWorkflow` keeps working unchanged.\n\nEmail-profile `smtp_password` values are masked (`••••••••`, exported as\n`MASKED_SECRET`) on read; echo the mask back on update to preserve the stored\nsecret, or send a new value to replace it.\n\n`waitForRun` throws if the run does not reach a terminal status before\n`timeoutMs` (default 300000) elapses; catch the error to distinguish a slow run\nfrom a failed one.\n\nWebhook helpers: `computeWebhookSignature`, `webhookSignatureHeader`,\n`verifyWebhookSignature`. Errors: `ChaosApiError` (`.status`, `.isAuthError`,\n`.isRateLimited`, `.isNotFound`).\n\n> `verifyWebhookSignature` compares the hex digest case-insensitively (and\n> tolerates a missing `sha256=` prefix). The backend emits lowercase hex with\n> the prefix, so this only relaxes acceptance and never rejects a valid\n> backend-signed request.\n\n## Source of truth\n\nThere is no generated OpenAPI document yet. The wire types in `src/types.ts` are\nhand-derived from the Rust backend and must be kept in sync with:\n\n- `src-tauri/src/db.rs` — `Workflow`, `Run`, `Environment`\n- `src-tauri/src/workflow_spec.rs` — `WorkflowSpec` and friends\n- `src-tauri/src/actions.rs` — `ActionSpec`, HMAC `sign_payload`\n- `src-tauri/src/scheduler.rs` — `DispatchOutcome`\n- `src-tauri/src/api.rs` — routes, request bodies, response envelopes\n\n## Development\n\n```bash\nnpm install\nnpm run build      # tsup → dist (ESM + CJS + d.ts)\nnpm test           # vitest\nnpm run typecheck  # tsc --noEmit\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}