@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.d.cts CHANGED
@@ -50,6 +50,12 @@ declare class TokenResponse {
50
50
  readonly injectionFormat: string;
51
51
  /** Extra credentials for multi-part auth (e.g. AWS SigV4 secret_key, region) */
52
52
  readonly additionalCredentials: Record<string, string> | null;
53
+ /** Additional injection rules for multi-header or query param auth */
54
+ readonly additionalInjections: ReadonlyArray<{
55
+ readonly target: string;
56
+ readonly key: string;
57
+ readonly value_source: string;
58
+ }> | null;
53
59
  constructor(data: {
54
60
  access_token: string;
55
61
  token_type?: string;
@@ -61,6 +67,11 @@ declare class TokenResponse {
61
67
  injection_header?: string;
62
68
  injection_format?: string;
63
69
  additional_credentials?: Record<string, string> | null;
70
+ additional_injections?: Array<{
71
+ target: string;
72
+ key: string;
73
+ value_source: string;
74
+ }> | null;
64
75
  });
65
76
  /**
66
77
  * Parse expires_at from ISO string.
@@ -98,22 +109,24 @@ declare class TokenResponse {
98
109
  * Returned by listConnections(). Contains metadata only — no tokens.
99
110
  */
100
111
  declare class ConnectionInfo {
101
- readonly id: string;
112
+ readonly connectionId: string;
102
113
  readonly providerId: string;
103
114
  readonly scopes: string[];
104
115
  readonly accountIdentifier: string | null;
105
116
  readonly accountDisplayName: string | null;
106
117
  readonly status: string;
118
+ readonly scopeMismatch: boolean;
107
119
  readonly expiresAt: string | null;
108
120
  readonly createdAt: string;
109
121
  readonly lastUsedAt: string | null;
110
122
  constructor(data: {
111
- id: string;
123
+ connection_id: string;
112
124
  provider_id: string;
113
125
  scopes?: string[];
114
126
  account_identifier?: string | null;
115
127
  account_display_name?: string | null;
116
128
  status: string;
129
+ scope_mismatch?: boolean;
117
130
  expires_at?: string | null;
118
131
  created_at: string;
119
132
  last_used_at?: string | null;
@@ -167,16 +180,29 @@ declare class ConnectionListResult {
167
180
  * Contains the connection metadata (no tokens — use request() with
168
181
  * the connectionId to make authenticated API calls).
169
182
  */
183
+ /**
184
+ * Per-connection policy (e.g., TTL expiry).
185
+ */
186
+ interface ConnectionPolicy {
187
+ /** Hard expiry timestamp (ISO 8601 UTC) */
188
+ readonly expiresAt?: string | null;
189
+ /** Who set the policy: 'developer' or 'end_user' */
190
+ readonly createdBy?: string | null;
191
+ /** When the policy was set (ISO 8601 UTC) */
192
+ readonly createdAt?: string | null;
193
+ }
170
194
  declare class ConnectResult {
171
195
  readonly connectionId: string;
172
196
  readonly providerId: string;
173
197
  readonly accountIdentifier: string | null;
174
198
  readonly scopes: string[];
199
+ readonly connectionPolicy: ConnectionPolicy | null;
175
200
  constructor(data: {
176
201
  connection_id: string;
177
202
  provider_id: string;
178
203
  account_identifier?: string | null;
179
204
  scopes?: string[];
205
+ connection_policy?: ConnectionPolicy | null;
180
206
  });
181
207
  toJSON(): Record<string, unknown>;
182
208
  toString(): string;
@@ -267,10 +293,72 @@ declare class APICallAuditLog {
267
293
  * ```
268
294
  */
269
295
  declare enum Provider {
270
- GOOGLE = "google",
296
+ ACUITY_SCHEDULING = "acuity-scheduling",
297
+ ADOBE = "adobe",
298
+ AIRCALL = "aircall",
299
+ AIRTABLE = "airtable",
300
+ APOLLO = "apollo",
301
+ ASANA = "asana",
302
+ ATLASSIAN = "atlassian",
303
+ ATTIO = "attio",
304
+ AUTODESK = "autodesk",
305
+ BASECAMP = "basecamp",
306
+ BITBUCKET = "bitbucket",
307
+ BITLY = "bitly",
308
+ BOX = "box",
309
+ BREX = "brex",
310
+ CALENDLY = "calendly",
311
+ CAL_COM = "cal-com",
312
+ CANVA = "canva",
313
+ CLICKUP = "clickup",
314
+ CLOSE = "close",
315
+ CONSTANT_CONTACT = "constant-contact",
316
+ CONTENTFUL = "contentful",
317
+ DEEL = "deel",
318
+ DIALPAD = "dialpad",
319
+ DIGITALOCEAN = "digitalocean",
320
+ DISCORD = "discord",
321
+ DOCUSIGN = "docusign",
322
+ DROPBOX = "dropbox",
323
+ EBAY = "ebay",
324
+ EVENTBRITE = "eventbrite",
325
+ FACEBOOK = "facebook",
326
+ FIGMA = "figma",
271
327
  GITHUB = "github",
328
+ GOOGLE = "google",
329
+ HUBSPOT = "hubspot",
330
+ INSTAGRAM = "instagram",
331
+ LINEAR = "linear",
332
+ LINKEDIN = "linkedin",
333
+ MAILCHIMP = "mailchimp",
334
+ MERCURY = "mercury",
335
+ MICROSOFT = "microsoft",
336
+ MIRO = "miro",
337
+ MONDAY = "monday",
338
+ NOTION = "notion",
339
+ OUTREACH = "outreach",
340
+ PAGERDUTY = "pagerduty",
341
+ PAYPAL = "paypal",
342
+ PINTEREST = "pinterest",
343
+ PIPEDRIVE = "pipedrive",
344
+ QUICKBOOKS = "quickbooks",
345
+ RAMP = "ramp",
346
+ REDDIT = "reddit",
347
+ RINGCENTRAL = "ringcentral",
348
+ SALESFORCE = "salesforce",
349
+ SENTRY = "sentry",
272
350
  SLACK = "slack",
273
- SENTRY = "sentry"
351
+ SNAPCHAT = "snapchat",
352
+ SPOTIFY = "spotify",
353
+ SQUARE = "square",
354
+ SQUARESPACE = "squarespace",
355
+ STRIPE = "stripe",
356
+ TIKTOK = "tiktok",
357
+ TODOIST = "todoist",
358
+ TWITTER = "twitter",
359
+ TYPEFORM = "typeform",
360
+ WEBEX = "webex",
361
+ WEBFLOW = "webflow"
274
362
  }
275
363
  /**
276
364
  * HTTP methods for type-safe method selection.
@@ -316,6 +404,8 @@ interface AlterVaultOptions {
316
404
  clientType?: string;
317
405
  /** AI framework (e.g., "langchain", "langgraph", "crewai") */
318
406
  framework?: string;
407
+ /** JWT identity resolution: callable that returns the current user's JWT */
408
+ userTokenGetter?: () => string | Promise<string>;
319
409
  }
320
410
  /**
321
411
  * Options for the request() method.
@@ -337,6 +427,10 @@ interface RequestOptions {
337
427
  threadId?: string;
338
428
  /** Tool invocation ID */
339
429
  toolCallId?: string;
430
+ /** Provider ID for identity resolution (e.g., "google"). Alternative to connectionId. */
431
+ provider?: string;
432
+ /** Account identifier for multi-account disambiguation (only with provider) */
433
+ account?: string;
340
434
  }
341
435
  /**
342
436
  * Options for the listConnections() method.
@@ -353,12 +447,6 @@ interface ListConnectionsOptions {
353
447
  * Options for the connect() method.
354
448
  */
355
449
  interface ConnectOptions {
356
- /** End user to create session for (requires at least id) */
357
- endUser: {
358
- id: string;
359
- email?: string;
360
- name?: string;
361
- };
362
450
  /** Restrict to specific providers (e.g., ["google"]) */
363
451
  providers?: string[];
364
452
  /** Max seconds to wait for completion (default 300 = 5 min) */
@@ -367,17 +455,18 @@ interface ConnectOptions {
367
455
  pollInterval?: number;
368
456
  /** If true, opens browser automatically. If false, prints URL. (default true) */
369
457
  openBrowser?: boolean;
458
+ /** TTL bounds for connection policy. End user picks duration within bounds in Connect UI. */
459
+ connectionPolicy?: {
460
+ /** Maximum TTL the end user can select (seconds) */
461
+ maxTtlSeconds?: number;
462
+ /** Pre-selected TTL in Connect UI (seconds) */
463
+ defaultTtlSeconds?: number;
464
+ };
370
465
  }
371
466
  /**
372
467
  * Options for the createConnectSession() method.
373
468
  */
374
469
  interface CreateConnectSessionOptions {
375
- /** End user to create session for (requires at least id) */
376
- endUser: {
377
- id: string;
378
- email?: string;
379
- name?: string;
380
- };
381
470
  /** Restrict to specific providers (e.g., ["google", "github"]) */
382
471
  allowedProviders?: string[];
383
472
  /** URL to redirect after OAuth completion */
@@ -389,6 +478,13 @@ interface CreateConnectSessionOptions {
389
478
  ipAddress?: string;
390
479
  userAgent?: string;
391
480
  };
481
+ /** TTL bounds for connection policy. End user picks duration within bounds in Connect UI. */
482
+ connectionPolicy?: {
483
+ /** Maximum TTL the end user can select (seconds) */
484
+ maxTtlSeconds?: number;
485
+ /** Pre-selected TTL in Connect UI (seconds) */
486
+ defaultTtlSeconds?: number;
487
+ };
392
488
  }
393
489
  /**
394
490
  * Main SDK class for Alter Vault OAuth token management.
@@ -431,7 +527,7 @@ declare class AlterVault {
431
527
  * 4. Logs the call for audit (fire-and-forget)
432
528
  * 5. Returns the raw response
433
529
  */
434
- request(connectionId: string, method: HttpMethod | string, url: string, options?: RequestOptions): Promise<Response>;
530
+ request(connectionId: string | null | undefined, method: HttpMethod | string, url: string, options?: RequestOptions): Promise<Response>;
435
531
  /**
436
532
  * List OAuth connections for this app.
437
533
  *
@@ -452,7 +548,7 @@ declare class AlterVault {
452
548
  * server-side applications. It creates a Connect session, opens the
453
549
  * browser, and polls until the user completes OAuth.
454
550
  *
455
- * @param options - Connect options (endUser is required)
551
+ * @param options - Connect options
456
552
  * @returns Array of ConnectResult objects (one per connected provider)
457
553
  * @throws ConnectTimeoutError if the user doesn't complete within timeout
458
554
  * @throws ConnectFlowError if the user denies or provider returns error
@@ -475,6 +571,25 @@ declare class AlterVault {
475
571
  * Exception hierarchy for Alter SDK.
476
572
  *
477
573
  * All exceptions inherit from AlterSDKError for easy catching.
574
+ * The hierarchy is organized by **developer action** — what you should do
575
+ * when you catch each error:
576
+ *
577
+ * AlterSDKError
578
+ * ├── BackendError — Alter Vault backend returned an error
579
+ * │ ├── ReAuthRequiredError — User must re-authorize via Alter Connect
580
+ * │ │ ├── ConnectionExpiredError — TTL elapsed
581
+ * │ │ ├── ConnectionRevokedError — Auth permanently broken
582
+ * │ │ └── ConnectionDeletedError — User disconnected via Wallet
583
+ * │ ├── ConnectionNotFoundError — Wrong connection_id — fix your code
584
+ * │ └── PolicyViolationError — Policy denied — may resolve on its own
585
+ * ├── ConnectFlowError — Connect flow failed
586
+ * │ ├── ConnectDeniedError — User clicked Deny
587
+ * │ ├── ConnectConfigError — OAuth app misconfigured
588
+ * │ └── ConnectTimeoutError — User didn't complete in time
589
+ * ├── ProviderAPIError — Provider returned 4xx/5xx
590
+ * │ └── ScopeReauthRequiredError — 403 + scope mismatch, user must re-authorize
591
+ * └── NetworkError — Connection/timeout errors
592
+ * └── TimeoutError — Request timed out
478
593
  */
479
594
  /**
480
595
  * Base exception for all Alter SDK errors.
@@ -485,50 +600,103 @@ declare class AlterSDKError extends Error {
485
600
  toString(): string;
486
601
  }
487
602
  /**
488
- * Raised when token retrieval fails.
603
+ * Raised when the Alter Vault backend returns an error.
489
604
  */
490
- declare class TokenRetrievalError extends AlterSDKError {
605
+ declare class BackendError extends AlterSDKError {
491
606
  constructor(message: string, details?: Record<string, unknown>);
492
607
  }
493
608
  /**
494
- * Raised when token access is denied by policy enforcement.
609
+ * Raised when the user must re-authorize via Alter Connect.
495
610
  *
496
- * This indicates the connection exists but access was denied by Cerbos policy
497
- * (e.g., unauthorized scopes, outside business hours, rate limit exceeded).
611
+ * This is the parent class for all errors that require the user to go through
612
+ * the Connect flow again. Catch this to handle all re-auth cases in one place.
498
613
  */
499
- declare class PolicyViolationError extends TokenRetrievalError {
500
- readonly policyError: string | undefined;
501
- constructor(message: string, policyError?: string, details?: Record<string, unknown>);
614
+ declare class ReAuthRequiredError extends BackendError {
615
+ constructor(message: string, details?: Record<string, unknown>);
502
616
  }
503
617
  /**
504
- * Raised when OAuth connection not found.
618
+ * Raised when a connection's TTL has expired.
505
619
  *
506
- * This indicates no connection exists for the given connection_id.
620
+ * The time-limited access granted during the Connect flow has elapsed.
621
+ * The user must re-authorize to restore access.
507
622
  */
508
- declare class ConnectionNotFoundError extends TokenRetrievalError {
623
+ declare class ConnectionExpiredError extends ReAuthRequiredError {
509
624
  constructor(message: string, details?: Record<string, unknown>);
510
625
  }
511
626
  /**
512
- * Raised when token refresh fails.
627
+ * Raised when a connection's auth is permanently broken.
513
628
  *
514
- * This indicates the connection exists but token refresh failed (e.g., refresh
515
- * token revoked, provider API error).
629
+ * This happens when:
630
+ * - The user revoked your app at the provider (e.g., Google Account settings)
631
+ * - The refresh token expired or was invalidated
632
+ * - Token refresh permanently failed (invalid_grant)
633
+ *
634
+ * The user must re-authorize via Alter Connect.
516
635
  */
517
- declare class TokenExpiredError extends TokenRetrievalError {
636
+ declare class ConnectionRevokedError extends ReAuthRequiredError {
518
637
  readonly connectionId: string | undefined;
519
638
  constructor(message: string, connectionId?: string, details?: Record<string, unknown>);
520
639
  }
640
+ /**
641
+ * Raised when a connection has been deliberately deleted.
642
+ *
643
+ * The end user disconnected the account via the Wallet dashboard.
644
+ * Re-authorization via Alter Connect will generate a **new** `connection_id`
645
+ * — update your stored reference from the `ConnectResult`.
646
+ */
647
+ declare class ConnectionDeletedError extends ReAuthRequiredError {
648
+ constructor(message: string, details?: Record<string, unknown>);
649
+ }
650
+ /**
651
+ * Raised when OAuth connection not found.
652
+ *
653
+ * No connection exists for the given connection_id.
654
+ * Check for typos or stale references.
655
+ */
656
+ declare class ConnectionNotFoundError extends BackendError {
657
+ constructor(message: string, details?: Record<string, unknown>);
658
+ }
659
+ /**
660
+ * Raised when token access is denied by policy enforcement.
661
+ *
662
+ * The connection exists but access was denied by a Cerbos policy
663
+ * (e.g., outside business hours, IP allowlist, rate limit exceeded).
664
+ * This may resolve on its own (e.g., wait until business hours).
665
+ */
666
+ declare class PolicyViolationError extends BackendError {
667
+ readonly policyError: string | undefined;
668
+ constructor(message: string, policyError?: string, details?: Record<string, unknown>);
669
+ }
521
670
  /**
522
671
  * Raised when the headless connect() flow fails.
523
672
  *
524
673
  * This can happen when:
525
674
  * - The user denies authorization
526
675
  * - The provider returns an error
676
+ * - The OAuth app is misconfigured
527
677
  * - The session expires before completion
528
678
  */
529
679
  declare class ConnectFlowError extends AlterSDKError {
530
680
  constructor(message: string, details?: Record<string, unknown>);
531
681
  }
682
+ /**
683
+ * Raised when the user denies authorization during the Connect flow.
684
+ *
685
+ * The user explicitly clicked "Deny" or "Cancel" on the provider's
686
+ * authorization page.
687
+ */
688
+ declare class ConnectDeniedError extends ConnectFlowError {
689
+ constructor(message: string, details?: Record<string, unknown>);
690
+ }
691
+ /**
692
+ * Raised when the OAuth app is misconfigured.
693
+ *
694
+ * Check your OAuth app configuration in the Developer Portal.
695
+ * Common causes: wrong redirect URI, invalid client ID/secret.
696
+ */
697
+ declare class ConnectConfigError extends ConnectFlowError {
698
+ constructor(message: string, details?: Record<string, unknown>);
699
+ }
532
700
  /**
533
701
  * Raised when the connect() flow times out.
534
702
  *
@@ -547,6 +715,36 @@ declare class ProviderAPIError extends AlterSDKError {
547
715
  readonly responseBody: string | undefined;
548
716
  constructor(message: string, statusCode?: number, responseBody?: string, details?: Record<string, unknown>);
549
717
  }
718
+ /**
719
+ * Raised when a provider API returns 403 and the connection has a scope mismatch.
720
+ *
721
+ * This indicates the connection's OAuth scopes don't match the provider config's
722
+ * required scopes — typically because the developer added new scopes after the
723
+ * user originally authorized. The user needs to re-authorize via a Connect session
724
+ * to grant the updated permissions.
725
+ *
726
+ * Recovery:
727
+ * ```typescript
728
+ * try {
729
+ * const result = await vault.request(connId, HttpMethod.GET, url);
730
+ * } catch (e) {
731
+ * if (e instanceof ScopeReauthRequiredError) {
732
+ * const session = await vault.createConnectSession({
733
+ * allowedProviders: [e.providerId],
734
+ * });
735
+ * notifyUser(e.connectionId, session.connectUrl);
736
+ * }
737
+ * }
738
+ * ```
739
+ *
740
+ * Extends ProviderAPIError so existing `catch` blocks for ProviderAPIError
741
+ * continue to work without code changes.
742
+ */
743
+ declare class ScopeReauthRequiredError extends ProviderAPIError {
744
+ readonly connectionId: string | undefined;
745
+ readonly providerId: string | undefined;
746
+ constructor(message: string, connectionId?: string, providerId?: string, statusCode?: number, responseBody?: string, details?: Record<string, unknown>);
747
+ }
550
748
  /**
551
749
  * Raised when network operations fail.
552
750
  *
@@ -569,4 +767,4 @@ declare class TimeoutError extends NetworkError {
569
767
  constructor(message: string, details?: Record<string, unknown>);
570
768
  }
571
769
 
572
- export { APICallAuditLog, ActorType, AlterSDKError, AlterVault, type AlterVaultOptions, ConnectFlowError, type ConnectOptions, ConnectResult, ConnectSession, ConnectTimeoutError, ConnectionInfo, ConnectionListResult, ConnectionNotFoundError, type CreateConnectSessionOptions, HttpMethod, type ListConnectionsOptions, NetworkError, PolicyViolationError, Provider, ProviderAPIError, type RequestOptions, TimeoutError, TokenExpiredError, TokenResponse, TokenRetrievalError };
770
+ export { APICallAuditLog, ActorType, AlterSDKError, AlterVault, type AlterVaultOptions, BackendError, ConnectConfigError, ConnectDeniedError, ConnectFlowError, type ConnectOptions, ConnectResult, ConnectSession, ConnectTimeoutError, ConnectionDeletedError, ConnectionExpiredError, ConnectionInfo, ConnectionListResult, ConnectionNotFoundError, type ConnectionPolicy, ConnectionRevokedError, type CreateConnectSessionOptions, HttpMethod, type ListConnectionsOptions, NetworkError, PolicyViolationError, Provider, ProviderAPIError, ReAuthRequiredError, type RequestOptions, ScopeReauthRequiredError, TimeoutError, TokenResponse };