@alter-ai/alter-sdk 0.4.0 → 0.6.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/dist/index.cjs CHANGED
@@ -34,22 +34,28 @@ __export(index_exports, {
34
34
  ActorType: () => ActorType,
35
35
  AlterSDKError: () => AlterSDKError,
36
36
  AlterVault: () => AlterVault,
37
+ BackendError: () => BackendError,
38
+ ConnectConfigError: () => ConnectConfigError,
39
+ ConnectDeniedError: () => ConnectDeniedError,
37
40
  ConnectFlowError: () => ConnectFlowError,
38
41
  ConnectResult: () => ConnectResult,
39
42
  ConnectSession: () => ConnectSession,
40
43
  ConnectTimeoutError: () => ConnectTimeoutError,
44
+ ConnectionDeletedError: () => ConnectionDeletedError,
45
+ ConnectionExpiredError: () => ConnectionExpiredError,
41
46
  ConnectionInfo: () => ConnectionInfo,
42
47
  ConnectionListResult: () => ConnectionListResult,
43
48
  ConnectionNotFoundError: () => ConnectionNotFoundError,
49
+ ConnectionRevokedError: () => ConnectionRevokedError,
44
50
  HttpMethod: () => HttpMethod,
45
51
  NetworkError: () => NetworkError,
46
52
  PolicyViolationError: () => PolicyViolationError,
47
53
  Provider: () => Provider,
48
54
  ProviderAPIError: () => ProviderAPIError,
55
+ ReAuthRequiredError: () => ReAuthRequiredError,
56
+ ScopeReauthRequiredError: () => ScopeReauthRequiredError,
49
57
  TimeoutError: () => TimeoutError,
50
- TokenExpiredError: () => TokenExpiredError,
51
- TokenResponse: () => TokenResponse,
52
- TokenRetrievalError: () => TokenRetrievalError
58
+ TokenResponse: () => TokenResponse
53
59
  });
54
60
  module.exports = __toCommonJS(index_exports);
55
61
 
@@ -72,40 +78,70 @@ var AlterSDKError = class extends Error {
72
78
  return this.message;
73
79
  }
74
80
  };
