@veltrosecurity/sdk
v0.27.0
Published
TypeScript client for the Veltro security operations suite (VectorFlow, CHAD, Warden).
Maintainers
Readme
@veltrosecurity/sdk
TypeScript client for the Veltro security operations suite: VectorFlow (telemetry pipelines), CHAD (detection) and Warden (SOAR / cases).
- No runtime dependencies — the transport is
fetch(Node ≥ 22, Bun, Deno, browsers). - Generated from the products' own OpenAPI documents, with a CI gate that fails when a product's API moves and the bindings do not.
- Apache-2.0, so it can be embedded in your own tooling regardless of the AGPL-3.0 servers it talks to.
npm install @veltrosecurity/sdkSuite deployment
import { VeltroClient } from "@veltrosecurity/sdk";
const suite = await VeltroClient.login("https://soc.example.com", email, password, {
vectorflowKey: "vf_live_…", // VectorFlow REST v1 takes a service-account key
});
const sources = await suite.chad.dataSources.list<{ name: string }[]>();
const cases = await suite.warden.cases.list({ params: { limit: 25, status: "open" } });
const pipelines = await suite.vectorflow.pipelines.list();The gateway serves CHAD at /chad, Warden at /warden and VectorFlow at
/vectorflow, and exchanges the identity session cookie for a short-lived
request assertion toward each product — one login reaches all three.
VectorFlow's REST v1 accepts only an environment-scoped service-account key;
a suite client built without one throws MissingCredentialError at the call
site instead of sending a credential VectorFlow will reject.
One product with a personal access token
Create a personal access token (vmcp_…) in the suite and send it as a bearer
to the product's gateway prefix. Identity turns it into the request assertion
the product checks, so the same token works for CHAD and Warden:
import { ChadClient, WardenClient, BearerToken } from "@veltrosecurity/sdk";
const chad = new ChadClient("https://soc.example.com/chad", { auth: new BearerToken(pat) });
await chad.rules.list();
const warden = new WardenClient("https://soc.example.com/warden", {
auth: new BearerToken(pat),
});
await warden.runbooks.list();VectorFlow's /api/v1 still wants its service-account key, so pass
new BearerToken("vf_live_…") to VectorFlowClient.
Example
examples/triage.ts lists open Warden cases and new critical or high CHAD alerts
with a personal access token from VELTRO_TOKEN. It's read-only and isn't
part of the published package.
Calling convention
Every operation is a method on a resource namespace: path parameters are
positional and percent-encoded, everything else goes in the options object.
Each method is generic over the response type, which defaults to unknown —
the products' JSON is returned as it comes off the wire, and the field-level
reference is each product's OpenAPI document.
await client.dataSources.get("ds-123");
await client.alerts.list({ params: { status: "open", limit: 50 } });
await client.rules.create({ json: { title: "…", sigmaYaml: "…" } });
await client.export.download({ raw: true }); // string, not parsed JSON| Option | Meaning |
| --- | --- |
| params | query parameters (null/undefined dropped, arrays repeat the key) |
| json | JSON request body |
| body | raw request body |
| headers | extra headers, applied after the credential |
| timeoutMs | per-request timeout override |
| signal | caller abort signal, honoured alongside the timeout |
| raw | return the response text instead of parsed JSON |
Errors
| Error | Raised when |
| --- | --- |
| VeltroApiError | any non-2xx; carries status, code, detail, body |
| VeltroTransportError | the request never produced a response |
| VeltroResponseTooLargeError | the response exceeded maxResponseBytes (32 MiB default), enforced while streaming |
| MissingCredentialError | a product namespace was used without a credential it accepts |
429, 502, 503 and 504 are retried twice with exponential backoff,
honouring Retry-After. Nothing else is retried.
Credentials are never logged: each credential's toString() masks its
material, and the transport keeps headers out of error messages.
A suite session is scoped to the origin that minted it. Pointing a product
client at a different origin while passing auth: session sends no cookie
there rather than the suite session — the Domain, Path and Secure
attributes the identity authority set are all honoured.
Coverage
| Product | Resources | Operations | Generated from | | --- | --- | --- | --- | | CHAD | 52 | 365 | CHAD 0.43.2 OpenAPI | | Warden | 27 | 123 | Warden 0.11.7 OpenAPI | | VectorFlow | 9 | 41 | VectorFlow REST API 2.0.0 |
Machine planes are deliberately not bound — product-peer and external
writeback seams, SCIM, ingest, agent enrollment, inbound webhook receivers, the
unauthenticated case portal, and VectorFlow's tRPC transport. Each exclusion
and its reason is recorded in sdk/specs/<product>-operations.json.
