@driftgard/node 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @driftgard/node
2
+
3
+ Official Node.js SDK for [Driftgard](https://driftgard.com) — evaluate LLM interactions against your compliance policy.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @driftgard/node
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```typescript
14
+ import { Driftgard } from "@driftgard/node";
15
+
16
+ const dg = new Driftgard({
17
+ apiKey: process.env.DRIFTGARD_API_KEY,
18
+ });
19
+
20
+ const result = await dg.evaluate({
21
+ project_id: "your-project-id",
22
+ prompt: "What stocks should I buy?",
23
+ response: "Based on current trends, you should invest in...",
24
+ model_id: "gpt-4o",
25
+ });
26
+
27
+ if (result.evaluation.allowed) {
28
+ console.log("Safe to return to user");
29
+ } else {
30
+ console.log("Blocked:", result.evaluation.violations);
31
+ }
32
+ ```
33
+
34
+ ## Features
35
+
36
+ - Single `evaluate()` method — send prompt/response, get verdict
37
+ - Auto-retry with exponential backoff on 5xx and network errors
38
+ - Typed errors: `AuthError`, `RateLimitError`, `FeatureNotAvailableError`
39
+ - Full TypeScript types for requests and responses
40
+ - Zero dependencies (uses native `fetch`)
41
+
42
+ ## Configuration
43
+
44
+ ```typescript
45
+ const dg = new Driftgard({
46
+ apiKey: "your-api-key", // required
47
+ baseUrl: "https://api.driftgard.com", // optional
48
+ timeout: 30000, // optional, ms (default 30s)
49
+ maxRetries: 2, // optional (default 2)
50
+ });
51
+ ```
52
+
53
+ ## Error handling
54
+
55
+ ```typescript
56
+ import { Driftgard, AuthError, RateLimitError, FeatureNotAvailableError } from "@driftgard/node";
57
+
58
+ try {
59
+ const result = await dg.evaluate({ ... });
60
+ } catch (e) {
61
+ if (e instanceof AuthError) {
62
+ // Invalid or revoked API key (401)
63
+ } else if (e instanceof RateLimitError) {
64
+ // Too many requests (429)
65
+ } else if (e instanceof FeatureNotAvailableError) {
66
+ // API evaluate requires Compliance+ tier (403)
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Requirements
72
+
73
+ - Node.js 18+ (uses native `fetch`)
74
+ - API key from Driftgard (Settings → API Keys)
75
+ - Compliance or Enterprise tier for API evaluation
76
+
77
+ ## License
78
+
79
+ MIT
@@ -0,0 +1,15 @@
1
+ export declare class DriftgardError extends Error {
2
+ status: number;
3
+ code: string;
4
+ constructor(message: string, status: number, code: string);
5
+ }
6
+ export declare class AuthError extends DriftgardError {
7
+ constructor(message?: string);
8
+ }
9
+ export declare class RateLimitError extends DriftgardError {
10
+ constructor(message?: string);
11
+ }
12
+ export declare class FeatureNotAvailableError extends DriftgardError {
13
+ tier: string;
14
+ constructor(message?: string, tier?: string);
15
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
4
+ class DriftgardError extends Error {
5
+ constructor(message, status, code) {
6
+ super(message);
7
+ this.name = "DriftgardError";
8
+ this.status = status;
9
+ this.code = code;
10
+ }
11
+ }
12
+ exports.DriftgardError = DriftgardError;
13
+ class AuthError extends DriftgardError {
14
+ constructor(message = "Invalid or missing API key") {
15
+ super(message, 401, "unauthorized");
16
+ this.name = "AuthError";
17
+ }
18
+ }
19
+ exports.AuthError = AuthError;
20
+ class RateLimitError extends DriftgardError {
21
+ constructor(message = "Rate limit exceeded") {
22
+ super(message, 429, "rate_limited");
23
+ this.name = "RateLimitError";
24
+ }
25
+ }
26
+ exports.RateLimitError = RateLimitError;
27
+ class FeatureNotAvailableError extends DriftgardError {
28
+ constructor(message = "Feature not available on your current plan", tier = "unknown") {
29
+ super(message, 403, "feature_not_available");
30
+ this.name = "FeatureNotAvailableError";
31
+ this.tier = tier;
32
+ }
33
+ }
34
+ exports.FeatureNotAvailableError = FeatureNotAvailableError;
@@ -0,0 +1,18 @@
1
+ import { DriftgardConfig, EvaluateRequest, EvaluateResponse } from "./types";
2
+ export { DriftgardConfig, EvaluateRequest, EvaluateResponse } from "./types";
3
+ export { Violation, EvaluationResult, HitlInfo } from "./types";
4
+ export { DriftgardError, AuthError, RateLimitError, FeatureNotAvailableError } from "./errors";
5
+ export declare class Driftgard {
6
+ private apiKey;
7
+ private baseUrl;
8
+ private timeout;
9
+ private maxRetries;
10
+ constructor(config: DriftgardConfig);
11
+ /**
12
+ * Evaluate a prompt/response pair against your active control pack.
13
+ */
14
+ evaluate(req: EvaluateRequest): Promise<EvaluateResponse>;
15
+ private post;
16
+ private delay;
17
+ }
18
+ export default Driftgard;
package/dist/index.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Driftgard = exports.FeatureNotAvailableError = exports.RateLimitError = exports.AuthError = exports.DriftgardError = void 0;
4
+ const errors_1 = require("./errors");
5
+ var errors_2 = require("./errors");
6
+ Object.defineProperty(exports, "DriftgardError", { enumerable: true, get: function () { return errors_2.DriftgardError; } });
7
+ Object.defineProperty(exports, "AuthError", { enumerable: true, get: function () { return errors_2.AuthError; } });
8
+ Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_2.RateLimitError; } });
9
+ Object.defineProperty(exports, "FeatureNotAvailableError", { enumerable: true, get: function () { return errors_2.FeatureNotAvailableError; } });
10
+ const DEFAULT_BASE_URL = "https://api.driftgard.com";
11
+ const DEFAULT_TIMEOUT = 30000;
12
+ const DEFAULT_MAX_RETRIES = 2;
13
+ const RETRY_DELAY_MS = 500;
14
+ class Driftgard {
15
+ constructor(config) {
16
+ if (!config.apiKey)
17
+ throw new Error("apiKey is required");
18
+ this.apiKey = config.apiKey;
19
+ this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
20
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
21
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
22
+ }
23
+ /**
24
+ * Evaluate a prompt/response pair against your active control pack.
25
+ */
26
+ async evaluate(req) {
27
+ return this.post("/audit/evaluate", {
28
+ project_id: req.project_id,
29
+ prompt: req.prompt,
30
+ response: req.response,
31
+ model_id: req.model_id,
32
+ timestamp: req.timestamp || new Date().toISOString(),
33
+ });
34
+ }
35
+ async post(path, body, attempt = 0) {
36
+ const controller = new AbortController();
37
+ const timer = setTimeout(() => controller.abort(), this.timeout);
38
+ try {
39
+ const res = await fetch(`${this.baseUrl}${path}`, {
40
+ method: "POST",
41
+ headers: {
42
+ "Content-Type": "application/json",
43
+ "x-api-key": this.apiKey,
44
+ },
45
+ body: JSON.stringify(body),
46
+ signal: controller.signal,
47
+ });
48
+ if (res.status === 401)
49
+ throw new errors_1.AuthError();
50
+ if (res.status === 429)
51
+ throw new errors_1.RateLimitError();
52
+ if (res.status === 403) {
53
+ const payload = await res.json().catch(() => ({}));
54
+ if (payload?.error === "feature_not_available") {
55
+ throw new errors_1.FeatureNotAvailableError(payload.message, payload.tier);
56
+ }
57
+ throw new errors_1.DriftgardError(payload?.message || "Forbidden", 403, "forbidden");
58
+ }
59
+ // Retry on 5xx
60
+ if (res.status >= 500 && attempt < this.maxRetries) {
61
+ await this.delay(RETRY_DELAY_MS * Math.pow(2, attempt));
62
+ return this.post(path, body, attempt + 1);
63
+ }
64
+ const payload = await res.json();
65
+ if (!res.ok) {
66
+ throw new errors_1.DriftgardError(payload?.message || payload?.error || "Request failed", res.status, payload?.error || "unknown");
67
+ }
68
+ return payload;
69
+ }
70
+ catch (e) {
71
+ if (e instanceof errors_1.DriftgardError)
72
+ throw e;
73
+ // Network error — retry
74
+ if (attempt < this.maxRetries) {
75
+ await this.delay(RETRY_DELAY_MS * Math.pow(2, attempt));
76
+ return this.post(path, body, attempt + 1);
77
+ }
78
+ const msg = e instanceof Error ? e.message : String(e);
79
+ throw new errors_1.DriftgardError(msg, 0, "network_error");
80
+ }
81
+ finally {
82
+ clearTimeout(timer);
83
+ }
84
+ }
85
+ delay(ms) {
86
+ return new Promise((r) => setTimeout(r, ms));
87
+ }
88
+ }
89
+ exports.Driftgard = Driftgard;
90
+ exports.default = Driftgard;
@@ -0,0 +1,51 @@
1
+ export interface DriftgardConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ timeout?: number;
5
+ maxRetries?: number;
6
+ }
7
+ export interface EvaluateRequest {
8
+ project_id: string;
9
+ prompt: string;
10
+ response: string;
11
+ model_id: string;
12
+ timestamp?: string;
13
+ }
14
+ export interface Violation {
15
+ clause_id?: string;
16
+ severity?: string;
17
+ category?: string;
18
+ reason?: string;
19
+ matched_pattern?: string;
20
+ }
21
+ export interface EvaluationResult {
22
+ allowed: boolean;
23
+ risk_score: number;
24
+ violations: Violation[];
25
+ flags?: {
26
+ pii_detected?: boolean;
27
+ pii_in_prompt?: boolean;
28
+ meta_bypass_detected?: boolean;
29
+ judge_used?: boolean;
30
+ judge_called?: boolean;
31
+ action_blocked?: boolean;
32
+ hard_blocked?: boolean;
33
+ };
34
+ }
35
+ export interface HitlInfo {
36
+ queued: boolean;
37
+ hitl_id?: string;
38
+ selection_mode?: string;
39
+ selection_reasons?: string[];
40
+ }
41
+ export interface EvaluateResponse {
42
+ ok: boolean;
43
+ project_id: string;
44
+ evaluation_id: string;
45
+ active_control_pack_id: string;
46
+ active_control_pack_version: number;
47
+ data_mode: string;
48
+ telemetry_mode: string;
49
+ hitl: HitlInfo;
50
+ evaluation: EvaluationResult;
51
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@driftgard/node",
3
+ "version": "1.0.0",
4
+ "description": "Official Driftgard Node.js SDK — evaluate LLM interactions against your compliance policy",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": ["dist", "README.md"],
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build"
11
+ },
12
+ "keywords": ["driftgard", "ai", "compliance", "guardrails", "llm", "evaluation", "policy", "audit"],
13
+ "author": "Driftgard <support@driftgard.com>",
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/driftgard/driftgard-sdk-node"
18
+ },
19
+ "homepage": "https://driftgard.com",
20
+ "engines": {
21
+ "node": ">=18.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "typescript": "^5.0.0"
25
+ }
26
+ }