@alter-ai/alter-sdk 0.2.1 → 0.2.2
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 +53 -1
- package/dist/index.cjs +198 -3
- package/dist/index.d.cts +243 -124
- package/dist/index.d.ts +243 -124
- package/dist/index.js +195 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Official TypeScript SDK for [Alter Vault](https://alterai.dev) — OAuth token m
|
|
|
8
8
|
- **Single Entry Point**: One method (`vault.request()`) for all provider APIs
|
|
9
9
|
- **Type-Safe Enums**: `Provider` and `HttpMethod` enums with autocomplete
|
|
10
10
|
- **URL Templating**: Path parameter substitution with automatic URL encoding
|
|
11
|
-
- **Automatic Audit Logging**: All API calls logged
|
|
11
|
+
- **Automatic Audit Logging**: All API calls logged with request metadata (HTTP method and URL) for full audit trail
|
|
12
12
|
- **Real-time Policy Enforcement**: Every token request checked against current policies
|
|
13
13
|
- **Automatic Token Refresh**: Tokens refreshed transparently by the backend
|
|
14
14
|
- **Actor Tracking**: First-class support for AI agent and MCP server observability
|
|
@@ -103,6 +103,58 @@ const response = await vault.request(
|
|
|
103
103
|
);
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
### Connection Management
|
|
107
|
+
|
|
108
|
+
#### List Connections
|
|
109
|
+
|
|
110
|
+
Retrieve OAuth connections for your app, optionally filtered by provider:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const result = await vault.listConnections();
|
|
114
|
+
for (const conn of result.connections) {
|
|
115
|
+
console.log(`${conn.providerId}: ${conn.accountDisplayName} (${conn.status})`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Filter by provider with pagination
|
|
119
|
+
const googleConns = await vault.listConnections({
|
|
120
|
+
providerId: "google",
|
|
121
|
+
limit: 10,
|
|
122
|
+
offset: 0,
|
|
123
|
+
});
|
|
124
|
+
console.log(`Total: ${googleConns.total}, Has more: ${googleConns.hasMore}`);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| Parameter | Type | Default | Description |
|
|
128
|
+
|-----------|------|---------|-------------|
|
|
129
|
+
| `providerId` | `string` | - | Filter by provider (e.g., `"google"`) |
|
|
130
|
+
| `limit` | `number` | `100` | Max connections to return |
|
|
131
|
+
| `offset` | `number` | `0` | Pagination offset |
|
|
132
|
+
|
|
133
|
+
Returns `ConnectionListResult` with: `connections` (`ConnectionInfo[]`), `total`, `limit`, `offset`, `hasMore`.
|
|
134
|
+
|
|
135
|
+
#### Create Connect Session
|
|
136
|
+
|
|
137
|
+
Generate a session URL for end-users to authenticate with OAuth providers:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
const session = await vault.createConnectSession({
|
|
141
|
+
endUser: { id: "alice" },
|
|
142
|
+
allowedProviders: ["google", "github"],
|
|
143
|
+
returnUrl: "https://myapp.com/callback",
|
|
144
|
+
});
|
|
145
|
+
console.log(`Connect URL: ${session.connectUrl}`);
|
|
146
|
+
console.log(`Expires in: ${session.expiresIn}s`);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Parameter | Type | Default | Description |
|
|
150
|
+
|-----------|------|---------|-------------|
|
|
151
|
+
| `endUser` | `{ id: string }` | *required* | End user identity |
|
|
152
|
+
| `attributes` | `Record<string, unknown>` | - | Connection attributes |
|
|
153
|
+
| `allowedProviders` | `string[]` | - | Restrict to specific providers |
|
|
154
|
+
| `returnUrl` | `string` | - | Redirect URL after OAuth flow |
|
|
155
|
+
|
|
156
|
+
Returns `ConnectSession` with: `sessionToken`, `connectUrl`, `expiresIn`, `expiresAt`.
|
|
157
|
+
|
|
106
158
|
### AI Agent Actor Tracking
|
|
107
159
|
|
|
108
160
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,9 @@ __export(index_exports, {
|
|
|
23
23
|
APICallAuditLog: () => APICallAuditLog,
|
|
24
24
|
AlterSDKError: () => AlterSDKError,
|
|
25
25
|
AlterVault: () => AlterVault,
|
|
26
|
+
ConnectSession: () => ConnectSession,
|
|
27
|
+
ConnectionInfo: () => ConnectionInfo,
|
|
28
|
+
ConnectionListResult: () => ConnectionListResult,
|
|
26
29
|
ConnectionNotFoundError: () => ConnectionNotFoundError,
|
|
27
30
|
HttpMethod: () => HttpMethod,
|
|
28
31
|
NetworkError: () => NetworkError,
|
|
@@ -182,6 +185,87 @@ var TokenResponse = class _TokenResponse {
|
|
|
182
185
|
return this.toString();
|
|
183
186
|
}
|
|
184
187
|
};
|
|
188
|
+
var ConnectionInfo = class {
|
|
189
|
+
id;
|
|
190
|
+
providerId;
|
|
191
|
+
attributes;
|
|
192
|
+
scopes;
|
|
193
|
+
accountIdentifier;
|
|
194
|
+
accountDisplayName;
|
|
195
|
+
status;
|
|
196
|
+
expiresAt;
|
|
197
|
+
createdAt;
|
|
198
|
+
lastUsedAt;
|
|
199
|
+
constructor(data) {
|
|
200
|
+
this.id = data.id;
|
|
201
|
+
this.providerId = data.provider_id;
|
|
202
|
+
this.attributes = data.attributes ?? {};
|
|
203
|
+
this.scopes = data.scopes ?? [];
|
|
204
|
+
this.accountIdentifier = data.account_identifier ?? null;
|
|
205
|
+
this.accountDisplayName = data.account_display_name ?? null;
|
|
206
|
+
this.status = data.status;
|
|
207
|
+
this.expiresAt = data.expires_at ?? null;
|
|
208
|
+
this.createdAt = data.created_at;
|
|
209
|
+
this.lastUsedAt = data.last_used_at ?? null;
|
|
210
|
+
Object.freeze(this);
|
|
211
|
+
}
|
|
212
|
+
toJSON() {
|
|
213
|
+
return {
|
|
214
|
+
id: this.id,
|
|
215
|
+
provider_id: this.providerId,
|
|
216
|
+
attributes: this.attributes,
|
|
217
|
+
scopes: this.scopes,
|
|
218
|
+
account_identifier: this.accountIdentifier,
|
|
219
|
+
account_display_name: this.accountDisplayName,
|
|
220
|
+
status: this.status,
|
|
221
|
+
expires_at: this.expiresAt,
|
|
222
|
+
created_at: this.createdAt,
|
|
223
|
+
last_used_at: this.lastUsedAt
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
toString() {
|
|
227
|
+
return `ConnectionInfo(id=${this.id}, provider=${this.providerId}, status=${this.status})`;
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var ConnectSession = class {
|
|
231
|
+
sessionToken;
|
|
232
|
+
connectUrl;
|
|
233
|
+
expiresIn;
|
|
234
|
+
expiresAt;
|
|
235
|
+
constructor(data) {
|
|
236
|
+
this.sessionToken = data.session_token;
|
|
237
|
+
this.connectUrl = data.connect_url;
|
|
238
|
+
this.expiresIn = data.expires_in;
|
|
239
|
+
this.expiresAt = data.expires_at;
|
|
240
|
+
Object.freeze(this);
|
|
241
|
+
}
|
|
242
|
+
toJSON() {
|
|
243
|
+
return {
|
|
244
|
+
session_token: this.sessionToken,
|
|
245
|
+
connect_url: this.connectUrl,
|
|
246
|
+
expires_in: this.expiresIn,
|
|
247
|
+
expires_at: this.expiresAt
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
toString() {
|
|
251
|
+
return `ConnectSession(url=${this.connectUrl}, expires_in=${this.expiresIn})`;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
var ConnectionListResult = class {
|
|
255
|
+
connections;
|
|
256
|
+
total;
|
|
257
|
+
limit;
|
|
258
|
+
offset;
|
|
259
|
+
hasMore;
|
|
260
|
+
constructor(data) {
|
|
261
|
+
this.connections = data.connections;
|
|
262
|
+
this.total = data.total;
|
|
263
|
+
this.limit = data.limit;
|
|
264
|
+
this.offset = data.offset;
|
|
265
|
+
this.hasMore = data.has_more;
|
|
266
|
+
Object.freeze(this);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
185
269
|
var SENSITIVE_HEADERS = /* @__PURE__ */ new Set([
|
|
186
270
|
"authorization",
|
|
187
271
|
"cookie",
|
|
@@ -276,7 +360,7 @@ function _extractAccessToken(token) {
|
|
|
276
360
|
return value;
|
|
277
361
|
}
|
|
278
362
|
var _fetch;
|
|
279
|
-
var SDK_VERSION = "0.2.
|
|
363
|
+
var SDK_VERSION = "0.2.2";
|
|
280
364
|
var SDK_USER_AGENT = `alter-sdk-node/${SDK_VERSION}`;
|
|
281
365
|
var VALID_ACTOR_TYPES = ["ai_agent", "mcp_server"];
|
|
282
366
|
var HTTP_FORBIDDEN = 403;
|
|
@@ -627,7 +711,7 @@ var AlterVault = class _AlterVault {
|
|
|
627
711
|
* This is a private method. Tokens are NEVER exposed to developers.
|
|
628
712
|
* Use request() instead, which handles tokens internally.
|
|
629
713
|
*/
|
|
630
|
-
async #getToken(providerId, attributes, reason, runId, threadId, toolCallId) {
|
|
714
|
+
async #getToken(providerId, attributes, reason, requestMetadata, runId, threadId, toolCallId) {
|
|
631
715
|
const actorHeaders = this.#getActorRequestHeaders(
|
|
632
716
|
runId,
|
|
633
717
|
threadId,
|
|
@@ -639,7 +723,8 @@ var AlterVault = class _AlterVault {
|
|
|
639
723
|
json: {
|
|
640
724
|
provider_id: providerId,
|
|
641
725
|
attributes,
|
|
642
|
-
reason: reason ?? null
|
|
726
|
+
reason: reason ?? null,
|
|
727
|
+
request: requestMetadata ?? null
|
|
643
728
|
},
|
|
644
729
|
headers: actorHeaders
|
|
645
730
|
});
|
|
@@ -816,6 +901,7 @@ var AlterVault = class _AlterVault {
|
|
|
816
901
|
providerStr,
|
|
817
902
|
options.user,
|
|
818
903
|
options.reason,
|
|
904
|
+
{ method: methodStr, url },
|
|
819
905
|
options.runId,
|
|
820
906
|
options.threadId,
|
|
821
907
|
options.toolCallId
|
|
@@ -896,6 +982,112 @@ var AlterVault = class _AlterVault {
|
|
|
896
982
|
}
|
|
897
983
|
return response;
|
|
898
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* List OAuth connections for this app.
|
|
987
|
+
*
|
|
988
|
+
* Returns paginated connection metadata (no tokens).
|
|
989
|
+
* Useful for discovering which services a user has connected.
|
|
990
|
+
*/
|
|
991
|
+
async listConnections(options) {
|
|
992
|
+
if (this.#closed) {
|
|
993
|
+
throw new AlterSDKError(
|
|
994
|
+
"SDK instance has been closed. Create a new AlterVault instance to make requests."
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
const actorHeaders = this.#getActorRequestHeaders();
|
|
998
|
+
let response;
|
|
999
|
+
try {
|
|
1000
|
+
response = await this.#alterClient.post("/oauth/connections/list", {
|
|
1001
|
+
json: {
|
|
1002
|
+
provider_id: options?.providerId ?? null,
|
|
1003
|
+
limit: options?.limit ?? 100,
|
|
1004
|
+
offset: options?.offset ?? 0
|
|
1005
|
+
},
|
|
1006
|
+
headers: actorHeaders
|
|
1007
|
+
});
|
|
1008
|
+
} catch (error) {
|
|
1009
|
+
if (_AlterVault.#isTimeoutOrAbortError(error)) {
|
|
1010
|
+
throw new TimeoutError(
|
|
1011
|
+
`Request to Alter Vault backend timed out: ${error instanceof Error ? error.message : String(error)}`,
|
|
1012
|
+
{ base_url: this.baseUrl }
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
if (error instanceof TypeError) {
|
|
1016
|
+
throw new NetworkError(
|
|
1017
|
+
`Failed to connect to Alter Vault backend: ${error.message}`,
|
|
1018
|
+
{ base_url: this.baseUrl }
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
throw new AlterSDKError(
|
|
1022
|
+
`Failed to list connections: ${error instanceof Error ? error.message : String(error)}`
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
this.#cacheActorIdFromResponse(response);
|
|
1026
|
+
await this.#handleErrorResponse(response);
|
|
1027
|
+
const data = await response.json();
|
|
1028
|
+
const connections = data.connections.map(
|
|
1029
|
+
(c) => new ConnectionInfo(
|
|
1030
|
+
c
|
|
1031
|
+
)
|
|
1032
|
+
);
|
|
1033
|
+
return new ConnectionListResult({
|
|
1034
|
+
connections,
|
|
1035
|
+
total: data.total,
|
|
1036
|
+
limit: data.limit,
|
|
1037
|
+
offset: data.offset,
|
|
1038
|
+
has_more: data.has_more
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Create a Connect session for initiating OAuth flows.
|
|
1043
|
+
*
|
|
1044
|
+
* Returns a URL the user can open in their browser to authorize access.
|
|
1045
|
+
*/
|
|
1046
|
+
async createConnectSession(options) {
|
|
1047
|
+
if (this.#closed) {
|
|
1048
|
+
throw new AlterSDKError(
|
|
1049
|
+
"SDK instance has been closed. Create a new AlterVault instance to make requests."
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
if (!options.endUser?.id) {
|
|
1053
|
+
throw new AlterSDKError("endUser.id is required");
|
|
1054
|
+
}
|
|
1055
|
+
const actorHeaders = this.#getActorRequestHeaders();
|
|
1056
|
+
let response;
|
|
1057
|
+
try {
|
|
1058
|
+
response = await this.#alterClient.post("/oauth/connect/session", {
|
|
1059
|
+
json: {
|
|
1060
|
+
end_user: options.endUser,
|
|
1061
|
+
attributes: options.attributes ?? null,
|
|
1062
|
+
allowed_providers: options.allowedProviders ?? null,
|
|
1063
|
+
return_url: options.returnUrl ?? null,
|
|
1064
|
+
allowed_origin: options.allowedOrigin ?? null,
|
|
1065
|
+
metadata: options.metadata ?? null
|
|
1066
|
+
},
|
|
1067
|
+
headers: actorHeaders
|
|
1068
|
+
});
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
if (_AlterVault.#isTimeoutOrAbortError(error)) {
|
|
1071
|
+
throw new TimeoutError(
|
|
1072
|
+
`Request to Alter Vault backend timed out: ${error instanceof Error ? error.message : String(error)}`,
|
|
1073
|
+
{ base_url: this.baseUrl }
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
if (error instanceof TypeError) {
|
|
1077
|
+
throw new NetworkError(
|
|
1078
|
+
`Failed to connect to Alter Vault backend: ${error.message}`,
|
|
1079
|
+
{ base_url: this.baseUrl }
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
throw new AlterSDKError(
|
|
1083
|
+
`Failed to create connect session: ${error instanceof Error ? error.message : String(error)}`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
this.#cacheActorIdFromResponse(response);
|
|
1087
|
+
await this.#handleErrorResponse(response);
|
|
1088
|
+
const data = await response.json();
|
|
1089
|
+
return new ConnectSession(data);
|
|
1090
|
+
}
|
|
899
1091
|
/**
|
|
900
1092
|
* Close HTTP clients and release resources.
|
|
901
1093
|
* Waits for any pending audit tasks before closing.
|
|
@@ -944,6 +1136,9 @@ var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
|
|
|
944
1136
|
APICallAuditLog,
|
|
945
1137
|
AlterSDKError,
|
|
946
1138
|
AlterVault,
|
|
1139
|
+
ConnectSession,
|
|
1140
|
+
ConnectionInfo,
|
|
1141
|
+
ConnectionListResult,
|
|
947
1142
|
ConnectionNotFoundError,
|
|
948
1143
|
HttpMethod,
|
|
949
1144
|
NetworkError,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Models for Alter SDK.
|
|
3
|
+
*
|
|
4
|
+
* These models provide type-safe data structures for SDK operations.
|
|
5
|
+
*
|
|
6
|
+
* Security Hardening (v0.4.0):
|
|
7
|
+
* - TokenResponse: accessToken stored in module-private WeakMap in client.ts
|
|
8
|
+
* (not readable as property, not importable from this module)
|
|
9
|
+
* - TokenResponse: Object.freeze(this) prevents mutation after creation
|
|
10
|
+
* - toJSON() and toString() exclude access token from serialization
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* OAuth token response from Alter Vault.
|
|
14
|
+
*
|
|
15
|
+
* This represents an access token retrieved from the backend.
|
|
16
|
+
* The access_token is NOT stored as a readable property — it lives in a
|
|
17
|
+
* module-private WeakMap in client.ts and is only accessible internally.
|
|
18
|
+
*
|
|
19
|
+
* SECURITY:
|
|
20
|
+
* - No accessToken property (stored in WeakMap inside client.ts)
|
|
21
|
+
* - Instance is frozen after construction to prevent mutation
|
|
22
|
+
* - toJSON() and toString() exclude access token
|
|
23
|
+
* - _extractAccessToken() lives in client.ts, NOT in this file,
|
|
24
|
+
* so it cannot be imported by consumers even via deep imports
|
|
25
|
+
*/
|
|
26
|
+
declare class TokenResponse {
|
|
27
|
+
/** Token type (usually "Bearer") */
|
|
28
|
+
readonly tokenType: string;
|
|
29
|
+
/** Seconds until token expires */
|
|
30
|
+
readonly expiresIn: number | null;
|
|
31
|
+
/** Absolute expiration time */
|
|
32
|
+
readonly expiresAt: Date | null;
|
|
33
|
+
/** OAuth scopes granted */
|
|
34
|
+
readonly scopes: string[];
|
|
35
|
+
/** Connection ID that provided this token */
|
|
36
|
+
readonly connectionId: string;
|
|
37
|
+
constructor(data: {
|
|
38
|
+
access_token: string;
|
|
39
|
+
token_type?: string;
|
|
40
|
+
expires_in?: number | null;
|
|
41
|
+
expires_at?: string | null;
|
|
42
|
+
scopes?: string[];
|
|
43
|
+
connection_id: string;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Parse expires_at from ISO string.
|
|
47
|
+
*/
|
|
48
|
+
private static parseExpiresAt;
|
|
49
|
+
/**
|
|
50
|
+
* Check if token is expired.
|
|
51
|
+
*
|
|
52
|
+
* @param bufferSeconds - Consider token expired N seconds before actual expiry.
|
|
53
|
+
* Useful for preventing race conditions.
|
|
54
|
+
* @returns True if token is expired or will expire within bufferSeconds.
|
|
55
|
+
*/
|
|
56
|
+
isExpired(bufferSeconds?: number): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Check if token should be refreshed soon.
|
|
59
|
+
*
|
|
60
|
+
* @param bufferSeconds - Consider token needing refresh N seconds before expiry.
|
|
61
|
+
* Default 5 minutes (300 seconds).
|
|
62
|
+
* @returns True if token will expire within bufferSeconds.
|
|
63
|
+
*/
|
|
64
|
+
needsRefresh(bufferSeconds?: number): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Custom JSON serialization — EXCLUDES access_token for security.
|
|
67
|
+
*/
|
|
68
|
+
toJSON(): Record<string, unknown>;
|
|
69
|
+
/**
|
|
70
|
+
* Custom string representation — EXCLUDES access_token for security.
|
|
71
|
+
*/
|
|
72
|
+
toString(): string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* OAuth connection info from Alter Vault.
|
|
76
|
+
*
|
|
77
|
+
* Represents a connected OAuth service (e.g., Google, GitHub).
|
|
78
|
+
* Returned by listConnections(). Contains metadata only — no tokens.
|
|
79
|
+
*/
|
|
80
|
+
declare class ConnectionInfo {
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly providerId: string;
|
|
83
|
+
readonly attributes: Record<string, unknown>;
|
|
84
|
+
readonly scopes: string[];
|
|
85
|
+
readonly accountIdentifier: string | null;
|
|
86
|
+
readonly accountDisplayName: string | null;
|
|
87
|
+
readonly status: string;
|
|
88
|
+
readonly expiresAt: string | null;
|
|
89
|
+
readonly createdAt: string;
|
|
90
|
+
readonly lastUsedAt: string | null;
|
|
91
|
+
constructor(data: {
|
|
92
|
+
id: string;
|
|
93
|
+
provider_id: string;
|
|
94
|
+
attributes?: Record<string, unknown>;
|
|
95
|
+
scopes?: string[];
|
|
96
|
+
account_identifier?: string | null;
|
|
97
|
+
account_display_name?: string | null;
|
|
98
|
+
status: string;
|
|
99
|
+
expires_at?: string | null;
|
|
100
|
+
created_at: string;
|
|
101
|
+
last_used_at?: string | null;
|
|
102
|
+
});
|
|
103
|
+
toJSON(): Record<string, unknown>;
|
|
104
|
+
toString(): string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Connect session for initiating OAuth flows.
|
|
108
|
+
*
|
|
109
|
+
* Returned by createConnectSession(). Contains a URL the user
|
|
110
|
+
* opens in their browser to authorize access.
|
|
111
|
+
*/
|
|
112
|
+
declare class ConnectSession {
|
|
113
|
+
readonly sessionToken: string;
|
|
114
|
+
readonly connectUrl: string;
|
|
115
|
+
readonly expiresIn: number;
|
|
116
|
+
readonly expiresAt: string;
|
|
117
|
+
constructor(data: {
|
|
118
|
+
session_token: string;
|
|
119
|
+
connect_url: string;
|
|
120
|
+
expires_in: number;
|
|
121
|
+
expires_at: string;
|
|
122
|
+
});
|
|
123
|
+
toJSON(): Record<string, unknown>;
|
|
124
|
+
toString(): string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Paginated list of connections.
|
|
128
|
+
*
|
|
129
|
+
* Returned by listConnections(). Contains connection array plus pagination metadata.
|
|
130
|
+
*/
|
|
131
|
+
declare class ConnectionListResult {
|
|
132
|
+
readonly connections: ConnectionInfo[];
|
|
133
|
+
readonly total: number;
|
|
134
|
+
readonly limit: number;
|
|
135
|
+
readonly offset: number;
|
|
136
|
+
readonly hasMore: boolean;
|
|
137
|
+
constructor(data: {
|
|
138
|
+
connections: ConnectionInfo[];
|
|
139
|
+
total: number;
|
|
140
|
+
limit: number;
|
|
141
|
+
offset: number;
|
|
142
|
+
has_more: boolean;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Audit log entry for an API call to a provider.
|
|
147
|
+
*
|
|
148
|
+
* This is sent to the backend audit endpoint.
|
|
149
|
+
*/
|
|
150
|
+
declare class APICallAuditLog {
|
|
151
|
+
readonly connectionId: string;
|
|
152
|
+
readonly providerId: string;
|
|
153
|
+
readonly method: string;
|
|
154
|
+
readonly url: string;
|
|
155
|
+
readonly requestHeaders: Record<string, string> | null;
|
|
156
|
+
readonly requestBody: unknown | null;
|
|
157
|
+
readonly responseStatus: number;
|
|
158
|
+
readonly responseHeaders: Record<string, string> | null;
|
|
159
|
+
readonly responseBody: unknown | null;
|
|
160
|
+
readonly latencyMs: number;
|
|
161
|
+
/** Client-side timestamp (excluded from sanitize() output, like Python SDK) */
|
|
162
|
+
readonly timestamp: Date;
|
|
163
|
+
readonly reason: string | null;
|
|
164
|
+
/** Execution run ID for actor tracking */
|
|
165
|
+
readonly runId: string | null;
|
|
166
|
+
/** Conversation thread ID for actor tracking */
|
|
167
|
+
readonly threadId: string | null;
|
|
168
|
+
/** Tool invocation ID for actor tracking */
|
|
169
|
+
readonly toolCallId: string | null;
|
|
170
|
+
constructor(data: {
|
|
171
|
+
connectionId: string;
|
|
172
|
+
providerId: string;
|
|
173
|
+
method: string;
|
|
174
|
+
url: string;
|
|
175
|
+
requestHeaders?: Record<string, string> | null;
|
|
176
|
+
requestBody?: unknown | null;
|
|
177
|
+
responseStatus: number;
|
|
178
|
+
responseHeaders?: Record<string, string> | null;
|
|
179
|
+
responseBody?: unknown | null;
|
|
180
|
+
latencyMs: number;
|
|
181
|
+
reason?: string | null;
|
|
182
|
+
runId?: string | null;
|
|
183
|
+
threadId?: string | null;
|
|
184
|
+
toolCallId?: string | null;
|
|
185
|
+
});
|
|
186
|
+
/**
|
|
187
|
+
* Sanitize sensitive data before sending.
|
|
188
|
+
*
|
|
189
|
+
* Removes Authorization headers, cookies, etc.
|
|
190
|
+
*/
|
|
191
|
+
sanitize(): Record<string, unknown>;
|
|
192
|
+
private filterSensitiveHeaders;
|
|
193
|
+
}
|
|
194
|
+
|
|
1
195
|
/**
|
|
2
196
|
* Provider and HttpMethod enums for type-safe SDK usage.
|
|
3
197
|
*
|
|
@@ -111,6 +305,41 @@ interface RequestOptions {
|
|
|
111
305
|
/** Tool invocation ID */
|
|
112
306
|
toolCallId?: string;
|
|
113
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Options for the listConnections() method.
|
|
310
|
+
*/
|
|
311
|
+
interface ListConnectionsOptions {
|
|
312
|
+
/** Filter by provider ID (e.g., "google") */
|
|
313
|
+
providerId?: string;
|
|
314
|
+
/** Maximum number of connections to return (default 100, max 1000) */
|
|
315
|
+
limit?: number;
|
|
316
|
+
/** Offset for pagination (default 0) */
|
|
317
|
+
offset?: number;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Options for the createConnectSession() method.
|
|
321
|
+
*/
|
|
322
|
+
interface CreateConnectSessionOptions {
|
|
323
|
+
/** End user to create session for (requires at least id) */
|
|
324
|
+
endUser: {
|
|
325
|
+
id: string;
|
|
326
|
+
email?: string;
|
|
327
|
+
name?: string;
|
|
328
|
+
};
|
|
329
|
+
/** User attributes for connection matching */
|
|
330
|
+
attributes?: Record<string, unknown>;
|
|
331
|
+
/** Restrict to specific providers (e.g., ["google", "github"]) */
|
|
332
|
+
allowedProviders?: string[];
|
|
333
|
+
/** URL to redirect after OAuth completion */
|
|
334
|
+
returnUrl?: string;
|
|
335
|
+
/** Allowed origin for postMessage communication */
|
|
336
|
+
allowedOrigin?: string;
|
|
337
|
+
/** Request metadata for audit */
|
|
338
|
+
metadata?: {
|
|
339
|
+
ipAddress?: string;
|
|
340
|
+
userAgent?: string;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
114
343
|
/**
|
|
115
344
|
* Main SDK class for Alter Vault OAuth token management.
|
|
116
345
|
*
|
|
@@ -155,138 +384,28 @@ declare class AlterVault {
|
|
|
155
384
|
*/
|
|
156
385
|
request(provider: Provider | string, method: HttpMethod | string, url: string, options: RequestOptions): Promise<Response>;
|
|
157
386
|
/**
|
|
158
|
-
*
|
|
159
|
-
* Waits for any pending audit tasks before closing.
|
|
160
|
-
*/
|
|
161
|
-
close(): Promise<void>;
|
|
162
|
-
/**
|
|
163
|
-
* Async dispose support for `await using vault = new AlterVault(...)`.
|
|
164
|
-
* Requires TypeScript 5.2+ and Node.js 18+.
|
|
165
|
-
*/
|
|
166
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Models for Alter SDK.
|
|
171
|
-
*
|
|
172
|
-
* These models provide type-safe data structures for SDK operations.
|
|
173
|
-
*
|
|
174
|
-
* Security Hardening (v0.4.0):
|
|
175
|
-
* - TokenResponse: accessToken stored in module-private WeakMap in client.ts
|
|
176
|
-
* (not readable as property, not importable from this module)
|
|
177
|
-
* - TokenResponse: Object.freeze(this) prevents mutation after creation
|
|
178
|
-
* - toJSON() and toString() exclude access token from serialization
|
|
179
|
-
*/
|
|
180
|
-
/**
|
|
181
|
-
* OAuth token response from Alter Vault.
|
|
182
|
-
*
|
|
183
|
-
* This represents an access token retrieved from the backend.
|
|
184
|
-
* The access_token is NOT stored as a readable property — it lives in a
|
|
185
|
-
* module-private WeakMap in client.ts and is only accessible internally.
|
|
186
|
-
*
|
|
187
|
-
* SECURITY:
|
|
188
|
-
* - No accessToken property (stored in WeakMap inside client.ts)
|
|
189
|
-
* - Instance is frozen after construction to prevent mutation
|
|
190
|
-
* - toJSON() and toString() exclude access token
|
|
191
|
-
* - _extractAccessToken() lives in client.ts, NOT in this file,
|
|
192
|
-
* so it cannot be imported by consumers even via deep imports
|
|
193
|
-
*/
|
|
194
|
-
declare class TokenResponse {
|
|
195
|
-
/** Token type (usually "Bearer") */
|
|
196
|
-
readonly tokenType: string;
|
|
197
|
-
/** Seconds until token expires */
|
|
198
|
-
readonly expiresIn: number | null;
|
|
199
|
-
/** Absolute expiration time */
|
|
200
|
-
readonly expiresAt: Date | null;
|
|
201
|
-
/** OAuth scopes granted */
|
|
202
|
-
readonly scopes: string[];
|
|
203
|
-
/** Connection ID that provided this token */
|
|
204
|
-
readonly connectionId: string;
|
|
205
|
-
constructor(data: {
|
|
206
|
-
access_token: string;
|
|
207
|
-
token_type?: string;
|
|
208
|
-
expires_in?: number | null;
|
|
209
|
-
expires_at?: string | null;
|
|
210
|
-
scopes?: string[];
|
|
211
|
-
connection_id: string;
|
|
212
|
-
});
|
|
213
|
-
/**
|
|
214
|
-
* Parse expires_at from ISO string.
|
|
215
|
-
*/
|
|
216
|
-
private static parseExpiresAt;
|
|
217
|
-
/**
|
|
218
|
-
* Check if token is expired.
|
|
387
|
+
* List OAuth connections for this app.
|
|
219
388
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* @returns True if token is expired or will expire within bufferSeconds.
|
|
389
|
+
* Returns paginated connection metadata (no tokens).
|
|
390
|
+
* Useful for discovering which services a user has connected.
|
|
223
391
|
*/
|
|
224
|
-
|
|
392
|
+
listConnections(options?: ListConnectionsOptions): Promise<ConnectionListResult>;
|
|
225
393
|
/**
|
|
226
|
-
*
|
|
394
|
+
* Create a Connect session for initiating OAuth flows.
|
|
227
395
|
*
|
|
228
|
-
*
|
|
229
|
-
* Default 5 minutes (300 seconds).
|
|
230
|
-
* @returns True if token will expire within bufferSeconds.
|
|
396
|
+
* Returns a URL the user can open in their browser to authorize access.
|
|
231
397
|
*/
|
|
232
|
-
|
|
398
|
+
createConnectSession(options: CreateConnectSessionOptions): Promise<ConnectSession>;
|
|
233
399
|
/**
|
|
234
|
-
*
|
|
235
|
-
|
|
236
|
-
toJSON(): Record<string, unknown>;
|
|
237
|
-
/**
|
|
238
|
-
* Custom string representation — EXCLUDES access_token for security.
|
|
400
|
+
* Close HTTP clients and release resources.
|
|
401
|
+
* Waits for any pending audit tasks before closing.
|
|
239
402
|
*/
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Audit log entry for an API call to a provider.
|
|
244
|
-
*
|
|
245
|
-
* This is sent to the backend audit endpoint.
|
|
246
|
-
*/
|
|
247
|
-
declare class APICallAuditLog {
|
|
248
|
-
readonly connectionId: string;
|
|
249
|
-
readonly providerId: string;
|
|
250
|
-
readonly method: string;
|
|
251
|
-
readonly url: string;
|
|
252
|
-
readonly requestHeaders: Record<string, string> | null;
|
|
253
|
-
readonly requestBody: unknown | null;
|
|
254
|
-
readonly responseStatus: number;
|
|
255
|
-
readonly responseHeaders: Record<string, string> | null;
|
|
256
|
-
readonly responseBody: unknown | null;
|
|
257
|
-
readonly latencyMs: number;
|
|
258
|
-
/** Client-side timestamp (excluded from sanitize() output, like Python SDK) */
|
|
259
|
-
readonly timestamp: Date;
|
|
260
|
-
readonly reason: string | null;
|
|
261
|
-
/** Execution run ID for actor tracking */
|
|
262
|
-
readonly runId: string | null;
|
|
263
|
-
/** Conversation thread ID for actor tracking */
|
|
264
|
-
readonly threadId: string | null;
|
|
265
|
-
/** Tool invocation ID for actor tracking */
|
|
266
|
-
readonly toolCallId: string | null;
|
|
267
|
-
constructor(data: {
|
|
268
|
-
connectionId: string;
|
|
269
|
-
providerId: string;
|
|
270
|
-
method: string;
|
|
271
|
-
url: string;
|
|
272
|
-
requestHeaders?: Record<string, string> | null;
|
|
273
|
-
requestBody?: unknown | null;
|
|
274
|
-
responseStatus: number;
|
|
275
|
-
responseHeaders?: Record<string, string> | null;
|
|
276
|
-
responseBody?: unknown | null;
|
|
277
|
-
latencyMs: number;
|
|
278
|
-
reason?: string | null;
|
|
279
|
-
runId?: string | null;
|
|
280
|
-
threadId?: string | null;
|
|
281
|
-
toolCallId?: string | null;
|
|
282
|
-
});
|
|
403
|
+
close(): Promise<void>;
|
|
283
404
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* Removes Authorization headers, cookies, etc.
|
|
405
|
+
* Async dispose support for `await using vault = new AlterVault(...)`.
|
|
406
|
+
* Requires TypeScript 5.2+ and Node.js 18+.
|
|
287
407
|
*/
|
|
288
|
-
|
|
289
|
-
private filterSensitiveHeaders;
|
|
408
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
290
409
|
}
|
|
291
410
|
|
|
292
411
|
/**
|
|
@@ -368,4 +487,4 @@ declare class TimeoutError extends NetworkError {
|
|
|
368
487
|
constructor(message: string, details?: Record<string, unknown>);
|
|
369
488
|
}
|
|
370
489
|
|
|
371
|
-
export { APICallAuditLog, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectionNotFoundError, HttpMethod, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
|
|
490
|
+
export { APICallAuditLog, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectSession, ConnectionInfo, ConnectionListResult, ConnectionNotFoundError, type CreateConnectSessionOptions, HttpMethod, type ListConnectionsOptions, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Models for Alter SDK.
|
|
3
|
+
*
|
|
4
|
+
* These models provide type-safe data structures for SDK operations.
|
|
5
|
+
*
|
|
6
|
+
* Security Hardening (v0.4.0):
|
|
7
|
+
* - TokenResponse: accessToken stored in module-private WeakMap in client.ts
|
|
8
|
+
* (not readable as property, not importable from this module)
|
|
9
|
+
* - TokenResponse: Object.freeze(this) prevents mutation after creation
|
|
10
|
+
* - toJSON() and toString() exclude access token from serialization
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* OAuth token response from Alter Vault.
|
|
14
|
+
*
|
|
15
|
+
* This represents an access token retrieved from the backend.
|
|
16
|
+
* The access_token is NOT stored as a readable property — it lives in a
|
|
17
|
+
* module-private WeakMap in client.ts and is only accessible internally.
|
|
18
|
+
*
|
|
19
|
+
* SECURITY:
|
|
20
|
+
* - No accessToken property (stored in WeakMap inside client.ts)
|
|
21
|
+
* - Instance is frozen after construction to prevent mutation
|
|
22
|
+
* - toJSON() and toString() exclude access token
|
|
23
|
+
* - _extractAccessToken() lives in client.ts, NOT in this file,
|
|
24
|
+
* so it cannot be imported by consumers even via deep imports
|
|
25
|
+
*/
|
|
26
|
+
declare class TokenResponse {
|
|
27
|
+
/** Token type (usually "Bearer") */
|
|
28
|
+
readonly tokenType: string;
|
|
29
|
+
/** Seconds until token expires */
|
|
30
|
+
readonly expiresIn: number | null;
|
|
31
|
+
/** Absolute expiration time */
|
|
32
|
+
readonly expiresAt: Date | null;
|
|
33
|
+
/** OAuth scopes granted */
|
|
34
|
+
readonly scopes: string[];
|
|
35
|
+
/** Connection ID that provided this token */
|
|
36
|
+
readonly connectionId: string;
|
|
37
|
+
constructor(data: {
|
|
38
|
+
access_token: string;
|
|
39
|
+
token_type?: string;
|
|
40
|
+
expires_in?: number | null;
|
|
41
|
+
expires_at?: string | null;
|
|
42
|
+
scopes?: string[];
|
|
43
|
+
connection_id: string;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Parse expires_at from ISO string.
|
|
47
|
+
*/
|
|
48
|
+
private static parseExpiresAt;
|
|
49
|
+
/**
|
|
50
|
+
* Check if token is expired.
|
|
51
|
+
*
|
|
52
|
+
* @param bufferSeconds - Consider token expired N seconds before actual expiry.
|
|
53
|
+
* Useful for preventing race conditions.
|
|
54
|
+
* @returns True if token is expired or will expire within bufferSeconds.
|
|
55
|
+
*/
|
|
56
|
+
isExpired(bufferSeconds?: number): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Check if token should be refreshed soon.
|
|
59
|
+
*
|
|
60
|
+
* @param bufferSeconds - Consider token needing refresh N seconds before expiry.
|
|
61
|
+
* Default 5 minutes (300 seconds).
|
|
62
|
+
* @returns True if token will expire within bufferSeconds.
|
|
63
|
+
*/
|
|
64
|
+
needsRefresh(bufferSeconds?: number): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Custom JSON serialization — EXCLUDES access_token for security.
|
|
67
|
+
*/
|
|
68
|
+
toJSON(): Record<string, unknown>;
|
|
69
|
+
/**
|
|
70
|
+
* Custom string representation — EXCLUDES access_token for security.
|
|
71
|
+
*/
|
|
72
|
+
toString(): string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* OAuth connection info from Alter Vault.
|
|
76
|
+
*
|
|
77
|
+
* Represents a connected OAuth service (e.g., Google, GitHub).
|
|
78
|
+
* Returned by listConnections(). Contains metadata only — no tokens.
|
|
79
|
+
*/
|
|
80
|
+
declare class ConnectionInfo {
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly providerId: string;
|
|
83
|
+
readonly attributes: Record<string, unknown>;
|
|
84
|
+
readonly scopes: string[];
|
|
85
|
+
readonly accountIdentifier: string | null;
|
|
86
|
+
readonly accountDisplayName: string | null;
|
|
87
|
+
readonly status: string;
|
|
88
|
+
readonly expiresAt: string | null;
|
|
89
|
+
readonly createdAt: string;
|
|
90
|
+
readonly lastUsedAt: string | null;
|
|
91
|
+
constructor(data: {
|
|
92
|
+
id: string;
|
|
93
|
+
provider_id: string;
|
|
94
|
+
attributes?: Record<string, unknown>;
|
|
95
|
+
scopes?: string[];
|
|
96
|
+
account_identifier?: string | null;
|
|
97
|
+
account_display_name?: string | null;
|
|
98
|
+
status: string;
|
|
99
|
+
expires_at?: string | null;
|
|
100
|
+
created_at: string;
|
|
101
|
+
last_used_at?: string | null;
|
|
102
|
+
});
|
|
103
|
+
toJSON(): Record<string, unknown>;
|
|
104
|
+
toString(): string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Connect session for initiating OAuth flows.
|
|
108
|
+
*
|
|
109
|
+
* Returned by createConnectSession(). Contains a URL the user
|
|
110
|
+
* opens in their browser to authorize access.
|
|
111
|
+
*/
|
|
112
|
+
declare class ConnectSession {
|
|
113
|
+
readonly sessionToken: string;
|
|
114
|
+
readonly connectUrl: string;
|
|
115
|
+
readonly expiresIn: number;
|
|
116
|
+
readonly expiresAt: string;
|
|
117
|
+
constructor(data: {
|
|
118
|
+
session_token: string;
|
|
119
|
+
connect_url: string;
|
|
120
|
+
expires_in: number;
|
|
121
|
+
expires_at: string;
|
|
122
|
+
});
|
|
123
|
+
toJSON(): Record<string, unknown>;
|
|
124
|
+
toString(): string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Paginated list of connections.
|
|
128
|
+
*
|
|
129
|
+
* Returned by listConnections(). Contains connection array plus pagination metadata.
|
|
130
|
+
*/
|
|
131
|
+
declare class ConnectionListResult {
|
|
132
|
+
readonly connections: ConnectionInfo[];
|
|
133
|
+
readonly total: number;
|
|
134
|
+
readonly limit: number;
|
|
135
|
+
readonly offset: number;
|
|
136
|
+
readonly hasMore: boolean;
|
|
137
|
+
constructor(data: {
|
|
138
|
+
connections: ConnectionInfo[];
|
|
139
|
+
total: number;
|
|
140
|
+
limit: number;
|
|
141
|
+
offset: number;
|
|
142
|
+
has_more: boolean;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Audit log entry for an API call to a provider.
|
|
147
|
+
*
|
|
148
|
+
* This is sent to the backend audit endpoint.
|
|
149
|
+
*/
|
|
150
|
+
declare class APICallAuditLog {
|
|
151
|
+
readonly connectionId: string;
|
|
152
|
+
readonly providerId: string;
|
|
153
|
+
readonly method: string;
|
|
154
|
+
readonly url: string;
|
|
155
|
+
readonly requestHeaders: Record<string, string> | null;
|
|
156
|
+
readonly requestBody: unknown | null;
|
|
157
|
+
readonly responseStatus: number;
|
|
158
|
+
readonly responseHeaders: Record<string, string> | null;
|
|
159
|
+
readonly responseBody: unknown | null;
|
|
160
|
+
readonly latencyMs: number;
|
|
161
|
+
/** Client-side timestamp (excluded from sanitize() output, like Python SDK) */
|
|
162
|
+
readonly timestamp: Date;
|
|
163
|
+
readonly reason: string | null;
|
|
164
|
+
/** Execution run ID for actor tracking */
|
|
165
|
+
readonly runId: string | null;
|
|
166
|
+
/** Conversation thread ID for actor tracking */
|
|
167
|
+
readonly threadId: string | null;
|
|
168
|
+
/** Tool invocation ID for actor tracking */
|
|
169
|
+
readonly toolCallId: string | null;
|
|
170
|
+
constructor(data: {
|
|
171
|
+
connectionId: string;
|
|
172
|
+
providerId: string;
|
|
173
|
+
method: string;
|
|
174
|
+
url: string;
|
|
175
|
+
requestHeaders?: Record<string, string> | null;
|
|
176
|
+
requestBody?: unknown | null;
|
|
177
|
+
responseStatus: number;
|
|
178
|
+
responseHeaders?: Record<string, string> | null;
|
|
179
|
+
responseBody?: unknown | null;
|
|
180
|
+
latencyMs: number;
|
|
181
|
+
reason?: string | null;
|
|
182
|
+
runId?: string | null;
|
|
183
|
+
threadId?: string | null;
|
|
184
|
+
toolCallId?: string | null;
|
|
185
|
+
});
|
|
186
|
+
/**
|
|
187
|
+
* Sanitize sensitive data before sending.
|
|
188
|
+
*
|
|
189
|
+
* Removes Authorization headers, cookies, etc.
|
|
190
|
+
*/
|
|
191
|
+
sanitize(): Record<string, unknown>;
|
|
192
|
+
private filterSensitiveHeaders;
|
|
193
|
+
}
|
|
194
|
+
|
|
1
195
|
/**
|
|
2
196
|
* Provider and HttpMethod enums for type-safe SDK usage.
|
|
3
197
|
*
|
|
@@ -111,6 +305,41 @@ interface RequestOptions {
|
|
|
111
305
|
/** Tool invocation ID */
|
|
112
306
|
toolCallId?: string;
|
|
113
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Options for the listConnections() method.
|
|
310
|
+
*/
|
|
311
|
+
interface ListConnectionsOptions {
|
|
312
|
+
/** Filter by provider ID (e.g., "google") */
|
|
313
|
+
providerId?: string;
|
|
314
|
+
/** Maximum number of connections to return (default 100, max 1000) */
|
|
315
|
+
limit?: number;
|
|
316
|
+
/** Offset for pagination (default 0) */
|
|
317
|
+
offset?: number;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Options for the createConnectSession() method.
|
|
321
|
+
*/
|
|
322
|
+
interface CreateConnectSessionOptions {
|
|
323
|
+
/** End user to create session for (requires at least id) */
|
|
324
|
+
endUser: {
|
|
325
|
+
id: string;
|
|
326
|
+
email?: string;
|
|
327
|
+
name?: string;
|
|
328
|
+
};
|
|
329
|
+
/** User attributes for connection matching */
|
|
330
|
+
attributes?: Record<string, unknown>;
|
|
331
|
+
/** Restrict to specific providers (e.g., ["google", "github"]) */
|
|
332
|
+
allowedProviders?: string[];
|
|
333
|
+
/** URL to redirect after OAuth completion */
|
|
334
|
+
returnUrl?: string;
|
|
335
|
+
/** Allowed origin for postMessage communication */
|
|
336
|
+
allowedOrigin?: string;
|
|
337
|
+
/** Request metadata for audit */
|
|
338
|
+
metadata?: {
|
|
339
|
+
ipAddress?: string;
|
|
340
|
+
userAgent?: string;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
114
343
|
/**
|
|
115
344
|
* Main SDK class for Alter Vault OAuth token management.
|
|
116
345
|
*
|
|
@@ -155,138 +384,28 @@ declare class AlterVault {
|
|
|
155
384
|
*/
|
|
156
385
|
request(provider: Provider | string, method: HttpMethod | string, url: string, options: RequestOptions): Promise<Response>;
|
|
157
386
|
/**
|
|
158
|
-
*
|
|
159
|
-
* Waits for any pending audit tasks before closing.
|
|
160
|
-
*/
|
|
161
|
-
close(): Promise<void>;
|
|
162
|
-
/**
|
|
163
|
-
* Async dispose support for `await using vault = new AlterVault(...)`.
|
|
164
|
-
* Requires TypeScript 5.2+ and Node.js 18+.
|
|
165
|
-
*/
|
|
166
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Models for Alter SDK.
|
|
171
|
-
*
|
|
172
|
-
* These models provide type-safe data structures for SDK operations.
|
|
173
|
-
*
|
|
174
|
-
* Security Hardening (v0.4.0):
|
|
175
|
-
* - TokenResponse: accessToken stored in module-private WeakMap in client.ts
|
|
176
|
-
* (not readable as property, not importable from this module)
|
|
177
|
-
* - TokenResponse: Object.freeze(this) prevents mutation after creation
|
|
178
|
-
* - toJSON() and toString() exclude access token from serialization
|
|
179
|
-
*/
|
|
180
|
-
/**
|
|
181
|
-
* OAuth token response from Alter Vault.
|
|
182
|
-
*
|
|
183
|
-
* This represents an access token retrieved from the backend.
|
|
184
|
-
* The access_token is NOT stored as a readable property — it lives in a
|
|
185
|
-
* module-private WeakMap in client.ts and is only accessible internally.
|
|
186
|
-
*
|
|
187
|
-
* SECURITY:
|
|
188
|
-
* - No accessToken property (stored in WeakMap inside client.ts)
|
|
189
|
-
* - Instance is frozen after construction to prevent mutation
|
|
190
|
-
* - toJSON() and toString() exclude access token
|
|
191
|
-
* - _extractAccessToken() lives in client.ts, NOT in this file,
|
|
192
|
-
* so it cannot be imported by consumers even via deep imports
|
|
193
|
-
*/
|
|
194
|
-
declare class TokenResponse {
|
|
195
|
-
/** Token type (usually "Bearer") */
|
|
196
|
-
readonly tokenType: string;
|
|
197
|
-
/** Seconds until token expires */
|
|
198
|
-
readonly expiresIn: number | null;
|
|
199
|
-
/** Absolute expiration time */
|
|
200
|
-
readonly expiresAt: Date | null;
|
|
201
|
-
/** OAuth scopes granted */
|
|
202
|
-
readonly scopes: string[];
|
|
203
|
-
/** Connection ID that provided this token */
|
|
204
|
-
readonly connectionId: string;
|
|
205
|
-
constructor(data: {
|
|
206
|
-
access_token: string;
|
|
207
|
-
token_type?: string;
|
|
208
|
-
expires_in?: number | null;
|
|
209
|
-
expires_at?: string | null;
|
|
210
|
-
scopes?: string[];
|
|
211
|
-
connection_id: string;
|
|
212
|
-
});
|
|
213
|
-
/**
|
|
214
|
-
* Parse expires_at from ISO string.
|
|
215
|
-
*/
|
|
216
|
-
private static parseExpiresAt;
|
|
217
|
-
/**
|
|
218
|
-
* Check if token is expired.
|
|
387
|
+
* List OAuth connections for this app.
|
|
219
388
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* @returns True if token is expired or will expire within bufferSeconds.
|
|
389
|
+
* Returns paginated connection metadata (no tokens).
|
|
390
|
+
* Useful for discovering which services a user has connected.
|
|
223
391
|
*/
|
|
224
|
-
|
|
392
|
+
listConnections(options?: ListConnectionsOptions): Promise<ConnectionListResult>;
|
|
225
393
|
/**
|
|
226
|
-
*
|
|
394
|
+
* Create a Connect session for initiating OAuth flows.
|
|
227
395
|
*
|
|
228
|
-
*
|
|
229
|
-
* Default 5 minutes (300 seconds).
|
|
230
|
-
* @returns True if token will expire within bufferSeconds.
|
|
396
|
+
* Returns a URL the user can open in their browser to authorize access.
|
|
231
397
|
*/
|
|
232
|
-
|
|
398
|
+
createConnectSession(options: CreateConnectSessionOptions): Promise<ConnectSession>;
|
|
233
399
|
/**
|
|
234
|
-
*
|
|
235
|
-
|
|
236
|
-
toJSON(): Record<string, unknown>;
|
|
237
|
-
/**
|
|
238
|
-
* Custom string representation — EXCLUDES access_token for security.
|
|
400
|
+
* Close HTTP clients and release resources.
|
|
401
|
+
* Waits for any pending audit tasks before closing.
|
|
239
402
|
*/
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Audit log entry for an API call to a provider.
|
|
244
|
-
*
|
|
245
|
-
* This is sent to the backend audit endpoint.
|
|
246
|
-
*/
|
|
247
|
-
declare class APICallAuditLog {
|
|
248
|
-
readonly connectionId: string;
|
|
249
|
-
readonly providerId: string;
|
|
250
|
-
readonly method: string;
|
|
251
|
-
readonly url: string;
|
|
252
|
-
readonly requestHeaders: Record<string, string> | null;
|
|
253
|
-
readonly requestBody: unknown | null;
|
|
254
|
-
readonly responseStatus: number;
|
|
255
|
-
readonly responseHeaders: Record<string, string> | null;
|
|
256
|
-
readonly responseBody: unknown | null;
|
|
257
|
-
readonly latencyMs: number;
|
|
258
|
-
/** Client-side timestamp (excluded from sanitize() output, like Python SDK) */
|
|
259
|
-
readonly timestamp: Date;
|
|
260
|
-
readonly reason: string | null;
|
|
261
|
-
/** Execution run ID for actor tracking */
|
|
262
|
-
readonly runId: string | null;
|
|
263
|
-
/** Conversation thread ID for actor tracking */
|
|
264
|
-
readonly threadId: string | null;
|
|
265
|
-
/** Tool invocation ID for actor tracking */
|
|
266
|
-
readonly toolCallId: string | null;
|
|
267
|
-
constructor(data: {
|
|
268
|
-
connectionId: string;
|
|
269
|
-
providerId: string;
|
|
270
|
-
method: string;
|
|
271
|
-
url: string;
|
|
272
|
-
requestHeaders?: Record<string, string> | null;
|
|
273
|
-
requestBody?: unknown | null;
|
|
274
|
-
responseStatus: number;
|
|
275
|
-
responseHeaders?: Record<string, string> | null;
|
|
276
|
-
responseBody?: unknown | null;
|
|
277
|
-
latencyMs: number;
|
|
278
|
-
reason?: string | null;
|
|
279
|
-
runId?: string | null;
|
|
280
|
-
threadId?: string | null;
|
|
281
|
-
toolCallId?: string | null;
|
|
282
|
-
});
|
|
403
|
+
close(): Promise<void>;
|
|
283
404
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* Removes Authorization headers, cookies, etc.
|
|
405
|
+
* Async dispose support for `await using vault = new AlterVault(...)`.
|
|
406
|
+
* Requires TypeScript 5.2+ and Node.js 18+.
|
|
287
407
|
*/
|
|
288
|
-
|
|
289
|
-
private filterSensitiveHeaders;
|
|
408
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
290
409
|
}
|
|
291
410
|
|
|
292
411
|
/**
|
|
@@ -368,4 +487,4 @@ declare class TimeoutError extends NetworkError {
|
|
|
368
487
|
constructor(message: string, details?: Record<string, unknown>);
|
|
369
488
|
}
|
|
370
489
|
|
|
371
|
-
export { APICallAuditLog, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectionNotFoundError, HttpMethod, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
|
|
490
|
+
export { APICallAuditLog, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectSession, ConnectionInfo, ConnectionListResult, ConnectionNotFoundError, type CreateConnectSessionOptions, HttpMethod, type ListConnectionsOptions, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
|
package/dist/index.js
CHANGED
|
@@ -144,6 +144,87 @@ var TokenResponse = class _TokenResponse {
|
|
|
144
144
|
return this.toString();
|
|
145
145
|
}
|
|
146
146
|
};
|
|
147
|
+
var ConnectionInfo = class {
|
|
148
|
+
id;
|
|
149
|
+
providerId;
|
|
150
|
+
attributes;
|
|
151
|
+
scopes;
|
|
152
|
+
accountIdentifier;
|
|
153
|
+
accountDisplayName;
|
|
154
|
+
status;
|
|
155
|
+
expiresAt;
|
|
156
|
+
createdAt;
|
|
157
|
+
lastUsedAt;
|
|
158
|
+
constructor(data) {
|
|
159
|
+
this.id = data.id;
|
|
160
|
+
this.providerId = data.provider_id;
|
|
161
|
+
this.attributes = data.attributes ?? {};
|
|
162
|
+
this.scopes = data.scopes ?? [];
|
|
163
|
+
this.accountIdentifier = data.account_identifier ?? null;
|
|
164
|
+
this.accountDisplayName = data.account_display_name ?? null;
|
|
165
|
+
this.status = data.status;
|
|
166
|
+
this.expiresAt = data.expires_at ?? null;
|
|
167
|
+
this.createdAt = data.created_at;
|
|
168
|
+
this.lastUsedAt = data.last_used_at ?? null;
|
|
169
|
+
Object.freeze(this);
|
|
170
|
+
}
|
|
171
|
+
toJSON() {
|
|
172
|
+
return {
|
|
173
|
+
id: this.id,
|
|
174
|
+
provider_id: this.providerId,
|
|
175
|
+
attributes: this.attributes,
|
|
176
|
+
scopes: this.scopes,
|
|
177
|
+
account_identifier: this.accountIdentifier,
|
|
178
|
+
account_display_name: this.accountDisplayName,
|
|
179
|
+
status: this.status,
|
|
180
|
+
expires_at: this.expiresAt,
|
|
181
|
+
created_at: this.createdAt,
|
|
182
|
+
last_used_at: this.lastUsedAt
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
toString() {
|
|
186
|
+
return `ConnectionInfo(id=${this.id}, provider=${this.providerId}, status=${this.status})`;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
var ConnectSession = class {
|
|
190
|
+
sessionToken;
|
|
191
|
+
connectUrl;
|
|
192
|
+
expiresIn;
|
|
193
|
+
expiresAt;
|
|
194
|
+
constructor(data) {
|
|
195
|
+
this.sessionToken = data.session_token;
|
|
196
|
+
this.connectUrl = data.connect_url;
|
|
197
|
+
this.expiresIn = data.expires_in;
|
|
198
|
+
this.expiresAt = data.expires_at;
|
|
199
|
+
Object.freeze(this);
|
|
200
|
+
}
|
|
201
|
+
toJSON() {
|
|
202
|
+
return {
|
|
203
|
+
session_token: this.sessionToken,
|
|
204
|
+
connect_url: this.connectUrl,
|
|
205
|
+
expires_in: this.expiresIn,
|
|
206
|
+
expires_at: this.expiresAt
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
toString() {
|
|
210
|
+
return `ConnectSession(url=${this.connectUrl}, expires_in=${this.expiresIn})`;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
var ConnectionListResult = class {
|
|
214
|
+
connections;
|
|
215
|
+
total;
|
|
216
|
+
limit;
|
|
217
|
+
offset;
|
|
218
|
+
hasMore;
|
|
219
|
+
constructor(data) {
|
|
220
|
+
this.connections = data.connections;
|
|
221
|
+
this.total = data.total;
|
|
222
|
+
this.limit = data.limit;
|
|
223
|
+
this.offset = data.offset;
|
|
224
|
+
this.hasMore = data.has_more;
|
|
225
|
+
Object.freeze(this);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
147
228
|
var SENSITIVE_HEADERS = /* @__PURE__ */ new Set([
|
|
148
229
|
"authorization",
|
|
149
230
|
"cookie",
|
|
@@ -238,7 +319,7 @@ function _extractAccessToken(token) {
|
|
|
238
319
|
return value;
|
|
239
320
|
}
|
|
240
321
|
var _fetch;
|
|
241
|
-
var SDK_VERSION = "0.2.
|
|
322
|
+
var SDK_VERSION = "0.2.2";
|
|
242
323
|
var SDK_USER_AGENT = `alter-sdk-node/${SDK_VERSION}`;
|
|
243
324
|
var VALID_ACTOR_TYPES = ["ai_agent", "mcp_server"];
|
|
244
325
|
var HTTP_FORBIDDEN = 403;
|
|
@@ -589,7 +670,7 @@ var AlterVault = class _AlterVault {
|
|
|
589
670
|
* This is a private method. Tokens are NEVER exposed to developers.
|
|
590
671
|
* Use request() instead, which handles tokens internally.
|
|
591
672
|
*/
|
|
592
|
-
async #getToken(providerId, attributes, reason, runId, threadId, toolCallId) {
|
|
673
|
+
async #getToken(providerId, attributes, reason, requestMetadata, runId, threadId, toolCallId) {
|
|
593
674
|
const actorHeaders = this.#getActorRequestHeaders(
|
|
594
675
|
runId,
|
|
595
676
|
threadId,
|
|
@@ -601,7 +682,8 @@ var AlterVault = class _AlterVault {
|
|
|
601
682
|
json: {
|
|
602
683
|
provider_id: providerId,
|
|
603
684
|
attributes,
|
|
604
|
-
reason: reason ?? null
|
|
685
|
+
reason: reason ?? null,
|
|
686
|
+
request: requestMetadata ?? null
|
|
605
687
|
},
|
|
606
688
|
headers: actorHeaders
|
|
607
689
|
});
|
|
@@ -778,6 +860,7 @@ var AlterVault = class _AlterVault {
|
|
|
778
860
|
providerStr,
|
|
779
861
|
options.user,
|
|
780
862
|
options.reason,
|
|
863
|
+
{ method: methodStr, url },
|
|
781
864
|
options.runId,
|
|
782
865
|
options.threadId,
|
|
783
866
|
options.toolCallId
|
|
@@ -858,6 +941,112 @@ var AlterVault = class _AlterVault {
|
|
|
858
941
|
}
|
|
859
942
|
return response;
|
|
860
943
|
}
|
|
944
|
+
/**
|
|
945
|
+
* List OAuth connections for this app.
|
|
946
|
+
*
|
|
947
|
+
* Returns paginated connection metadata (no tokens).
|
|
948
|
+
* Useful for discovering which services a user has connected.
|
|
949
|
+
*/
|
|
950
|
+
async listConnections(options) {
|
|
951
|
+
if (this.#closed) {
|
|
952
|
+
throw new AlterSDKError(
|
|
953
|
+
"SDK instance has been closed. Create a new AlterVault instance to make requests."
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
const actorHeaders = this.#getActorRequestHeaders();
|
|
957
|
+
let response;
|
|
958
|
+
try {
|
|
959
|
+
response = await this.#alterClient.post("/oauth/connections/list", {
|
|
960
|
+
json: {
|
|
961
|
+
provider_id: options?.providerId ?? null,
|
|
962
|
+
limit: options?.limit ?? 100,
|
|
963
|
+
offset: options?.offset ?? 0
|
|
964
|
+
},
|
|
965
|
+
headers: actorHeaders
|
|
966
|
+
});
|
|
967
|
+
} catch (error) {
|
|
968
|
+
if (_AlterVault.#isTimeoutOrAbortError(error)) {
|
|
969
|
+
throw new TimeoutError(
|
|
970
|
+
`Request to Alter Vault backend timed out: ${error instanceof Error ? error.message : String(error)}`,
|
|
971
|
+
{ base_url: this.baseUrl }
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
if (error instanceof TypeError) {
|
|
975
|
+
throw new NetworkError(
|
|
976
|
+
`Failed to connect to Alter Vault backend: ${error.message}`,
|
|
977
|
+
{ base_url: this.baseUrl }
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
throw new AlterSDKError(
|
|
981
|
+
`Failed to list connections: ${error instanceof Error ? error.message : String(error)}`
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
this.#cacheActorIdFromResponse(response);
|
|
985
|
+
await this.#handleErrorResponse(response);
|
|
986
|
+
const data = await response.json();
|
|
987
|
+
const connections = data.connections.map(
|
|
988
|
+
(c) => new ConnectionInfo(
|
|
989
|
+
c
|
|
990
|
+
)
|
|
991
|
+
);
|
|
992
|
+
return new ConnectionListResult({
|
|
993
|
+
connections,
|
|
994
|
+
total: data.total,
|
|
995
|
+
limit: data.limit,
|
|
996
|
+
offset: data.offset,
|
|
997
|
+
has_more: data.has_more
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Create a Connect session for initiating OAuth flows.
|
|
1002
|
+
*
|
|
1003
|
+
* Returns a URL the user can open in their browser to authorize access.
|
|
1004
|
+
*/
|
|
1005
|
+
async createConnectSession(options) {
|
|
1006
|
+
if (this.#closed) {
|
|
1007
|
+
throw new AlterSDKError(
|
|
1008
|
+
"SDK instance has been closed. Create a new AlterVault instance to make requests."
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
if (!options.endUser?.id) {
|
|
1012
|
+
throw new AlterSDKError("endUser.id is required");
|
|
1013
|
+
}
|
|
1014
|
+
const actorHeaders = this.#getActorRequestHeaders();
|
|
1015
|
+
let response;
|
|
1016
|
+
try {
|
|
1017
|
+
response = await this.#alterClient.post("/oauth/connect/session", {
|
|
1018
|
+
json: {
|
|
1019
|
+
end_user: options.endUser,
|
|
1020
|
+
attributes: options.attributes ?? null,
|
|
1021
|
+
allowed_providers: options.allowedProviders ?? null,
|
|
1022
|
+
return_url: options.returnUrl ?? null,
|
|
1023
|
+
allowed_origin: options.allowedOrigin ?? null,
|
|
1024
|
+
metadata: options.metadata ?? null
|
|
1025
|
+
},
|
|
1026
|
+
headers: actorHeaders
|
|
1027
|
+
});
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
if (_AlterVault.#isTimeoutOrAbortError(error)) {
|
|
1030
|
+
throw new TimeoutError(
|
|
1031
|
+
`Request to Alter Vault backend timed out: ${error instanceof Error ? error.message : String(error)}`,
|
|
1032
|
+
{ base_url: this.baseUrl }
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
if (error instanceof TypeError) {
|
|
1036
|
+
throw new NetworkError(
|
|
1037
|
+
`Failed to connect to Alter Vault backend: ${error.message}`,
|
|
1038
|
+
{ base_url: this.baseUrl }
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
throw new AlterSDKError(
|
|
1042
|
+
`Failed to create connect session: ${error instanceof Error ? error.message : String(error)}`
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
this.#cacheActorIdFromResponse(response);
|
|
1046
|
+
await this.#handleErrorResponse(response);
|
|
1047
|
+
const data = await response.json();
|
|
1048
|
+
return new ConnectSession(data);
|
|
1049
|
+
}
|
|
861
1050
|
/**
|
|
862
1051
|
* Close HTTP clients and release resources.
|
|
863
1052
|
* Waits for any pending audit tasks before closing.
|
|
@@ -905,6 +1094,9 @@ export {
|
|
|
905
1094
|
APICallAuditLog,
|
|
906
1095
|
AlterSDKError,
|
|
907
1096
|
AlterVault,
|
|
1097
|
+
ConnectSession,
|
|
1098
|
+
ConnectionInfo,
|
|
1099
|
+
ConnectionListResult,
|
|
908
1100
|
ConnectionNotFoundError,
|
|
909
1101
|
HttpMethod,
|
|
910
1102
|
NetworkError,
|