@alter-ai/alter-sdk 0.2.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 +234 -0
- package/dist/index.cjs +962 -0
- package/dist/index.d.cts +392 -0
- package/dist/index.d.ts +392 -0
- package/dist/index.js +923 -0
- package/package.json +49 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider and HttpMethod enums for type-safe SDK usage.
|
|
3
|
+
*
|
|
4
|
+
* Static enum of supported OAuth providers. Strings are also accepted
|
|
5
|
+
* by the SDK for forward compatibility with new providers.
|
|
6
|
+
*
|
|
7
|
+
* When adding a new provider to the backend, add it here too.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Supported OAuth provider identifiers.
|
|
11
|
+
*
|
|
12
|
+
* Use these for type safety and IDE autocomplete. The SDK also accepts
|
|
13
|
+
* plain strings for providers not yet in this enum.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { AlterVault, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
18
|
+
*
|
|
19
|
+
* const vault = new AlterVault({ apiKey: "alter_key_..." });
|
|
20
|
+
*
|
|
21
|
+
* // Type-safe (recommended)
|
|
22
|
+
* const resp = await vault.request(
|
|
23
|
+
* Provider.GOOGLE, HttpMethod.GET,
|
|
24
|
+
* "https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
25
|
+
* { user: { user_id: "alice" } },
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* // String also works (forward compatible with new providers)
|
|
29
|
+
* const resp2 = await vault.request(
|
|
30
|
+
* "new-provider", "GET",
|
|
31
|
+
* "https://api.new-provider.com/v1/data",
|
|
32
|
+
* { user: { user_id: "alice" } },
|
|
33
|
+
* );
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare enum Provider {
|
|
37
|
+
GOOGLE = "google",
|
|
38
|
+
GITHUB = "github",
|
|
39
|
+
SLACK = "slack",
|
|
40
|
+
MICROSOFT = "microsoft",
|
|
41
|
+
SALESFORCE = "salesforce",
|
|
42
|
+
SENTRY = "sentry"
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* HTTP methods for type-safe method selection.
|
|
46
|
+
*
|
|
47
|
+
* Use these for IDE autocomplete and type safety. Plain strings
|
|
48
|
+
* are also accepted for forward compatibility.
|
|
49
|
+
*/
|
|
50
|
+
declare enum HttpMethod {
|
|
51
|
+
GET = "GET",
|
|
52
|
+
POST = "POST",
|
|
53
|
+
PUT = "PUT",
|
|
54
|
+
PATCH = "PATCH",
|
|
55
|
+
DELETE = "DELETE",
|
|
56
|
+
HEAD = "HEAD",
|
|
57
|
+
OPTIONS = "OPTIONS"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Main Alter Vault SDK client.
|
|
62
|
+
*
|
|
63
|
+
* This module provides the primary AlterVault class for interacting with
|
|
64
|
+
* the Alter Vault OAuth token management system.
|
|
65
|
+
*
|
|
66
|
+
* Security Hardening (v0.4.0):
|
|
67
|
+
* - Layer 1: Prototype frozen to prevent subclass method override attacks
|
|
68
|
+
* - Layer 1b: HttpClient.prototype also frozen to prevent request interception
|
|
69
|
+
* - Layer 2: Instance frozen after construction (Object.freeze)
|
|
70
|
+
* - Layer 3: API key not stored as instance property
|
|
71
|
+
* - Layer 4: ES2022 private fields (#) for truly private internal state
|
|
72
|
+
* - Layer 5: (see models.ts) TokenResponse access_token in module-private WeakMap
|
|
73
|
+
* - Layer 6: Test accessors removed from production builds
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Configuration options for AlterVault constructor.
|
|
78
|
+
*/
|
|
79
|
+
interface AlterVaultOptions {
|
|
80
|
+
/** Alter Vault API key (must start with "alter_key_") */
|
|
81
|
+
apiKey: string;
|
|
82
|
+
/** Base URL for Alter Vault API */
|
|
83
|
+
baseUrl?: string;
|
|
84
|
+
/** Whether to send audit logs to backend (default: true) */
|
|
85
|
+
enableAuditLogging?: boolean;
|
|
86
|
+
/** HTTP request timeout in milliseconds (default: 30000) */
|
|
87
|
+
timeout?: number;
|
|
88
|
+
/** Actor type ("ai_agent" or "mcp_server") for tracking */
|
|
89
|
+
actorType?: string;
|
|
90
|
+
/** Unique identifier for the actor (e.g., "email-assistant-v2") */
|
|
91
|
+
actorIdentifier?: string;
|
|
92
|
+
/** Human-readable name for the actor */
|
|
93
|
+
actorName?: string;
|
|
94
|
+
/** Actor version string (e.g., "1.0.0") */
|
|
95
|
+
actorVersion?: string;
|
|
96
|
+
/** MCP client type (e.g., "cursor", "claude-desktop") */
|
|
97
|
+
clientType?: string;
|
|
98
|
+
/** AI framework (e.g., "langchain", "langgraph", "crewai") */
|
|
99
|
+
framework?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Options for the request() method.
|
|
103
|
+
*/
|
|
104
|
+
interface RequestOptions {
|
|
105
|
+
/** User attributes to match connection (e.g., { user_id: "alice" }) */
|
|
106
|
+
user: Record<string, unknown>;
|
|
107
|
+
/** Optional JSON request body */
|
|
108
|
+
json?: Record<string, unknown>;
|
|
109
|
+
/** Optional additional headers */
|
|
110
|
+
extraHeaders?: Record<string, string>;
|
|
111
|
+
/** Optional URL query parameters (values are coerced to strings) */
|
|
112
|
+
queryParams?: Record<string, string | number | boolean>;
|
|
113
|
+
/** Optional URL path template substitutions */
|
|
114
|
+
pathParams?: Record<string, string>;
|
|
115
|
+
/** Optional reason for API call (for audit) */
|
|
116
|
+
reason?: string;
|
|
117
|
+
/** Run execution ID (UUID, for actor instance tracking) */
|
|
118
|
+
runId?: string;
|
|
119
|
+
/** Conversation thread ID */
|
|
120
|
+
threadId?: string;
|
|
121
|
+
/** Tool invocation ID */
|
|
122
|
+
toolCallId?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Main SDK class for Alter Vault OAuth token management.
|
|
126
|
+
*
|
|
127
|
+
* This class handles:
|
|
128
|
+
* - Executing API requests to any OAuth provider with automatic token injection
|
|
129
|
+
* - Audit logging of API calls
|
|
130
|
+
* - Actor tracking for AI agents and MCP servers
|
|
131
|
+
*
|
|
132
|
+
* Zero Token Exposure:
|
|
133
|
+
* - Tokens are retrieved internally but NEVER exposed to developers
|
|
134
|
+
* - All API calls inject tokens automatically behind the scenes
|
|
135
|
+
* - Developers only see API results, never authentication credentials
|
|
136
|
+
*
|
|
137
|
+
* Security Hardening:
|
|
138
|
+
* - Cannot be effectively subclassed (prototype is frozen)
|
|
139
|
+
* - Instance is frozen after construction (Object.freeze)
|
|
140
|
+
* - API key is NOT stored as an instance property
|
|
141
|
+
* - Internal HTTP clients use ES2022 private fields (#)
|
|
142
|
+
* - Test accessors are removed (no production leak path)
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* import { AlterVault, Provider, HttpMethod } from "@alter-ai/alter-sdk";
|
|
147
|
+
*
|
|
148
|
+
* const vault = new AlterVault({ apiKey: "alter_key_..." });
|
|
149
|
+
*
|
|
150
|
+
* // Make API request (token injected automatically)
|
|
151
|
+
* const response = await vault.request(
|
|
152
|
+
* Provider.GOOGLE, HttpMethod.GET,
|
|
153
|
+
* "https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
154
|
+
* { user: { user_id: "alice" } },
|
|
155
|
+
* );
|
|
156
|
+
* const events = await response.json();
|
|
157
|
+
*
|
|
158
|
+
* // Clean up
|
|
159
|
+
* await vault.close();
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare class AlterVault {
|
|
163
|
+
#private;
|
|
164
|
+
readonly baseUrl: string;
|
|
165
|
+
readonly enableAuditLogging: boolean;
|
|
166
|
+
constructor(options: AlterVaultOptions);
|
|
167
|
+
/**
|
|
168
|
+
* Execute an HTTP request to a provider API with automatic token injection.
|
|
169
|
+
*
|
|
170
|
+
* This is the single entry point for all provider API calls. The SDK:
|
|
171
|
+
* 1. Fetches an OAuth token from Alter backend (never exposed)
|
|
172
|
+
* 2. Injects the token as a Bearer header
|
|
173
|
+
* 3. Calls the provider API
|
|
174
|
+
* 4. Logs the call for audit (if enabled, fire-and-forget)
|
|
175
|
+
* 5. Returns the raw response
|
|
176
|
+
*/
|
|
177
|
+
request(provider: Provider | string, method: HttpMethod | string, url: string, options: RequestOptions): Promise<Response>;
|
|
178
|
+
/**
|
|
179
|
+
* Close HTTP clients and release resources.
|
|
180
|
+
* Waits for any pending audit tasks before closing.
|
|
181
|
+
*/
|
|
182
|
+
close(): Promise<void>;
|
|
183
|
+
/**
|
|
184
|
+
* Async dispose support for `await using vault = new AlterVault(...)`.
|
|
185
|
+
* Requires TypeScript 5.2+ and Node.js 18+.
|
|
186
|
+
*/
|
|
187
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Models for Alter SDK.
|
|
192
|
+
*
|
|
193
|
+
* These models provide type-safe data structures for SDK operations.
|
|
194
|
+
*
|
|
195
|
+
* Security Hardening (v0.4.0):
|
|
196
|
+
* - TokenResponse: accessToken stored in module-private WeakMap in client.ts
|
|
197
|
+
* (not readable as property, not importable from this module)
|
|
198
|
+
* - TokenResponse: Object.freeze(this) prevents mutation after creation
|
|
199
|
+
* - toJSON() and toString() exclude access token from serialization
|
|
200
|
+
*/
|
|
201
|
+
/**
|
|
202
|
+
* OAuth token response from Alter Vault.
|
|
203
|
+
*
|
|
204
|
+
* This represents an access token retrieved from the backend.
|
|
205
|
+
* The access_token is NOT stored as a readable property — it lives in a
|
|
206
|
+
* module-private WeakMap in client.ts and is only accessible internally.
|
|
207
|
+
*
|
|
208
|
+
* SECURITY:
|
|
209
|
+
* - No accessToken property (stored in WeakMap inside client.ts)
|
|
210
|
+
* - Instance is frozen after construction to prevent mutation
|
|
211
|
+
* - toJSON() and toString() exclude access token
|
|
212
|
+
* - _extractAccessToken() lives in client.ts, NOT in this file,
|
|
213
|
+
* so it cannot be imported by consumers even via deep imports
|
|
214
|
+
*/
|
|
215
|
+
declare class TokenResponse {
|
|
216
|
+
/** Token type (usually "Bearer") */
|
|
217
|
+
readonly tokenType: string;
|
|
218
|
+
/** Seconds until token expires */
|
|
219
|
+
readonly expiresIn: number | null;
|
|
220
|
+
/** Absolute expiration time */
|
|
221
|
+
readonly expiresAt: Date | null;
|
|
222
|
+
/** OAuth scopes granted */
|
|
223
|
+
readonly scopes: string[];
|
|
224
|
+
/** Connection ID that provided this token */
|
|
225
|
+
readonly connectionId: string;
|
|
226
|
+
constructor(data: {
|
|
227
|
+
access_token: string;
|
|
228
|
+
token_type?: string;
|
|
229
|
+
expires_in?: number | null;
|
|
230
|
+
expires_at?: string | null;
|
|
231
|
+
scopes?: string[];
|
|
232
|
+
connection_id: string;
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* Parse expires_at from ISO string.
|
|
236
|
+
*/
|
|
237
|
+
private static parseExpiresAt;
|
|
238
|
+
/**
|
|
239
|
+
* Check if token is expired.
|
|
240
|
+
*
|
|
241
|
+
* @param bufferSeconds - Consider token expired N seconds before actual expiry.
|
|
242
|
+
* Useful for preventing race conditions.
|
|
243
|
+
* @returns True if token is expired or will expire within bufferSeconds.
|
|
244
|
+
*/
|
|
245
|
+
isExpired(bufferSeconds?: number): boolean;
|
|
246
|
+
/**
|
|
247
|
+
* Check if token should be refreshed soon.
|
|
248
|
+
*
|
|
249
|
+
* @param bufferSeconds - Consider token needing refresh N seconds before expiry.
|
|
250
|
+
* Default 5 minutes (300 seconds).
|
|
251
|
+
* @returns True if token will expire within bufferSeconds.
|
|
252
|
+
*/
|
|
253
|
+
needsRefresh(bufferSeconds?: number): boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Custom JSON serialization — EXCLUDES access_token for security.
|
|
256
|
+
*/
|
|
257
|
+
toJSON(): Record<string, unknown>;
|
|
258
|
+
/**
|
|
259
|
+
* Custom string representation — EXCLUDES access_token for security.
|
|
260
|
+
*/
|
|
261
|
+
toString(): string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Audit log entry for an API call to a provider.
|
|
265
|
+
*
|
|
266
|
+
* This is sent to the backend audit endpoint.
|
|
267
|
+
*/
|
|
268
|
+
declare class APICallAuditLog {
|
|
269
|
+
readonly connectionId: string;
|
|
270
|
+
readonly providerId: string;
|
|
271
|
+
readonly method: string;
|
|
272
|
+
readonly url: string;
|
|
273
|
+
readonly requestHeaders: Record<string, string> | null;
|
|
274
|
+
readonly requestBody: unknown | null;
|
|
275
|
+
readonly responseStatus: number;
|
|
276
|
+
readonly responseHeaders: Record<string, string> | null;
|
|
277
|
+
readonly responseBody: unknown | null;
|
|
278
|
+
readonly latencyMs: number;
|
|
279
|
+
/** Client-side timestamp (excluded from sanitize() output, like Python SDK) */
|
|
280
|
+
readonly timestamp: Date;
|
|
281
|
+
readonly reason: string | null;
|
|
282
|
+
/** Execution run ID for actor tracking */
|
|
283
|
+
readonly runId: string | null;
|
|
284
|
+
/** Conversation thread ID for actor tracking */
|
|
285
|
+
readonly threadId: string | null;
|
|
286
|
+
/** Tool invocation ID for actor tracking */
|
|
287
|
+
readonly toolCallId: string | null;
|
|
288
|
+
constructor(data: {
|
|
289
|
+
connectionId: string;
|
|
290
|
+
providerId: string;
|
|
291
|
+
method: string;
|
|
292
|
+
url: string;
|
|
293
|
+
requestHeaders?: Record<string, string> | null;
|
|
294
|
+
requestBody?: unknown | null;
|
|
295
|
+
responseStatus: number;
|
|
296
|
+
responseHeaders?: Record<string, string> | null;
|
|
297
|
+
responseBody?: unknown | null;
|
|
298
|
+
latencyMs: number;
|
|
299
|
+
reason?: string | null;
|
|
300
|
+
runId?: string | null;
|
|
301
|
+
threadId?: string | null;
|
|
302
|
+
toolCallId?: string | null;
|
|
303
|
+
});
|
|
304
|
+
/**
|
|
305
|
+
* Sanitize sensitive data before sending.
|
|
306
|
+
*
|
|
307
|
+
* Removes Authorization headers, cookies, etc.
|
|
308
|
+
*/
|
|
309
|
+
sanitize(): Record<string, unknown>;
|
|
310
|
+
private filterSensitiveHeaders;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Exception hierarchy for Alter SDK.
|
|
315
|
+
*
|
|
316
|
+
* All exceptions inherit from AlterSDKError for easy catching.
|
|
317
|
+
*/
|
|
318
|
+
/**
|
|
319
|
+
* Base exception for all Alter SDK errors.
|
|
320
|
+
*/
|
|
321
|
+
declare class AlterSDKError extends Error {
|
|
322
|
+
readonly details: Record<string, unknown>;
|
|
323
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
324
|
+
toString(): string;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Raised when token retrieval fails.
|
|
328
|
+
*/
|
|
329
|
+
declare class TokenRetrievalError extends AlterSDKError {
|
|
330
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Raised when token access is denied by policy enforcement.
|
|
334
|
+
*
|
|
335
|
+
* This indicates the connection exists but access was denied by Cerbos policy
|
|
336
|
+
* (e.g., unauthorized scopes, outside business hours, rate limit exceeded).
|
|
337
|
+
*/
|
|
338
|
+
declare class PolicyViolationError extends TokenRetrievalError {
|
|
339
|
+
readonly policyError: string | undefined;
|
|
340
|
+
constructor(message: string, policyError?: string, details?: Record<string, unknown>);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Raised when OAuth connection not found.
|
|
344
|
+
*
|
|
345
|
+
* This indicates no connection exists for the given provider and attributes.
|
|
346
|
+
*/
|
|
347
|
+
declare class ConnectionNotFoundError extends TokenRetrievalError {
|
|
348
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Raised when token refresh fails.
|
|
352
|
+
*
|
|
353
|
+
* This indicates the connection exists but token refresh failed (e.g., refresh
|
|
354
|
+
* token revoked, provider API error).
|
|
355
|
+
*/
|
|
356
|
+
declare class TokenExpiredError extends TokenRetrievalError {
|
|
357
|
+
readonly connectionId: string | undefined;
|
|
358
|
+
constructor(message: string, connectionId?: string, details?: Record<string, unknown>);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Raised when provider API call fails.
|
|
362
|
+
*
|
|
363
|
+
* This is raised when the actual provider API returns an error (4xx/5xx).
|
|
364
|
+
*/
|
|
365
|
+
declare class ProviderAPIError extends AlterSDKError {
|
|
366
|
+
readonly statusCode: number | undefined;
|
|
367
|
+
readonly responseBody: string | undefined;
|
|
368
|
+
constructor(message: string, statusCode?: number, responseBody?: string, details?: Record<string, unknown>);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Raised when network operations fail.
|
|
372
|
+
*
|
|
373
|
+
* This includes connection errors, DNS failures, and other network issues when
|
|
374
|
+
* communicating with Alter Vault backend or provider APIs.
|
|
375
|
+
*
|
|
376
|
+
* For timeout-specific errors, see {@link TimeoutError}.
|
|
377
|
+
*/
|
|
378
|
+
declare class NetworkError extends AlterSDKError {
|
|
379
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Raised when a request times out.
|
|
383
|
+
*
|
|
384
|
+
* Extends NetworkError so callers catching NetworkError will still catch timeouts,
|
|
385
|
+
* but callers can also catch TimeoutError specifically to implement retry strategies
|
|
386
|
+
* (e.g., retry on timeout but not on connection refused).
|
|
387
|
+
*/
|
|
388
|
+
declare class TimeoutError extends NetworkError {
|
|
389
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export { APICallAuditLog, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectionNotFoundError, HttpMethod, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
|