75
- var TokenRetrievalError = class extends AlterSDKError {
81
+ var BackendError = class extends AlterSDKError {
76
82
  constructor(message, details) {
77
83
  super(message, details);
78
- this.name = "TokenRetrievalError";
84
+ this.name = "BackendError";
79
85
  }
80
86
  };
81
- var PolicyViolationError = class extends TokenRetrievalError {
82
- policyError;
83
- constructor(message, policyError, details) {
87
+ var ReAuthRequiredError = class extends BackendError {
88
+ constructor(message, details) {
84
89
  super(message, details);
85
- this.name = "PolicyViolationError";
86
- this.policyError = policyError;
90
+ this.name = "ReAuthRequiredError";
87
91
  }
88
92
  };
89
- var ConnectionNotFoundError = class extends TokenRetrievalError {
93
+ var ConnectionExpiredError = class extends ReAuthRequiredError {
90
94
  constructor(message, details) {
91
95
  super(message, details);
92
- this.name = "ConnectionNotFoundError";
96
+ this.name = "ConnectionExpiredError";
93
97
  }
94
98
  };
95
- var TokenExpiredError = class extends TokenRetrievalError {
99
+ var ConnectionRevokedError = class extends ReAuthRequiredError {
96
100
  connectionId;
97
101
  constructor(message, connectionId, details) {
98
102
  super(message, details);
99
- this.name = "TokenExpiredError";
103
+ this.name = "ConnectionRevokedError";
100
104
  this.connectionId = connectionId;
101
105
  }
102
106
  };
107
+ var ConnectionDeletedError = class extends ReAuthRequiredError {
108
+ constructor(message, details) {
109
+ super(message, details);
110
+ this.name = "ConnectionDeletedError";
111
+ }
112
+ };
113
+ var ConnectionNotFoundError = class extends BackendError {
114
+ constructor(message, details) {
115
+ super(message, details);
116
+ this.name = "ConnectionNotFoundError";
117
+ }
118
+ };
119
+ var PolicyViolationError = class extends BackendError {
120
+ policyError;
121
+ constructor(message, policyError, details) {
122
+ super(message, details);
123
+ this.name = "PolicyViolationError";
124
+ this.policyError = policyError;
125
+ }
126
+ };
103
127
  var ConnectFlowError = class extends AlterSDKError {
104
128
  constructor(message, details) {
105
129
  super(message, details);
106
130
  this.name = "ConnectFlowError";
107
131
  }
108
132
  };
133
+ var ConnectDeniedError = class extends ConnectFlowError {
134
+ constructor(message, details) {
135
+ super(message, details);
136
+ this.name = "ConnectDeniedError";
137
+ }
138
+ };
139
+ var ConnectConfigError = class extends ConnectFlowError {
140
+ constructor(message, details) {
141
+ super(message, details);
142
+ this.name = "ConnectConfigError";
143
+ }
144
+ };
109
145
  var ConnectTimeoutError = class extends ConnectFlowError {
110
146
  constructor(message, details) {
111
147
  super(message, details);
@@ -122,6 +158,16 @@ var ProviderAPIError = class extends AlterSDKError {
122
158
  this.responseBody = responseBody;
123
159
  }
124
160
  };
161
+ var ScopeReauthRequiredError = class extends ProviderAPIError {
162
+ connectionId;
163
+ providerId;
164
+ constructor(message, connectionId, providerId, statusCode, responseBody, details) {
165
+ super(message, statusCode, responseBody, details);
166
+ this.name = "ScopeReauthRequiredError";
167
+ this.connectionId = connectionId;
168
+ this.providerId = providerId;
169
+ }
170
+ };
125
171
  var NetworkError = class extends AlterSDKError {
126
172
  constructor(message, details) {
127
173
  super(message, details);
@@ -161,6 +207,8 @@ var TokenResponse = class _TokenResponse {
161
207
  injectionFormat;
162
208
  /** Extra credentials for multi-part auth (e.g. AWS SigV4 secret_key, region) */
163
209
  additionalCredentials;
210
+ /** Additional injection rules for multi-header or query param auth */
211
+ additionalInjections;
164
212
  constructor(data) {
165
213
  this.tokenType = data.token_type ?? "Bearer";
166
214
  this.expiresIn = data.expires_in ?? null;
@@ -176,6 +224,7 @@ var TokenResponse = class _TokenResponse {
176
224
  } else {
177
225
  this.additionalCredentials = null;
178
226
  }
227
+ this.additionalInjections = data.additional_injections ?? null;
179
228
  Object.freeze(this);
180
229
  }
181
230
  /**
@@ -221,7 +270,8 @@ var TokenResponse = class _TokenResponse {
221
270
  expires_in: this.expiresIn,
222
271
  expires_at: this.expiresAt?.toISOString() ?? null,
223
272
  scopes: this.scopes,
224
- connection_id: this.connectionId
273
+ connection_id: this.connectionId,
274
+ provider_id: this.providerId
225
275
  };
226
276
  }
227
277
  /**
@@ -238,22 +288,24 @@ var TokenResponse = class _TokenResponse {
238
288
  }
239
289
  };
240
290
  var ConnectionInfo = class {
241
- id;
291
+ connectionId;
242
292
  providerId;
243
293
  scopes;
244
294
  accountIdentifier;
245
295
  accountDisplayName;
246
296
  status;
297
+ scopeMismatch;
247
298
  expiresAt;
248
299
  createdAt;
249
300
  lastUsedAt;
250
301
  constructor(data) {
251
- this.id = data.id;
302
+ this.connectionId = data.connection_id;
252
303
  this.providerId = data.provider_id;
253
304
  this.scopes = data.scopes ?? [];
254
305
  this.accountIdentifier = data.account_identifier ?? null;
255
306
  this.accountDisplayName = data.account_display_name ?? null;
256
307
  this.status = data.status;
308
+ this.scopeMismatch = data.scope_mismatch ?? false;
257
309
  this.expiresAt = data.expires_at ?? null;
258
310
  this.createdAt = data.created_at;
259
311
  this.lastUsedAt = data.last_used_at ?? null;
@@ -261,19 +313,20 @@ var ConnectionInfo = class {
261
313
  }
262
314
  toJSON() {
263
315
  return {
264
- id: this.id,
316
+ connection_id: this.connectionId,
265
317
  provider_id: this.providerId,
266
318
  scopes: this.scopes,
267
319
  account_identifier: this.accountIdentifier,
268
320
  account_display_name: this.accountDisplayName,
269
321
  status: this.status,
322
+ scope_mismatch: this.scopeMismatch,
270
323
  expires_at: this.expiresAt,
271
324
  created_at: this.createdAt,
272
325
  last_used_at: this.lastUsedAt
273
326
  };
274
327
  }
275
328
  toString() {
276
- return `ConnectionInfo(id=${this.id}, provider=${this.providerId}, status=${this.status})`;
329
+ return `ConnectionInfo(connection_id=${this.connectionId}, provider=${this.providerId}, status=${this.status})`;
277
330
  }
278
331
  };
279
332
  var ConnectSession = class {
@@ -320,11 +373,23 @@ var ConnectResult = class {
320
373
  providerId;
321
374
  accountIdentifier;
322
375
  scopes;
376
+ connectionPolicy;
323
377
  constructor(data) {
324
378
  this.connectionId = data.connection_id;
325
379
  this.providerId = data.provider_id;
326
380
  this.accountIdentifier = data.account_identifier ?? null;
327
381
  this.scopes = data.scopes ?? [];
382
+ const rawPolicy = data.connection_policy;
383
+ if (rawPolicy) {
384
+ const raw = rawPolicy;
385
+ this.connectionPolicy = Object.freeze({
386
+ expiresAt: raw["expires_at"] !== void 0 ? raw["expires_at"] : rawPolicy.expiresAt ?? null,
387
+ createdBy: raw["created_by"] !== void 0 ? raw["created_by"] : rawPolicy.createdBy ?? null,
388
+ createdAt: raw["created_at"] !== void 0 ? raw["created_at"] : rawPolicy.createdAt ?? null
389
+ });
390
+ } else {
391
+ this.connectionPolicy = null;
392
+ }
328
393
  Object.freeze(this);
329
394
  }
330
395
  toJSON() {
@@ -332,7 +397,12 @@ var ConnectResult = class {
332
397
  connection_id: this.connectionId,
333
398
  provider_id: this.providerId,
334
399
  account_identifier: this.accountIdentifier,
335
- scopes: this.scopes
400
+ scopes: this.scopes,
401
+ connection_policy: this.connectionPolicy ? {
402
+ expires_at: this.connectionPolicy.expiresAt ?? null,
403
+ created_by: this.connectionPolicy.createdBy ?? null,
404
+ created_at: this.connectionPolicy.createdAt ?? null
405
+ } : null
336
406
  };
337
407
  }
338
408
  toString() {
@@ -346,7 +416,8 @@ var SENSITIVE_HEADERS = /* @__PURE__ */ new Set([
346
416
  "x-api-key",
347
417
  "x-auth-token",
348
418
  "x-amz-date",
349
- "x-amz-content-sha256"
419
+ "x-amz-content-sha256",
420
+ "x-amz-security-token"
350
421
  ]);
351
422
  var APICallAuditLog = class {
352
423
  connectionId;
@@ -425,6 +496,7 @@ var import_node_crypto = require("crypto");
425
496
  var ALGORITHM = "AWS4-HMAC-SHA256";
426
497
  var AWS_HOST_RE = /^(?<service>[a-z0-9-]+)\.(?<region>[a-z]{2}(?:-[a-z0-9]+)+-\d+)\.amazonaws\.com$/;
427
498
  var S3_VIRTUAL_HOST_RE = /^[^.]+\.s3\.(?<region>[a-z]{2}(?:-[a-z0-9]+)+-\d+)\.amazonaws\.com$/;
499
+ var VPCE_HOST_RE = /^vpce-[a-z0-9-]+\.(?<service>[a-z0-9-]+)\.(?<region>[a-z]{2}(?:-[a-z0-9]+)+-\d+)\.vpce\.amazonaws\.com$/;
428
500
  function hmacSha256(key, message) {
429
501
  return (0, import_node_crypto.createHmac)("sha256", key).update(message, "utf8").digest();
430
502
  }
@@ -447,6 +519,10 @@ function detectServiceAndRegion(hostname) {
447
519
  if (s3m?.groups) {
448
520
  return { service: "s3", region: s3m.groups.region };
449
521
  }
522
+ const vpcem = VPCE_HOST_RE.exec(lower);
523
+ if (vpcem?.groups) {
524
+ return { service: vpcem.groups.service, region: vpcem.groups.region };
525
+ }
450
526
  return { service: null, region: null };
451
527
  }
452
528
  function deriveSigningKey(secretKey, dateStamp, region, service) {
@@ -481,18 +557,21 @@ function canonicalQueryString(query) {
481
557
  ]);
482
558
  }
483
559
  }
484
- sorted.sort((a, b) => {
560
+ const sigv4Encode = (s) => encodeURIComponent(s).replace(
561
+ /[!'()*]/g,
562
+ (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
563
+ );
564
+ const encoded = sorted.map(
565
+ ([k, v]) => [sigv4Encode(k), sigv4Encode(v)]
566
+ );
567
+ encoded.sort((a, b) => {
485
568
  if (a[0] < b[0]) return -1;
486
569
  if (a[0] > b[0]) return 1;
487
570
  if (a[1] < b[1]) return -1;
488
571
  if (a[1] > b[1]) return 1;
489
572
  return 0;
490
573
  });
491
- const sigv4Encode = (s) => encodeURIComponent(s).replace(
492
- /[!'()*]/g,
493
- (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
494
- );
495
- return sorted.map(([k, v]) => `${sigv4Encode(k)}=${sigv4Encode(v)}`).join("&");
574
+ return encoded.map(([k, v]) => `${k}=${v}`).join("&");
496
575
  }
497
576
  function canonicalHeadersAndSigned(headers) {
498
577
  const canonical = {};
@@ -511,11 +590,9 @@ function signAwsRequest(opts) {
511
590
  const parsed = new URL(opts.url);
512
591
  const hostname = parsed.hostname;
513
592
  let { region, service } = opts;
514
- if (region == null || service == null) {
515
- const detected = detectServiceAndRegion(hostname);
516
- if (region == null) region = detected.region;
517
- if (service == null) service = detected.service;
518
- }
593
+ const detected = detectServiceAndRegion(hostname);
594
+ if (detected.region != null) region = detected.region;
595
+ if (detected.service != null) service = detected.service;
519
596
  if (!region) {
520
597
  throw new Error(
521
598
  `Cannot determine AWS region from URL '${opts.url}'. Pass region explicitly via additional_credentials.`
@@ -598,10 +675,11 @@ function _extractAdditionalCredentials(token) {
598
675
  return _additionalCredsStore.get(token);
599
676
  }
600
677
  var _fetch;
601
- var SDK_VERSION = "0.4.0";
678
+ var SDK_VERSION = "0.6.0";
602
679
  var SDK_USER_AGENT = `alter-sdk-node/${SDK_VERSION}`;
603
680
  var HTTP_FORBIDDEN = 403;
604
681
  var HTTP_NOT_FOUND = 404;
682
+ var HTTP_GONE = 410;
605
683
  var HTTP_BAD_REQUEST = 400;
606
684
  var HTTP_UNAUTHORIZED = 401;
607
685
  var HTTP_BAD_GATEWAY = 502;
@@ -657,6 +735,9 @@ var HttpClient = class {
657
735
  };
658
736
  if (options?.body !== void 0) {
659
737
  init.body = options.body;
738
+ if (!mergedHeaders["Content-Type"]) {
739
+ mergedHeaders["Content-Type"] = "application/json";
740
+ }
660
741
  } else if (options?.json !== void 0) {
661
742
  init.body = JSON.stringify(options.json);
662
743
  mergedHeaders["Content-Type"] = "application/json";
@@ -693,6 +774,8 @@ var AlterVault = class _AlterVault {
693
774
  #closed = false;
694
775
  /** Pending audit log promises (fire-and-forget) */
695
776
  #auditPromises = /* @__PURE__ */ new Set();
777
+ /** JWT identity resolution: callable that returns user token */
778
+ #userTokenGetter = null;
696
779
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
697
780
  // Public readonly properties (frozen by Object.freeze)
698
781
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -728,6 +811,7 @@ var AlterVault = class _AlterVault {
728
811
  this.#actorName = options.actorName;
729
812
  this.#actorVersion = options.actorVersion;
730
813
  this.#clientType = options.clientType;
814
+ this.#userTokenGetter = options.userTokenGetter ?? null;
731
815
  this.#framework = options.framework;
732
816
  if (!_fetch) {
733
817
  _fetch = globalThis.fetch;
@@ -902,6 +986,24 @@ ${contentHash}`;
902
986
  }
903
987
  return false;
904
988
  }
989
+ /**
990
+ * Resolve a value_source to the actual value for injection.
991
+ *
992
+ * @param valueSource - "token" or "additional_credentials.<field>"
993
+ * @param accessToken - The main credential value
994
+ * @param additionalCreds - Additional credentials from vault
995
+ * @returns The resolved value, or null if not available
996
+ */
997
+ static #resolveInjectionValue(valueSource, accessToken, additionalCreds) {
998
+ if (valueSource === "token") {
999
+ return accessToken;
1000
+ }
1001
+ if (valueSource.startsWith("additional_credentials.")) {
1002
+ const field = valueSource.slice("additional_credentials.".length);
1003
+ return additionalCreds?.[field] ?? null;
1004
+ }
1005
+ return null;
1006
+ }
905
1007
  static async #safeParseJson(response) {
906
1008
  try {
907
1009
  return await response.clone().json();
@@ -923,12 +1025,25 @@ ${contentHash}`;
923
1025
  }
924
1026
  if (response.status === HTTP_FORBIDDEN) {
925
1027
  const errorData = await _AlterVault.#safeParseJson(response);
1028
+ if (errorData.error === "connection_expired") {
1029
+ throw new ConnectionExpiredError(
1030
+ errorData.message ?? "Connection expired per TTL policy",
1031
+ errorData.details
1032
+ );
1033
+ }
926
1034
  throw new PolicyViolationError(
927
1035
  errorData.message ?? "Access denied by policy",
928
1036
  errorData.error,
929
1037
  errorData.details
930
1038
  );
931
1039
  }
1040
+ if (response.status === HTTP_GONE) {
1041
+ const errorData = await _AlterVault.#safeParseJson(response);
1042
+ throw new ConnectionDeletedError(
1043
+ errorData.message ?? "Connection has been deleted. A new connection_id will be issued on re-authorization.",
1044
+ errorData
1045
+ );
1046
+ }
932
1047
  if (response.status === HTTP_NOT_FOUND) {
933
1048
  const errorData = await _AlterVault.#safeParseJson(response);
934
1049
  throw new ConnectionNotFoundError(
@@ -938,35 +1053,35 @@ ${contentHash}`;
938
1053
  }
939
1054
  if (response.status === HTTP_BAD_REQUEST || response.status === HTTP_BAD_GATEWAY) {
940
1055
  const errorData = await _AlterVault.#safeParseJson(response);
941
- if (JSON.stringify(errorData).toLowerCase().includes("token_expired")) {
942
- throw new TokenExpiredError(
943
- errorData.message ?? "Token expired and refresh failed",
1056
+ if (errorData.error === "connection_revoked") {
1057
+ throw new ConnectionRevokedError(
1058
+ errorData.message ?? "Connection has been revoked. User must re-authorize.",
944
1059
  errorData.connection_id,
945
1060
  errorData
946
1061
  );
947
1062
  }
948
- throw new TokenRetrievalError(
1063
+ throw new BackendError(
949
1064
  errorData.message ?? `Backend error ${response.status}`,
950
1065
  errorData
951
1066
  );
952
1067
  }
953
1068
  if (response.status === HTTP_UNAUTHORIZED) {
954
1069
  const errorData = await _AlterVault.#safeParseJson(response);
955
- throw new TokenRetrievalError(
1070
+ throw new BackendError(
956
1071
  errorData.message ?? "Unauthorized \u2014 check your API key",
957
1072
  errorData
958
1073
  );
959
1074
  }
960
1075
  if (response.status === HTTP_INTERNAL_SERVER_ERROR || response.status === HTTP_SERVICE_UNAVAILABLE) {
961
1076
  const errorData = await _AlterVault.#safeParseJson(response);
962
- throw new TokenRetrievalError(
1077
+ throw new BackendError(
963
1078
  errorData.message ?? `Backend unavailable (HTTP ${response.status})`,
964
1079
  errorData
965
1080
  );
966
1081
  }
967
1082
  if (response.status >= HTTP_CLIENT_ERROR_START) {
968
1083
  const errorData = await _AlterVault.#safeParseJson(response);
969
- throw new TokenRetrievalError(
1084
+ throw new BackendError(
970
1085
  errorData.message ?? `Unexpected backend error (HTTP ${response.status})`,
971
1086
  errorData
972
1087
  );
@@ -978,24 +1093,52 @@ ${contentHash}`;
978
1093
  * This is a private method. Tokens are NEVER exposed to developers.
979
1094
  * Use request() instead, which handles tokens internally.
980
1095
  */
981
- async #getToken(connectionId, reason, requestMetadata, runId, threadId, toolCallId) {
1096
+ async #getUserToken() {
1097
+ if (!this.#userTokenGetter) {
1098
+ throw new AlterSDKError(
1099
+ "userTokenGetter is required for provider-based resolution. Pass userTokenGetter to AlterVault constructor."
1100
+ );
1101
+ }
1102
+ const result = this.#userTokenGetter();
1103
+ const token = result instanceof Promise ? await result : result;
1104
+ if (!token || typeof token !== "string") {
1105
+ throw new AlterSDKError("userTokenGetter must return a non-empty string");
1106
+ }
1107
+ return token;
1108
+ }
1109
+ async #getToken(connectionId, reason, requestMetadata, runId, threadId, toolCallId, provider, account) {
982
1110
  const actorHeaders = this.#getActorRequestHeaders(
983
1111
  runId,
984
1112
  threadId,
985
1113
  toolCallId
986
1114
  );
987
1115
  let response;
988
- const tokenBody = {
989
- connection_id: connectionId,
990
- reason: reason ?? null,
991
- request: requestMetadata ?? null
992
- };
1116
+ let tokenBody;
1117
+ if (provider) {
1118
+ const userToken = await this.#getUserToken();
1119
+ tokenBody = {
1120
+ provider_id: provider,
1121
+ user_token: userToken,
1122
+ reason: reason ?? null,
1123
+ request: requestMetadata ?? null
1124
+ };
1125
+ if (account) {
1126
+ tokenBody.account = account;
1127
+ }
1128
+ } else {
1129
+ tokenBody = {
1130
+ connection_id: connectionId,
1131
+ reason: reason ?? null,
1132
+ request: requestMetadata ?? null
1133
+ };
1134
+ }
993
1135
  const tokenPath = "/sdk/token";
994
- const hmacHeaders = this.#computeHmacHeaders("POST", tokenPath, JSON.stringify(tokenBody));
1136
+ const tokenBodyStr = JSON.stringify(tokenBody);
1137
+ const hmacHeaders = this.#computeHmacHeaders("POST", tokenPath, tokenBodyStr);
995
1138
  try {
996
1139
  response = await this.#alterClient.post(tokenPath, {
997
- json: tokenBody,
998
- headers: { ...actorHeaders, ...hmacHeaders }
1140
+ body: tokenBodyStr,
1141
+ headers: { ...actorHeaders, ...hmacHeaders, "Content-Type": "application/json" }
999
1142
  });
1000
1143
  } catch (error) {
1001
1144
  if (_AlterVault.#isTimeoutOrAbortError(error)) {
@@ -1010,7 +1153,7 @@ ${contentHash}`;
1010
1153
  { base_url: this.baseUrl }
1011
1154
  );
1012
1155
  }
1013
- throw new TokenRetrievalError(
1156
+ throw new BackendError(
1014
1157
  `Failed to retrieve token: ${error instanceof Error ? error.message : String(error)}`,
1015
1158
  { connection_id: connectionId, error: String(error) }
1016
1159
  );
@@ -1019,15 +1162,16 @@ ${contentHash}`;
1019
1162
  await this.#handleErrorResponse(response);
1020
1163
  const tokenData = await response.json();
1021
1164
  const typedData = tokenData;
1165
+ const scopeMismatch = typedData.scope_mismatch ?? false;
1022
1166
  const tokenResponse = new TokenResponse(typedData);
1023
1167
  if (!/^[A-Za-z][A-Za-z0-9-]*$/.test(tokenResponse.injectionHeader)) {
1024
- throw new TokenRetrievalError(
1168
+ throw new BackendError(
1025
1169
  `Backend returned invalid injection_header: ${tokenResponse.injectionHeader}`,
1026
1170
  { connectionId: String(connectionId) }
1027
1171
  );
1028
1172
  }
1029
1173
  if (/[\r\n\x00]/.test(tokenResponse.injectionFormat)) {
1030
- throw new TokenRetrievalError(
1174
+ throw new BackendError(
1031
1175
  `Backend returned invalid injection_format (contains control characters)`,
1032
1176
  { connectionId: String(connectionId) }
1033
1177
  );
@@ -1036,7 +1180,7 @@ ${contentHash}`;
1036
1180
  if (typedData.additional_credentials) {
1037
1181
  _storeAdditionalCredentials(tokenResponse, typedData.additional_credentials);
1038
1182
  }
1039
- return tokenResponse;
1183
+ return { tokenResponse, scopeMismatch };
1040
1184
  }
1041
1185
  /**
1042
1186
  * Log an API call to the backend audit endpoint (INTERNAL).
@@ -1066,10 +1210,11 @@ ${contentHash}`;
1066
1210
  const actorHeaders = this.#getActorRequestHeaders(params.runId);
1067
1211
  const auditPath = "/sdk/oauth/audit/api-call";
1068
1212
  const auditBody = sanitized;
1069
- const auditHmac = this.#computeHmacHeaders("POST", auditPath, JSON.stringify(auditBody));
1213
+ const auditBodyStr = JSON.stringify(auditBody);
1214
+ const auditHmac = this.#computeHmacHeaders("POST", auditPath, auditBodyStr);
1070
1215
  const response = await this.#alterClient.post(auditPath, {
1071
- json: auditBody,
1072
- headers: { ...actorHeaders, ...auditHmac }
1216
+ body: auditBodyStr,
1217
+ headers: { ...actorHeaders, ...auditHmac, "Content-Type": "application/json" }
1073
1218
  });
1074
1219
  this.#cacheActorIdFromResponse(response);
1075
1220
  if (!response.ok) {
@@ -1141,12 +1286,22 @@ ${contentHash}`;
1141
1286
  "SDK instance has been closed. Create a new AlterVault instance to make requests."
1142
1287
  );
1143
1288
  }
1289
+ const provider = options?.provider;
1290
+ const account = options?.account;
1291
+ if (!connectionId && !provider) {
1292
+ throw new AlterSDKError("Provide connectionId or options.provider");
1293
+ }
1294
+ if (connectionId && provider) {
1295
+ throw new AlterSDKError("Cannot provide both connectionId and options.provider");
1296
+ }
1297
+ const effectiveConnectionId = connectionId ?? null;
1298
+ let currentUrl = url;
1144
1299
  const runId = options?.runId ?? (0, import_node_crypto2.randomUUID)();
1145
1300
  const methodStr = String(method).toUpperCase();
1146
- const urlLower = url.toLowerCase();
1301
+ const urlLower = currentUrl.toLowerCase();
1147
1302
  if (!ALLOWED_URL_SCHEMES.some((scheme) => urlLower.startsWith(scheme))) {
1148
1303
  throw new AlterSDKError(
1149
- `URL must start with https:// or http://, got: ${url.slice(0, 50)}`
1304
+ `URL must start with https:// or http://, got: ${currentUrl.slice(0, 50)}`
1150
1305
  );
1151
1306
  }
1152
1307
  if (options?.pathParams && Object.keys(options.pathParams).length > 0) {
@@ -1155,7 +1310,7 @@ ${contentHash}`;
1155
1310
  encodedParams[key] = encodeURIComponent(String(value));
1156
1311
  }
1157
1312
  try {
1158
- let resolvedUrl = url;
1313
+ let resolvedUrl = currentUrl;
1159
1314
  for (const [key, value] of Object.entries(encodedParams)) {
1160
1315
  const placeholder = `{${key}}`;
1161
1316
  if (!resolvedUrl.includes(placeholder)) {
@@ -1166,26 +1321,28 @@ ${contentHash}`;
1166
1321
  const remaining = resolvedUrl.match(/\{(\w+)\}/);
1167
1322
  if (remaining) {
1168
1323
  throw new AlterSDKError(
1169
- `Invalid URL template or missing path_params: '${remaining[1]}'. URL: ${url}, path_params: ${JSON.stringify(options.pathParams)}`
1324
+ `Invalid URL template or missing path_params: '${remaining[1]}'. URL: ${currentUrl}, path_params: ${JSON.stringify(options.pathParams)}`
1170
1325
  );
1171
1326
  }
1172
- url = resolvedUrl;
1327
+ currentUrl = resolvedUrl;
1173
1328
  } catch (error) {
1174
1329
  if (error instanceof AlterSDKError) {
1175
1330
  throw error;
1176
1331
  }
1177
1332
  throw new AlterSDKError(
1178
- `Invalid URL template or missing path_params: ${error instanceof Error ? error.message : String(error)}. URL: ${url}, path_params: ${JSON.stringify(options.pathParams)}`
1333
+ `Invalid URL template or missing path_params: ${error instanceof Error ? error.message : String(error)}. URL: ${currentUrl}, path_params: ${JSON.stringify(options.pathParams)}`
1179
1334
  );
1180
1335
  }
1181
1336
  }
1182
- const tokenResponse = await this.#getToken(
1183
- connectionId,
1337
+ const { tokenResponse, scopeMismatch } = await this.#getToken(
1338
+ effectiveConnectionId,
1184
1339
  options?.reason,
1185
- { method: methodStr, url },
1340
+ { method: methodStr, url: currentUrl },
1186
1341
  runId,
1187
1342
  options?.threadId,
1188
- options?.toolCallId
1343
+ options?.toolCallId,
1344
+ provider,
1345
+ account
1189
1346
  );
1190
1347
  const requestHeaders = options?.extraHeaders ? { ...options.extraHeaders } : {};
1191
1348
  const accessToken = _extractAccessToken(tokenResponse);
@@ -1202,14 +1359,14 @@ ${contentHash}`;
1202
1359
  }
1203
1360
  }
1204
1361
  if (!additionalCreds.secret_key) {
1205
- throw new TokenRetrievalError(
1362
+ throw new BackendError(
1206
1363
  "AWS SigV4 credential is missing secret_key in additional_credentials. Re-store the credential with both Access Key ID and Secret Access Key.",
1207
- { connection_id: connectionId }
1364
+ { connection_id: effectiveConnectionId }
1208
1365
  );
1209
1366
  }
1210
1367
  const awsHeaders = signAwsRequest({
1211
1368
  method: methodStr,
1212
- url,
1369
+ url: currentUrl,
1213
1370
  headers: requestHeaders,
1214
1371
  body: sigv4BodyStr,
1215
1372
  accessKeyId,
@@ -1228,6 +1385,25 @@ ${contentHash}`;
1228
1385
  }
1229
1386
  requestHeaders[tokenResponse.injectionHeader] = tokenResponse.injectionFormat.replace("{token}", accessToken);
1230
1387
  }
1388
+ const auditUrl = currentUrl;
1389
+ if (tokenResponse.additionalInjections && !isSigV4) {
1390
+ for (const rule of tokenResponse.additionalInjections) {
1391
+ const value = _AlterVault.#resolveInjectionValue(
1392
+ rule.value_source,
1393
+ accessToken,
1394
+ additionalCreds
1395
+ );
1396
+ if (!value) continue;
1397
+ if (!/^[A-Za-z][A-Za-z0-9\-_]*$/.test(rule.key)) continue;
1398
+ if (rule.target === "header") {
1399
+ requestHeaders[rule.key] = value;
1400
+ } else if (rule.target === "query_param") {
1401
+ const urlObj = new URL(currentUrl);
1402
+ urlObj.searchParams.set(rule.key, value);
1403
+ currentUrl = urlObj.toString();
1404
+ }
1405
+ }
1406
+ }
1231
1407
  if (!requestHeaders["User-Agent"]) {
1232
1408
  requestHeaders["User-Agent"] = SDK_USER_AGENT;
1233
1409
  }
@@ -1235,13 +1411,13 @@ ${contentHash}`;
1235
1411
  let response;
1236
1412
  try {
1237
1413
  if (isSigV4 && sigv4BodyStr != null) {
1238
- response = await this.#providerClient.request(methodStr, url, {
1414
+ response = await this.#providerClient.request(methodStr, currentUrl, {
1239
1415
  body: sigv4BodyStr,
1240
1416
  headers: requestHeaders,
1241
1417
  params: options?.queryParams
1242
1418
  });
1243
1419
  } else {
1244
- response = await this.#providerClient.request(methodStr, url, {
1420
+ response = await this.#providerClient.request(methodStr, currentUrl, {
1245
1421
  json: options?.json,
1246
1422
  headers: requestHeaders,
1247
1423
  params: options?.queryParams
@@ -1252,18 +1428,18 @@ ${contentHash}`;
1252
1428
  throw new TimeoutError(
1253
1429
  `Provider API request timed out: ${error instanceof Error ? error.message : String(error)}`,
1254
1430
  {
1255
- connection_id: connectionId,
1431
+ connection_id: effectiveConnectionId,
1256
1432
  method: methodStr,
1257
- url
1433
+ url: currentUrl
1258
1434
  }
1259
1435
  );
1260
1436
  }
1261
1437
  throw new NetworkError(
1262
1438
  `Failed to call provider API: ${error instanceof Error ? error.message : String(error)}`,
1263
1439
  {
1264
- connection_id: connectionId,
1440
+ connection_id: effectiveConnectionId,
1265
1441
  method: methodStr,
1266
- url,
1442
+ url: currentUrl,
1267
1443
  error: String(error)
1268
1444
  }
1269
1445
  );
@@ -1271,6 +1447,13 @@ ${contentHash}`;
1271
1447
  const latencyMs = Date.now() - startTime;
1272
1448
  const sigv4Sensitive = /* @__PURE__ */ new Set(["authorization", "x-amz-date", "x-amz-content-sha256"]);
1273
1449
  const stripHeaders = isSigV4 ? sigv4Sensitive : /* @__PURE__ */ new Set([injectionHeaderLower]);
1450
+ if (tokenResponse.additionalInjections && !isSigV4) {
1451
+ for (const rule of tokenResponse.additionalInjections) {
1452
+ if (rule.target === "header") {
1453
+ stripHeaders.add(rule.key.toLowerCase());
1454
+ }
1455
+ }
1456
+ }
1274
1457
  const auditHeaders = {};
1275
1458
  for (const [key, value] of Object.entries(requestHeaders)) {
1276
1459
  if (!stripHeaders.has(key.toLowerCase())) {
@@ -1284,9 +1467,9 @@ ${contentHash}`;
1284
1467
  });
1285
1468
  this.#scheduleAuditLog({
1286
1469
  connectionId: tokenResponse.connectionId,
1287
- providerId: tokenResponse.providerId || connectionId,
1470
+ providerId: tokenResponse.providerId || effectiveConnectionId || "",
1288
1471
  method: methodStr,
1289
- url,
1472
+ url: auditUrl,
1290
1473
  requestHeaders: auditHeaders,
1291
1474
  requestBody: options?.json ?? null,
1292
1475
  responseStatus: response.status,
@@ -1299,14 +1482,29 @@ ${contentHash}`;
1299
1482
  toolCallId: options?.toolCallId ?? null
1300
1483
  });
1301
1484
  if (response.status >= HTTP_CLIENT_ERROR_START) {
1485
+ if (response.status === HTTP_FORBIDDEN && scopeMismatch) {
1486
+ throw new ScopeReauthRequiredError(
1487
+ "Provider API returned 403 and the connection's scopes don't match the provider config. The user needs to re-authorize to grant updated permissions.",
1488
+ tokenResponse.connectionId,
1489
+ tokenResponse.providerId,
1490
+ response.status,
1491
+ responseBody,
1492
+ {
1493
+ connection_id: tokenResponse.connectionId,
1494
+ provider_id: tokenResponse.providerId,
1495
+ method: methodStr,
1496
+ url: currentUrl
1497
+ }
1498
+ );
1499
+ }
1302
1500
  throw new ProviderAPIError(
1303
1501
  `Provider API returned error ${response.status}`,
1304
1502
  response.status,
1305
1503
  responseBody,
1306
1504
  {
1307
- connection_id: connectionId,
1505
+ connection_id: effectiveConnectionId,
1308
1506
  method: methodStr,
1309
- url
1507
+ url: currentUrl
1310
1508
  }
1311
1509
  );
1312
1510
  }
@@ -1331,12 +1529,23 @@ ${contentHash}`;
1331
1529
  limit: options?.limit ?? 100,
1332
1530
  offset: options?.offset ?? 0
1333
1531
  };
1532
+ if (this.#userTokenGetter) {
1533
+ try {
1534
+ listBody.user_token = await this.#getUserToken();
1535
+ } catch (err) {
1536
+ console.warn(
1537
+ "user_token_getter failed in listConnections, falling back to un-scoped listing:",
1538
+ err instanceof Error ? err.message : String(err)
1539
+ );
1540
+ }
1541
+ }
1334
1542
  const listPath = "/sdk/oauth/connections/list";
1335
- const listHmac = this.#computeHmacHeaders("POST", listPath, JSON.stringify(listBody));
1543
+ const listBodyStr = JSON.stringify(listBody);
1544
+ const listHmac = this.#computeHmacHeaders("POST", listPath, listBodyStr);
1336
1545
  try {
1337
1546
  response = await this.#alterClient.post(listPath, {
1338
- json: listBody,
1339
- headers: { ...actorHeaders, ...listHmac }
1547
+ body: listBodyStr,
1548
+ headers: { ...actorHeaders, ...listHmac, "Content-Type": "application/json" }
1340
1549
  });
1341
1550
  } catch (error) {
1342
1551
  if (_AlterVault.#isTimeoutOrAbortError(error)) {
@@ -1382,24 +1591,37 @@ ${contentHash}`;
1382
1591
  "SDK instance has been closed. Create a new AlterVault instance to make requests."
1383
1592
  );
1384
1593
  }
1385
- if (!options.endUser?.id) {
1386
- throw new AlterSDKError("endUser.id is required");
1387
- }
1388
1594
  const actorHeaders = this.#getActorRequestHeaders();
1389
1595
  let response;
1390
1596
  const sessionBody = {
1391
- end_user: options.endUser,
1392
1597
  allowed_providers: options.allowedProviders ?? null,
1393
1598
  return_url: options.returnUrl ?? null,
1394
1599
  allowed_origin: options.allowedOrigin ?? null,
1395
1600
  metadata: options.metadata ?? null
1396
1601
  };
1602
+ if (options.connectionPolicy) {
1603
+ sessionBody.connection_policy = {
1604
+ max_ttl_seconds: options.connectionPolicy.maxTtlSeconds ?? null,
1605
+ default_ttl_seconds: options.connectionPolicy.defaultTtlSeconds ?? null
1606
+ };
1607
+ }
1608
+ if (this.#userTokenGetter) {
1609
+ try {
1610
+ sessionBody.user_token = await this.#getUserToken();
1611
+ } catch (err) {
1612
+ console.warn(
1613
+ "userTokenGetter failed in createConnectSession, session will not have identity tagging:",
1614
+ err instanceof Error ? err.message : String(err)
1615
+ );
1616
+ }
1617
+ }
1397
1618
  const sessionPath = "/sdk/oauth/connect/session";
1398
- const sessionHmac = this.#computeHmacHeaders("POST", sessionPath, JSON.stringify(sessionBody));
1619
+ const sessionBodyStr = JSON.stringify(sessionBody);
1620
+ const sessionHmac = this.#computeHmacHeaders("POST", sessionPath, sessionBodyStr);
1399
1621
  try {
1400
1622
  response = await this.#alterClient.post(sessionPath, {
1401
- json: sessionBody,
1402
- headers: { ...actorHeaders, ...sessionHmac }
1623
+ body: sessionBodyStr,
1624
+ headers: { ...actorHeaders, ...sessionHmac, "Content-Type": "application/json" }
1403
1625
  });
1404
1626
  } catch (error) {
1405
1627
  if (_AlterVault.#isTimeoutOrAbortError(error)) {
@@ -1430,7 +1652,7 @@ ${contentHash}`;
1430
1652
  * server-side applications. It creates a Connect session, opens the
1431
1653
  * browser, and polls until the user completes OAuth.
1432
1654
  *
1433
- * @param options - Connect options (endUser is required)
1655
+ * @param options - Connect options
1434
1656
  * @returns Array of ConnectResult objects (one per connected provider)
1435
1657
  * @throws ConnectTimeoutError if the user doesn't complete within timeout
1436
1658
  * @throws ConnectFlowError if the user denies or provider returns error
@@ -1446,8 +1668,8 @@ ${contentHash}`;
1446
1668
  const pollInterval = options.pollInterval ?? 2;
1447
1669
  const openBrowser = options.openBrowser ?? true;
1448
1670
  const session = await this.createConnectSession({
1449
- endUser: options.endUser,
1450
- allowedProviders: options.providers
1671
+ allowedProviders: options.providers,
1672
+ connectionPolicy: options.connectionPolicy
1451
1673
  });
1452
1674
  if (openBrowser) {
1453
1675
  try {
@@ -1484,18 +1706,28 @@ ${contentHash}`;
1484
1706
  connection_id: conn.connection_id ?? "",
1485
1707
  provider_id: conn.provider_id ?? "",
1486
1708
  account_identifier: conn.account_identifier ?? null,
1487
- scopes: conn.scopes ?? []
1709
+ scopes: conn.scopes ?? [],
1710
+ connection_policy: conn.connection_policy ?? null
1488
1711
  })
1489
1712
  );
1490
1713
  }
1491
1714
  if (pollStatus === "error") {
1492
1715
  const err = pollResult.error;
1493
- throw new ConnectFlowError(
1494
- err?.error_message ?? "OAuth flow failed",
1495
- {
1496
- error_code: err?.error_code ?? "unknown_error"
1497
- }
1498
- );
1716
+ const errorCode = err?.error_code ?? "unknown_error";
1717
+ const errorMessage = err?.error_message ?? "OAuth flow failed";
1718
+ const errorDetails = { error_code: errorCode };
1719
+ if (errorCode === "connect_denied") {
1720
+ throw new ConnectDeniedError(errorMessage, errorDetails);
1721
+ }
1722
+ if ([
1723
+ "connect_config_error",
1724
+ "invalid_redirect_uri",
1725
+ "invalid_client",
1726
+ "unauthorized_client"
1727
+ ].includes(errorCode)) {
1728
+ throw new ConnectConfigError(errorMessage, errorDetails);
1729
+ }
1730
+ throw new ConnectFlowError(errorMessage, errorDetails);
1499
1731
  }
1500
1732
  if (pollStatus === "expired") {
1501
1733
  throw new ConnectFlowError(
@@ -1517,16 +1749,17 @@ ${contentHash}`;
1517
1749
  const actorHeaders = this.#getActorRequestHeaders();
1518
1750
  const pollPath = "/sdk/oauth/connect/session/poll";
1519
1751
  const pollBody = { session_token: sessionToken };
1752
+ const pollBodyStr = JSON.stringify(pollBody);
1520
1753
  const pollHmac = this.#computeHmacHeaders(
1521
1754
  "POST",
1522
1755
  pollPath,
1523
- JSON.stringify(pollBody)
1756
+ pollBodyStr
1524
1757
  );
1525
1758
  let response;
1526
1759
  try {
1527
1760
  response = await this.#alterClient.post(pollPath, {
1528
- json: pollBody,
1529
- headers: { ...actorHeaders, ...pollHmac }
1761
+ body: pollBodyStr,
1762
+ headers: { ...actorHeaders, ...pollHmac, "Content-Type": "application/json" }
1530
1763
  });
1531
1764
  } catch (error) {
1532
1765
  if (_AlterVault.#isTimeoutOrAbortError(error)) {
@@ -1574,10 +1807,72 @@ Object.freeze(AlterVault.prototype);
1574
1807
 
1575
1808
  // src/providers/enums.ts
1576
1809
  var Provider = /* @__PURE__ */ ((Provider2) => {
1577
- Provider2["GOOGLE"] = "google";
1810
+ Provider2["ACUITY_SCHEDULING"] = "acuity-scheduling";
1811
+ Provider2["ADOBE"] = "adobe";
1812
+ Provider2["AIRCALL"] = "aircall";
1813
+ Provider2["AIRTABLE"] = "airtable";
1814
+ Provider2["APOLLO"] = "apollo";
1815
+ Provider2["ASANA"] = "asana";
1816
+ Provider2["ATLASSIAN"] = "atlassian";
1817
+ Provider2["ATTIO"] = "attio";
1818
+ Provider2["AUTODESK"] = "autodesk";
1819
+ Provider2["BASECAMP"] = "basecamp";
1820
+ Provider2["BITBUCKET"] = "bitbucket";
1821
+ Provider2["BITLY"] = "bitly";
1822
+ Provider2["BOX"] = "box";
1823
+ Provider2["BREX"] = "brex";
1824
+ Provider2["CALENDLY"] = "calendly";
1825
+ Provider2["CAL_COM"] = "cal-com";
1826
+ Provider2["CANVA"] = "canva";
1827
+ Provider2["CLICKUP"] = "clickup";
1828
+ Provider2["CLOSE"] = "close";
1829
+ Provider2["CONSTANT_CONTACT"] = "constant-contact";
1830
+ Provider2["CONTENTFUL"] = "contentful";
1831
+ Provider2["DEEL"] = "deel";
1832
+ Provider2["DIALPAD"] = "dialpad";
1833
+ Provider2["DIGITALOCEAN"] = "digitalocean";
1834
+ Provider2["DISCORD"] = "discord";
1835
+ Provider2["DOCUSIGN"] = "docusign";
1836
+ Provider2["DROPBOX"] = "dropbox";
1837
+ Provider2["EBAY"] = "ebay";
1838
+ Provider2["EVENTBRITE"] = "eventbrite";
1839
+ Provider2["FACEBOOK"] = "facebook";
1840
+ Provider2["FIGMA"] = "figma";
1578
1841
  Provider2["GITHUB"] = "github";
1579
- Provider2["SLACK"] = "slack";
1842
+ Provider2["GOOGLE"] = "google";
1843
+ Provider2["HUBSPOT"] = "hubspot";
1844
+ Provider2["INSTAGRAM"] = "instagram";
1845
+ Provider2["LINEAR"] = "linear";
1846
+ Provider2["LINKEDIN"] = "linkedin";
1847
+ Provider2["MAILCHIMP"] = "mailchimp";
1848
+ Provider2["MERCURY"] = "mercury";
1849
+ Provider2["MICROSOFT"] = "microsoft";
1850
+ Provider2["MIRO"] = "miro";
1851
+ Provider2["MONDAY"] = "monday";
1852
+ Provider2["NOTION"] = "notion";
1853
+ Provider2["OUTREACH"] = "outreach";
1854
+ Provider2["PAGERDUTY"] = "pagerduty";
1855
+ Provider2["PAYPAL"] = "paypal";
1856
+ Provider2["PINTEREST"] = "pinterest";
1857
+ Provider2["PIPEDRIVE"] = "pipedrive";
1858
+ Provider2["QUICKBOOKS"] = "quickbooks";
1859
+ Provider2["RAMP"] = "ramp";
1860
+ Provider2["REDDIT"] = "reddit";
1861
+ Provider2["RINGCENTRAL"] = "ringcentral";
1862
+ Provider2["SALESFORCE"] = "salesforce";
1580
1863
  Provider2["SENTRY"] = "sentry";
1864
+ Provider2["SLACK"] = "slack";
1865
+ Provider2["SNAPCHAT"] = "snapchat";
1866
+ Provider2["SPOTIFY"] = "spotify";
1867
+ Provider2["SQUARE"] = "square";
1868
+ Provider2["SQUARESPACE"] = "squarespace";
1869
+ Provider2["STRIPE"] = "stripe";
1870
+ Provider2["TIKTOK"] = "tiktok";
1871
+ Provider2["TODOIST"] = "todoist";
1872
+ Provider2["TWITTER"] = "twitter";
1873
+ Provider2["TYPEFORM"] = "typeform";
1874
+ Provider2["WEBEX"] = "webex";
1875
+ Provider2["WEBFLOW"] = "webflow";
1581
1876
  return Provider2;
1582
1877
  })(Provider || {});
1583
1878
  var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
@@ -1596,20 +1891,26 @@ var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
1596
1891
  ActorType,
1597
1892
  AlterSDKError,
1598
1893
  AlterVault,
1894
+ BackendError,
1895
+ ConnectConfigError,
1896
+ ConnectDeniedError,
1599
1897
  ConnectFlowError,
1600
1898
  ConnectResult,
1601
1899
  ConnectSession,
1602
1900
  ConnectTimeoutError,
1901
+ ConnectionDeletedError,
1902
+ ConnectionExpiredError,
1603
1903
  ConnectionInfo,
1604
1904
  ConnectionListResult,
1605
1905
  ConnectionNotFoundError,
1906
+ ConnectionRevokedError,
1606
1907
  HttpMethod,
1607
1908
  NetworkError,
1608
1909
  PolicyViolationError,
1609
1910
  Provider,
1610
1911
  ProviderAPIError,
1912
+ ReAuthRequiredError,
1913
+ ScopeReauthRequiredError,
1611
1914
  TimeoutError,
1612
- TokenExpiredError,
1613
- TokenResponse,
1614
- TokenRetrievalError
1915
+ TokenResponse
1615
1916
  });