@atlasauth/backend 0.25.0 → 0.27.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +42 -1
  2. package/dist/client/abac.d.ts +454 -0
  3. package/dist/client/abac.js +123 -0
  4. package/dist/client/abac.js.map +1 -1
  5. package/dist/client/access-policies.d.ts +84 -2
  6. package/dist/client/access-policies.js +8 -0
  7. package/dist/client/access-policies.js.map +1 -1
  8. package/dist/client/actions.d.ts +1 -1
  9. package/dist/client/actions.js.map +1 -1
  10. package/dist/client/agent-platform.d.ts +294 -0
  11. package/dist/client/agent-platform.js +132 -0
  12. package/dist/client/agent-platform.js.map +1 -0
  13. package/dist/client/analytics-reports.d.ts +1 -1
  14. package/dist/client/app-catalog.d.ts +60 -1
  15. package/dist/client/app-catalog.js +32 -2
  16. package/dist/client/app-catalog.js.map +1 -1
  17. package/dist/client/authz-decisions.d.ts +154 -0
  18. package/dist/client/authz-decisions.js +53 -0
  19. package/dist/client/authz-decisions.js.map +1 -0
  20. package/dist/client/connections.d.ts +519 -0
  21. package/dist/client/connections.js +171 -0
  22. package/dist/client/connections.js.map +1 -0
  23. package/dist/client/custom-oauth-providers.d.ts +15 -0
  24. package/dist/client/custom-oauth-providers.js.map +1 -1
  25. package/dist/client/desktop-mfa.d.ts +141 -0
  26. package/dist/client/desktop-mfa.js +58 -0
  27. package/dist/client/desktop-mfa.js.map +1 -0
  28. package/dist/client/devices.d.ts +130 -0
  29. package/dist/client/devices.js +54 -0
  30. package/dist/client/devices.js.map +1 -1
  31. package/dist/client/email-templates.d.ts +1 -1
  32. package/dist/client/email-templates.js.map +1 -1
  33. package/dist/client/fga.d.ts +301 -5
  34. package/dist/client/fga.js +81 -1
  35. package/dist/client/fga.js.map +1 -1
  36. package/dist/client/iga.d.ts +436 -0
  37. package/dist/client/iga.js +82 -0
  38. package/dist/client/iga.js.map +1 -0
  39. package/dist/client/index.d.ts +3767 -2443
  40. package/dist/client/index.js +51 -0
  41. package/dist/client/index.js.map +1 -1
  42. package/dist/client/least-privilege.d.ts +95 -0
  43. package/dist/client/least-privilege.js +28 -0
  44. package/dist/client/least-privilege.js.map +1 -0
  45. package/dist/client/log-streams.d.ts +1 -1
  46. package/dist/client/managed-grants.d.ts +52 -0
  47. package/dist/client/managed-grants.js +28 -0
  48. package/dist/client/managed-grants.js.map +1 -0
  49. package/dist/client/mcp-gateways.d.ts +220 -2
  50. package/dist/client/mcp-gateways.js +74 -0
  51. package/dist/client/mcp-gateways.js.map +1 -1
  52. package/dist/client/messaging.d.ts +11 -2
  53. package/dist/client/messaging.js.map +1 -1
  54. package/dist/client/oauth-clients.d.ts +4 -0
  55. package/dist/client/oauth-clients.js.map +1 -1
  56. package/dist/client/oauth-protocols.d.ts +116 -0
  57. package/dist/client/oauth-protocols.js +54 -0
  58. package/dist/client/oauth-protocols.js.map +1 -0
  59. package/dist/client/oauth-providers.d.ts +4 -4
  60. package/dist/client/openfga.d.ts +90 -3
  61. package/dist/client/openfga.js +27 -1
  62. package/dist/client/openfga.js.map +1 -1
  63. package/dist/client/org-ldap-connections.d.ts +3 -0
  64. package/dist/client/org-ldap-connections.js.map +1 -1
  65. package/dist/client/organizations.d.ts +14 -0
  66. package/dist/client/organizations.js.map +1 -1
  67. package/dist/client/policy-bundles.d.ts +105 -0
  68. package/dist/client/policy-bundles.js +38 -0
  69. package/dist/client/policy-bundles.js.map +1 -0
  70. package/dist/client/resources.d.ts +1 -0
  71. package/dist/client/resources.js.map +1 -1
  72. package/dist/client/risk-containment.d.ts +244 -0
  73. package/dist/client/risk-containment.js +120 -0
  74. package/dist/client/risk-containment.js.map +1 -0
  75. package/dist/client/saml-idp.d.ts +183 -0
  76. package/dist/client/saml-idp.js +71 -0
  77. package/dist/client/saml-idp.js.map +1 -0
  78. package/dist/client/scim-provisioning.d.ts +100 -4
  79. package/dist/client/scim-provisioning.js +30 -0
  80. package/dist/client/scim-provisioning.js.map +1 -1
  81. package/dist/client/scim-tokens.d.ts +34 -0
  82. package/dist/client/scim-tokens.js +17 -0
  83. package/dist/client/scim-tokens.js.map +1 -1
  84. package/dist/client/service-connectors.d.ts +1 -1
  85. package/dist/client/ssf.d.ts +31 -1
  86. package/dist/client/ssf.js +17 -0
  87. package/dist/client/ssf.js.map +1 -1
  88. package/dist/client/users.d.ts +9 -0
  89. package/dist/client/users.js +9 -0
  90. package/dist/client/users.js.map +1 -1
  91. package/dist/client/vault.d.ts +54 -0
  92. package/dist/client/vault.js +30 -0
  93. package/dist/client/vault.js.map +1 -1
  94. package/dist/client/vc.d.ts +62 -2
  95. package/dist/client/vc.js +15 -0
  96. package/dist/client/vc.js.map +1 -1
  97. package/dist/client/workflows.d.ts +182 -3
  98. package/dist/client/workflows.js +34 -0
  99. package/dist/client/workflows.js.map +1 -1
  100. package/dist/index.d.ts +5 -2
  101. package/dist/index.js +6 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/oauth-resource.d.ts +30 -3
  104. package/dist/oauth-resource.js +43 -2
  105. package/dist/oauth-resource.js.map +1 -1
  106. package/dist/policy-bundle.d.ts +110 -0
  107. package/dist/policy-bundle.js +289 -0
  108. package/dist/policy-bundle.js.map +1 -0
  109. package/dist/txn-token.d.ts +36 -0
  110. package/dist/txn-token.js +30 -0
  111. package/dist/txn-token.js.map +1 -0
  112. package/dist/uma.d.ts +77 -0
  113. package/dist/uma.js +95 -0
  114. package/dist/uma.js.map +1 -0
  115. package/package.json +2 -2
@@ -0,0 +1,519 @@
1
+ import { type RequestFn } from './request';
2
+ import type { CursorParams, ListPage } from './types';
3
+ export type ConnectionOwnerType = 'organization' | 'user';
4
+ export type ConnectionEnvironment = 'production' | 'sandbox';
5
+ export type ConnectionRelayMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
6
+ export type ConnectionStatus = 'connected' | 'needs_reauth' | 'revoked' | 'error' | 'not_connected';
7
+ /**
8
+ * A connection: one provider account that an organization or a user owns. An OAuth connection holds its own
9
+ * token set (sealed in the vault), independent of any user, and is never a sign-in method.
10
+ */
11
+ export interface Connection {
12
+ object: 'connection';
13
+ id: string;
14
+ owner: {
15
+ type: ConnectionOwnerType;
16
+ id: string;
17
+ };
18
+ kind: string;
19
+ provider: string;
20
+ name: string;
21
+ allowed_hosts: string[];
22
+ config: Record<string, unknown>;
23
+ status: ConnectionStatus;
24
+ /** Always `data`: connecting adds no sign-in method. */
25
+ purpose: 'data';
26
+ environment: ConnectionEnvironment;
27
+ sandbox: boolean;
28
+ /** The provider-side account this connection covers (a realm, a workspace, a hub, a user id). */
29
+ external_id: string | null;
30
+ host_params: Record<string, string>;
31
+ oauth_client_id: string | null;
32
+ /** Connections from one grant (a Xero split connect) share this id and one token set; null = the connection owns its tokens. */
33
+ token_family_id: string | null;
34
+ scopes: string[];
35
+ /** Epoch ms. */
36
+ expires_at: number | null;
37
+ metadata: Record<string, string>;
38
+ authorized_by_user_id: string | null;
39
+ connected_at: number | null;
40
+ last_refreshed_at: number | null;
41
+ status_changed_at: number | null;
42
+ /** Why the connection left `connected`, or why the last refresh failed: the provider's own error code and HTTP status. */
43
+ last_error: {
44
+ code: string;
45
+ message: string;
46
+ httpStatus?: number | null;
47
+ at: number;
48
+ } | null;
49
+ /** Consecutive failed refreshes; 0 when healthy. */
50
+ refresh_failures: number;
51
+ /** When the keep-alive worker next refreshes this connection (epoch ms). */
52
+ next_refresh_at: number | null;
53
+ /** @deprecated Always null: a connection owns its tokens. */
54
+ external_account_id: null;
55
+ has_secret: boolean;
56
+ /** When the entered credential expires (epoch ms); `connection.secret_expiring` reminders go out 30, 7 and 1 days before. */
57
+ secret_expires_at: number | null;
58
+ /** While a rotation's overlap window is open: when the replaced version stops being accepted. */
59
+ previous_valid_until: number | null;
60
+ allowed_methods: ConnectionRelayMethod[];
61
+ created_at: number;
62
+ updated_at: number;
63
+ }
64
+ export interface CreateConnectionBody {
65
+ owner: {
66
+ type: ConnectionOwnerType;
67
+ id: string;
68
+ };
69
+ kind: string;
70
+ provider: string;
71
+ name?: string;
72
+ allowed_hosts: string[];
73
+ config?: Record<string, unknown>;
74
+ environment?: ConnectionEnvironment;
75
+ /** Values that fill the provider's host templates, e.g. `{ subdomain: 'acme' }`. Validated per provider. */
76
+ host_params?: Record<string, string>;
77
+ /** Relay verbs this connection may use; GET, HEAD and POST unless set. */
78
+ allowed_methods?: ConnectionRelayMethod[];
79
+ }
80
+ export interface UpdateConnectionBody {
81
+ name?: string;
82
+ allowed_hosts?: string[];
83
+ config?: Record<string, unknown>;
84
+ /** Transfer to another owner; the stored tokens move with it. */
85
+ owner?: {
86
+ type: ConnectionOwnerType;
87
+ id: string;
88
+ };
89
+ environment?: ConnectionEnvironment;
90
+ host_params?: Record<string, string>;
91
+ shared_by_user_id?: string;
92
+ allowed_methods?: ConnectionRelayMethod[];
93
+ }
94
+ export interface ListConnectionsParams extends CursorParams {
95
+ owner_type?: ConnectionOwnerType;
96
+ owner_id?: string;
97
+ provider?: string;
98
+ environment?: ConnectionEnvironment;
99
+ status?: ConnectionStatus;
100
+ }
101
+ export interface ConnectConnectionBody {
102
+ redirect_url: string;
103
+ host_params?: Record<string, string>;
104
+ environment?: ConnectionEnvironment;
105
+ additional_scopes?: string[];
106
+ login_hint?: string;
107
+ display?: 'redirect' | 'popup';
108
+ /** A different provider account than the connection holds creates a sibling instead of answering 409. */
109
+ create_if_new?: boolean;
110
+ /** One grant covering several accounts (Xero organisations) becomes one connection per account, sharing one token set. */
111
+ split_tenants?: boolean;
112
+ connect_user_id?: string;
113
+ }
114
+ export interface ConnectionAuthorization {
115
+ object: 'connection_authorization';
116
+ connection_id: string;
117
+ authorization_url: string;
118
+ attempt_id: string;
119
+ }
120
+ export interface ConnectionToken {
121
+ object: 'connection_token';
122
+ connection_id: string;
123
+ access_token: string;
124
+ expires_at: number | null;
125
+ scopes: string[];
126
+ metadata: Record<string, string>;
127
+ token_response: Record<string, unknown>;
128
+ /** Further credentials by name (Slack: `user`). */
129
+ credentials: Record<string, {
130
+ access_token: string;
131
+ expires_at: number | null;
132
+ scopes: string[];
133
+ }>;
134
+ external_id: string | null;
135
+ environment: ConnectionEnvironment;
136
+ host_params: Record<string, string>;
137
+ refreshed: boolean;
138
+ /** jwt_bearer: the user the token acts as (domain-wide delegation). */
139
+ subject?: string;
140
+ }
141
+ /** What the provider said when a token was revoked. The local token is cleared in every case. */
142
+ export interface ProviderRevokeResult {
143
+ /** `true` the provider confirmed; `'unsupported'` it has no revoke endpoint; `false` it refused or was unreachable (see `provider_error`). */
144
+ provider_revoked: boolean | 'unsupported' | 'not_connected';
145
+ provider_status: number | null;
146
+ provider_error: {
147
+ code: string;
148
+ description: string | null;
149
+ } | null;
150
+ local_cleared: true;
151
+ }
152
+ export type ConnectionRevoked = Connection & ProviderRevokeResult;
153
+ export interface ConnectionDeletion extends ProviderRevokeResult {
154
+ object: 'connection_deletion';
155
+ id: string;
156
+ deleted: true;
157
+ }
158
+ export interface ConnectionTokenBatchItem {
159
+ id: string;
160
+ status: 'ok' | 'error';
161
+ token?: ConnectionToken;
162
+ error?: {
163
+ code: 'connection_required' | 'not_found';
164
+ reason?: 'not_connected' | 'needs_reauth' | 'revoked' | 'refresh_failed' | 'unknown_connection';
165
+ };
166
+ }
167
+ /** One row of a bulk import. `external_id` is the provider-side account; a re-import of it updates the same connection. */
168
+ export interface ImportConnectionRow {
169
+ provider: string;
170
+ owner: {
171
+ type: ConnectionOwnerType;
172
+ id: string;
173
+ };
174
+ external_id: string;
175
+ refresh_token?: string;
176
+ access_token?: string;
177
+ /** Epoch ms or ISO 8601. */
178
+ expires_at?: number | string;
179
+ scopes?: string[] | string;
180
+ metadata?: Record<string, string | number | boolean>;
181
+ environment?: ConnectionEnvironment;
182
+ host_params?: Record<string, string>;
183
+ name?: string;
184
+ allowed_hosts?: string[];
185
+ }
186
+ export interface ImportConnectionsBody {
187
+ /** 1 to 500 rows. */
188
+ connections: ImportConnectionRow[];
189
+ /** Spend each refresh token against the provider and store what it issues (default true). */
190
+ validate?: boolean;
191
+ /** Check shapes only; never calls the provider. */
192
+ dry_run?: boolean;
193
+ }
194
+ export interface ImportConnectionResult {
195
+ index: number;
196
+ status: 'created' | 'updated' | 'would_create' | 'would_update' | 'failed';
197
+ connection_id: string | null;
198
+ validated: boolean;
199
+ refreshed: boolean;
200
+ error: {
201
+ code: string;
202
+ message: string;
203
+ field?: string;
204
+ provider_error?: {
205
+ code: string;
206
+ description: string | null;
207
+ http_status: number | null;
208
+ };
209
+ } | null;
210
+ }
211
+ export interface ImportConnectionsResult {
212
+ object: 'connection_import';
213
+ total: number;
214
+ dry_run: boolean;
215
+ validated: boolean;
216
+ created: number;
217
+ updated: number;
218
+ would_create: number;
219
+ would_update: number;
220
+ failed: number;
221
+ data: ImportConnectionResult[];
222
+ }
223
+ export interface ExportConnectionsBody {
224
+ owner_type?: ConnectionOwnerType;
225
+ owner_id?: string;
226
+ provider?: string;
227
+ environment?: ConnectionEnvironment;
228
+ status?: ConnectionStatus;
229
+ limit?: number;
230
+ starting_after?: string;
231
+ /** Include the tokens, sealed to `recipient_public_key`. Needs the `connections:export_secrets` scope. */
232
+ include_secrets?: boolean;
233
+ /** A public JWK: RSA (3072 bits or more) or EC P-256/384/521. Never the private half. */
234
+ recipient_public_key?: Record<string, unknown>;
235
+ }
236
+ export interface ExportedConnection {
237
+ provider: string;
238
+ owner: {
239
+ type: ConnectionOwnerType;
240
+ id: string;
241
+ };
242
+ external_id: string | null;
243
+ environment: ConnectionEnvironment;
244
+ host_params: Record<string, string>;
245
+ scopes: string[];
246
+ metadata: Record<string, string>;
247
+ name: string;
248
+ allowed_hosts: string[];
249
+ status: ConnectionStatus;
250
+ expires_at: number | null;
251
+ refresh_token?: string;
252
+ access_token?: string;
253
+ }
254
+ export type ExportConnectionsResult = {
255
+ object: 'connection_export';
256
+ sealed: false;
257
+ count: number;
258
+ has_more: boolean;
259
+ next_cursor: string | null;
260
+ connections: ExportedConnection[];
261
+ } | {
262
+ object: 'connection_export';
263
+ sealed: true;
264
+ count: number;
265
+ has_more: boolean;
266
+ next_cursor: string | null;
267
+ recipient_key_id: string;
268
+ bundle: string;
269
+ };
270
+ export interface TokenReadOptions {
271
+ /** Refresh first unless at least this many seconds of validity remain (0 to 3600). */
272
+ minTtlSeconds?: number;
273
+ /** Force a refresh now. Prefer {@link refreshToken}, which does not refresh again when a peer already did. */
274
+ refresh?: boolean;
275
+ /** Skip the in-process cache for this call. */
276
+ noCache?: boolean;
277
+ /** jwt_bearer only: act as this user (Google domain-wide delegation). Never cached. */
278
+ subject?: string;
279
+ }
280
+ /** An owner's own OAuth client (BYOK) for a provider. The secret is write-only. */
281
+ export interface ConnectionOAuthClient {
282
+ object: 'connection_oauth_client';
283
+ id: string;
284
+ owner: {
285
+ type: ConnectionOwnerType;
286
+ id: string;
287
+ };
288
+ provider: string;
289
+ environment: ConnectionEnvironment;
290
+ client_id: string;
291
+ has_secret: true;
292
+ scopes: string[];
293
+ host_params: Record<string, string>;
294
+ enabled: boolean;
295
+ /** The redirect URI to register on this client at the provider. */
296
+ callback_url: string;
297
+ created_at: number;
298
+ updated_at: number;
299
+ }
300
+ export interface SetConnectionOAuthClientBody {
301
+ owner: {
302
+ type: ConnectionOwnerType;
303
+ id: string;
304
+ };
305
+ provider: string;
306
+ environment?: ConnectionEnvironment;
307
+ client_id: string;
308
+ /** Required when the client is first created; omit to keep the stored secret. */
309
+ client_secret?: string;
310
+ scopes?: string[];
311
+ host_params?: Record<string, string>;
312
+ enabled?: boolean;
313
+ }
314
+ /**
315
+ * The credential fields of a connection's kind (write-only). api_key `{api_key}`, bearer `{token}`, basic
316
+ * `{username, password}`, custom_header `{value}`, hmac_secret `{secret}`, client_credentials `{client_id,
317
+ * client_secret, token_url...}`, jwt_bearer `{private_key | service_account_json | generate_key | assertion}`,
318
+ * oauth1 `{consumer_key, consumer_secret, token?, token_secret?}`, github_app_installation `{private_key}`.
319
+ * The kind's non-secret settings may ride along or go in `config`.
320
+ */
321
+ export interface SetConnectionCredentialsBody {
322
+ [field: string]: unknown;
323
+ /** Epoch milliseconds or an ISO date. Reminders go out at 30, 7 and 1 days before. */
324
+ expires_at?: number | string;
325
+ config?: Record<string, unknown>;
326
+ }
327
+ export interface RotateConnectionCredentialsBody extends SetConnectionCredentialsBody {
328
+ /** How long the replaced version stays valid, 0 to 30 days. Default 3600. */
329
+ overlap_seconds?: number;
330
+ }
331
+ export interface ConnectionSecret {
332
+ object: 'connection_secret';
333
+ connection_id: string;
334
+ kind: 'api_key' | 'bearer' | 'basic' | 'custom_header' | 'hmac_secret';
335
+ version: number;
336
+ /** api_key `{api_key}`, bearer `{token}`, basic `{username, password}`, custom_header `{value}`, hmac_secret `{secret}`. */
337
+ secret: Record<string, string>;
338
+ config: Record<string, unknown>;
339
+ expires_at: number | null;
340
+ }
341
+ export interface ConnectionSecretVersions {
342
+ object: 'list';
343
+ connection_id: string;
344
+ current_version: number | null;
345
+ previous_valid_until: number | null;
346
+ data: Array<{
347
+ object: 'connection_secret_version';
348
+ version: number;
349
+ current: boolean;
350
+ previous: boolean;
351
+ created_at: number;
352
+ valid_until: number | null;
353
+ }>;
354
+ has_more: false;
355
+ }
356
+ export interface ConnectionSignature {
357
+ object: 'connection_signature';
358
+ connection_id: string;
359
+ /** The `Authorization: OAuth ...` header value, valid for this method, URL and body only. */
360
+ authorization: string;
361
+ method: string;
362
+ url: string;
363
+ }
364
+ export type ConnectionWebhookScheme = 'hubspot_v3' | 'shopify_hmac' | 'intercom' | 'zoom' | 'slack_v0' | 'calendly' | 'stripe' | 'generic_hmac_sha256';
365
+ export interface VerifyConnectionWebhookBody {
366
+ scheme: ConnectionWebhookScheme;
367
+ /** The delivery's headers. */
368
+ headers: Record<string, string>;
369
+ /** The body exactly as received. */
370
+ raw_body: string;
371
+ raw_body_encoding?: 'utf8' | 'base64';
372
+ /** hubspot_v3: the method and the full URL the provider posted to. */
373
+ method?: string;
374
+ url?: string;
375
+ /** Use this webhook endpoint's signing secret and options. */
376
+ endpoint_id?: string;
377
+ tolerance_seconds?: number;
378
+ /** generic_hmac_sha256: `signature_header`, `encoding`, `prefix`, `algorithm`. */
379
+ options?: Record<string, string>;
380
+ /** false checks without remembering the delivery for replay protection. */
381
+ record_replay?: boolean;
382
+ }
383
+ export interface ConnectionWebhookVerification {
384
+ object: 'connection_webhook_verification';
385
+ connection_id: string;
386
+ scheme: ConnectionWebhookScheme;
387
+ valid: boolean;
388
+ reason: 'missing_signature' | 'missing_timestamp' | 'malformed_signature' | 'stale_timestamp' | 'bad_signature' | 'url_required' | 'replayed' | null;
389
+ replayed: boolean;
390
+ timestamp: number | null;
391
+ delivery_id: string | null;
392
+ /** Zoom endpoint.url_validation or Slack url_verification: answer the provider with this body. */
393
+ handshake: Record<string, string> | null;
394
+ }
395
+ export interface ConnectionWebhookEndpoint {
396
+ object: 'connection_webhook_endpoint';
397
+ id: string;
398
+ connection_id: string;
399
+ scheme: ConnectionWebhookScheme;
400
+ forward_url: string;
401
+ /** Give this URL to the provider. */
402
+ ingress_url: string;
403
+ options: Record<string, string>;
404
+ has_signing_secret: boolean;
405
+ enabled: boolean;
406
+ last_delivery_at: number | null;
407
+ created_at: number;
408
+ updated_at: number;
409
+ /** Only in the create response, once: verifies the Atlas-signed deliveries sent to `forward_url`. */
410
+ forward_secret?: string;
411
+ }
412
+ export interface CreateConnectionWebhookEndpointBody {
413
+ scheme: ConnectionWebhookScheme;
414
+ /** https URL that receives verified deliveries as Atlas-signed webhooks. */
415
+ forward_url: string;
416
+ /** Write-only provider signing secret for this endpoint. */
417
+ signing_secret?: string;
418
+ options?: Record<string, string>;
419
+ }
420
+ /** Org- or user-owned provider connections and their stored tokens. */
421
+ export declare function connectionsResource(request: RequestFn): {
422
+ create(body: CreateConnectionBody, idempotencyKey?: string): Promise<Connection>;
423
+ list(params?: ListConnectionsParams): Promise<ListPage<Connection>>;
424
+ get(id: string): Promise<Connection>;
425
+ update(id: string, body: UpdateConnectionBody): Promise<Connection>;
426
+ /** Delete a connection. Pass `{ revoke: true }` to revoke at the provider first and learn what it said. */
427
+ delete<R extends boolean = false>(id: string, options?: {
428
+ revoke?: R;
429
+ }): Promise<R extends true ? ConnectionDeletion : void>;
430
+ /** Start the provider authorization; send the owner to `authorization_url`. */
431
+ connect(id: string, body: ConnectConnectionBody): Promise<ConnectionAuthorization>;
432
+ /** Revoke at the provider and forget the stored token. The answer says what the provider said (`provider_revoked`). */
433
+ revoke(id: string): Promise<ConnectionRevoked>;
434
+ /**
435
+ * The live token for your backend (refreshed when needed). Needs the `connections:token` scope.
436
+ * Reads are cached in this client until shortly before `expires_at` (and a cached read is `refreshed: false`),
437
+ * so calling it in a hot loop costs one request per connection per token lifetime.
438
+ */
439
+ token(id: string, options?: TokenReadOptions): Promise<ConnectionToken>;
440
+ /**
441
+ * Call this when the provider answers 401 to a token you got from here. Pass the access token you were refused with
442
+ * (`staleAccessToken`): if Atlas already holds a newer one, you get it back without another call to the provider.
443
+ */
444
+ refreshToken(id: string, options?: {
445
+ staleAccessToken?: string;
446
+ reason?: "provider_401" | "expired" | "manual";
447
+ }): Promise<ConnectionToken>;
448
+ /**
449
+ * A token limited to a subset of the granted scopes, for a less-trusted caller. Not cached and never replaces the
450
+ * connection's own token. Refused with 422 `invalid_scope` or `downscope_unsupported` (the provider cannot narrow).
451
+ */
452
+ downscopeToken(id: string, scopes: string[]): Promise<{
453
+ object: "connection_token";
454
+ connection_id: string;
455
+ access_token: string;
456
+ expires_at: number | null;
457
+ scopes: string[];
458
+ downscoped: true;
459
+ }>;
460
+ /** Read up to 100 connections' tokens in one call. Each id has its own result, so one dead connection does not fail the rest. */
461
+ tokens(ids: string[], options?: {
462
+ minTtlSeconds?: number;
463
+ }): Promise<{
464
+ object: "list";
465
+ data: ConnectionTokenBatchItem[];
466
+ has_more: false;
467
+ }>;
468
+ /** Bulk-import existing provider refresh tokens (up to 500 per call). Needs the `connections:import` scope. */
469
+ importConnections(body: ImportConnectionsBody, idempotencyKey?: string): Promise<ImportConnectionsResult>;
470
+ /**
471
+ * Export connections. Without `include_secrets` it lists metadata. With it (scope `connections:export_secrets`) the tokens
472
+ * come back as one compact JWE sealed to `recipient_public_key`; open it with the matching private key.
473
+ */
474
+ exportConnections(body?: ExportConnectionsBody): Promise<ExportConnectionsResult>;
475
+ /** Enter the credential of a non-OAuth connection (write-only; sealed in the vault, never returned). */
476
+ setCredentials(id: string, body: SetConnectionCredentialsBody): Promise<Connection>;
477
+ /** Rotate the credential; the replaced version stays valid for `overlap_seconds`. */
478
+ rotateCredentials(id: string, body: RotateConnectionCredentialsBody): Promise<Connection>;
479
+ /** The credential's vault versions (numbers and times, never values). */
480
+ secretVersions(id: string): Promise<ConnectionSecretVersions>;
481
+ /**
482
+ * Read an api_key, bearer, basic, custom_header or hmac_secret credential. Needs the `connections:secret_read`
483
+ * scope; every read is audited. `version` is `current` (default), `previous` (inside a rotation's overlap
484
+ * window) or a number. With `organizationId` the connection must belong to that organization (404 otherwise).
485
+ */
486
+ secret(id: string, options?: {
487
+ version?: "current" | "previous" | number;
488
+ organizationId?: string;
489
+ }): Promise<ConnectionSecret>;
490
+ /** Have Atlas sign a request with an oauth1 connection (needs `connections:sign`). */
491
+ oauth1Sign(id: string, body: {
492
+ method?: string;
493
+ url: string;
494
+ body?: string;
495
+ content_type?: string;
496
+ }): Promise<ConnectionSignature>;
497
+ webhooks: {
498
+ /** Verify a provider webhook signature (needs `connections:webhook_verify`). */
499
+ verify(id: string, body: VerifyConnectionWebhookBody): Promise<ConnectionWebhookVerification>;
500
+ createEndpoint(id: string, body: CreateConnectionWebhookEndpointBody): Promise<ConnectionWebhookEndpoint>;
501
+ listEndpoints(id: string): Promise<ListPage<ConnectionWebhookEndpoint>>;
502
+ updateEndpoint(id: string, endpointId: string, body: {
503
+ forward_url?: string;
504
+ enabled?: boolean;
505
+ signing_secret?: string;
506
+ }): Promise<ConnectionWebhookEndpoint>;
507
+ deleteEndpoint(id: string, endpointId: string): Promise<void>;
508
+ };
509
+ oauthClients: {
510
+ set(body: SetConnectionOAuthClientBody): Promise<ConnectionOAuthClient>;
511
+ list(params?: {
512
+ owner_type?: ConnectionOwnerType;
513
+ owner_id?: string;
514
+ provider?: string;
515
+ }): Promise<ListPage<ConnectionOAuthClient>>;
516
+ get(id: string): Promise<ConnectionOAuthClient>;
517
+ delete(id: string): Promise<void>;
518
+ };
519
+ };
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connectionsResource = connectionsResource;
4
+ const request_1 = require("./request");
5
+ const SKEW_MS = 60_000;
6
+ async function sha256Hex(text) {
7
+ const d = await globalThis.crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));
8
+ return [...new Uint8Array(d)].map((b) => b.toString(16).padStart(2, '0')).join('');
9
+ }
10
+ /** Org- or user-owned provider connections and their stored tokens. */
11
+ function connectionsResource(request) {
12
+ // Tokens read by this client, reused until shortly before the provider's `expires_at`. A token with no expiry is never cached.
13
+ const cache = new Map();
14
+ const live = (t, minTtlSeconds) => !!t && t.expires_at !== null && t.expires_at - Date.now() > Math.max(minTtlSeconds * 1000, SKEW_MS);
15
+ const remember = (t) => {
16
+ if (t.expires_at !== null)
17
+ cache.set(t.connection_id, t);
18
+ else
19
+ cache.delete(t.connection_id);
20
+ return t;
21
+ };
22
+ return {
23
+ create(body, idempotencyKey) {
24
+ return request({ method: 'POST', path: '/v1/connections', body, idempotencyKey });
25
+ },
26
+ list(params = {}) {
27
+ return request({ method: 'GET', path: '/v1/connections', query: { ...params } });
28
+ },
29
+ get(id) {
30
+ return request({ method: 'GET', path: `/v1/connections/${(0, request_1.enc)(id)}` });
31
+ },
32
+ update(id, body) {
33
+ return request({ method: 'PATCH', path: `/v1/connections/${(0, request_1.enc)(id)}`, body });
34
+ },
35
+ /** Delete a connection. Pass `{ revoke: true }` to revoke at the provider first and learn what it said. */
36
+ delete(id, options = {}) {
37
+ cache.delete(id);
38
+ return request({ method: 'DELETE', path: `/v1/connections/${(0, request_1.enc)(id)}`, query: options.revoke ? { revoke: 'true' } : undefined });
39
+ },
40
+ /** Start the provider authorization; send the owner to `authorization_url`. */
41
+ connect(id, body) {
42
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/connect`, body });
43
+ },
44
+ /** Revoke at the provider and forget the stored token. The answer says what the provider said (`provider_revoked`). */
45
+ revoke(id) {
46
+ cache.delete(id);
47
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/revoke` });
48
+ },
49
+ /**
50
+ * The live token for your backend (refreshed when needed). Needs the `connections:token` scope.
51
+ * Reads are cached in this client until shortly before `expires_at` (and a cached read is `refreshed: false`),
52
+ * so calling it in a hot loop costs one request per connection per token lifetime.
53
+ */
54
+ async token(id, options = {}) {
55
+ const minTtl = options.minTtlSeconds ?? 0;
56
+ const hit = cache.get(id);
57
+ if (options.subject) {
58
+ return request({ method: 'GET', path: `/v1/connections/${(0, request_1.enc)(id)}/token`, query: { subject: options.subject, ...(options.refresh ? { refresh: 'true' } : {}) } });
59
+ }
60
+ if (!options.refresh && !options.noCache && live(hit, minTtl))
61
+ return { ...hit, refreshed: false };
62
+ const t = await request({
63
+ method: 'GET',
64
+ path: `/v1/connections/${(0, request_1.enc)(id)}/token`,
65
+ query: { ...(options.refresh ? { refresh: 'true' } : {}), ...(minTtl ? { min_ttl_seconds: String(minTtl) } : {}) },
66
+ });
67
+ return remember(t);
68
+ },
69
+ /**
70
+ * Call this when the provider answers 401 to a token you got from here. Pass the access token you were refused with
71
+ * (`staleAccessToken`): if Atlas already holds a newer one, you get it back without another call to the provider.
72
+ */
73
+ async refreshToken(id, options = {}) {
74
+ cache.delete(id);
75
+ const t = await request({
76
+ method: 'POST',
77
+ path: `/v1/connections/${(0, request_1.enc)(id)}/token/refresh`,
78
+ body: { reason: options.reason ?? 'provider_401', ...(options.staleAccessToken ? { stale_token_hash: await sha256Hex(options.staleAccessToken) } : {}) },
79
+ });
80
+ return remember(t);
81
+ },
82
+ /**
83
+ * A token limited to a subset of the granted scopes, for a less-trusted caller. Not cached and never replaces the
84
+ * connection's own token. Refused with 422 `invalid_scope` or `downscope_unsupported` (the provider cannot narrow).
85
+ */
86
+ downscopeToken(id, scopes) {
87
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/token/downscope`, body: { scopes } });
88
+ },
89
+ /** Read up to 100 connections' tokens in one call. Each id has its own result, so one dead connection does not fail the rest. */
90
+ async tokens(ids, options = {}) {
91
+ const r = await request({
92
+ method: 'POST',
93
+ path: '/v1/connections/tokens/batch',
94
+ body: { ids, ...(options.minTtlSeconds ? { min_ttl_seconds: options.minTtlSeconds } : {}) },
95
+ });
96
+ for (const item of r.data)
97
+ if (item.status === 'ok' && item.token)
98
+ remember(item.token);
99
+ return r;
100
+ },
101
+ /** Bulk-import existing provider refresh tokens (up to 500 per call). Needs the `connections:import` scope. */
102
+ importConnections(body, idempotencyKey) {
103
+ return request({ method: 'POST', path: '/v1/connections/import', body, idempotencyKey });
104
+ },
105
+ /**
106
+ * Export connections. Without `include_secrets` it lists metadata. With it (scope `connections:export_secrets`) the tokens
107
+ * come back as one compact JWE sealed to `recipient_public_key`; open it with the matching private key.
108
+ */
109
+ exportConnections(body = {}) {
110
+ return request({ method: 'POST', path: '/v1/connections/export', body, headers: body.include_secrets ? { 'x-atlas-confirm': 'export-secrets' } : undefined });
111
+ },
112
+ /** Enter the credential of a non-OAuth connection (write-only; sealed in the vault, never returned). */
113
+ setCredentials(id, body) {
114
+ return request({ method: 'PUT', path: `/v1/connections/${(0, request_1.enc)(id)}/credentials`, body });
115
+ },
116
+ /** Rotate the credential; the replaced version stays valid for `overlap_seconds`. */
117
+ rotateCredentials(id, body) {
118
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/credentials/rotate`, body });
119
+ },
120
+ /** The credential's vault versions (numbers and times, never values). */
121
+ secretVersions(id) {
122
+ return request({ method: 'GET', path: `/v1/connections/${(0, request_1.enc)(id)}/credentials/versions` });
123
+ },
124
+ /**
125
+ * Read an api_key, bearer, basic, custom_header or hmac_secret credential. Needs the `connections:secret_read`
126
+ * scope; every read is audited. `version` is `current` (default), `previous` (inside a rotation's overlap
127
+ * window) or a number. With `organizationId` the connection must belong to that organization (404 otherwise).
128
+ */
129
+ secret(id, options = {}) {
130
+ const path = options.organizationId ? `/v1/organizations/${(0, request_1.enc)(options.organizationId)}/connections/${(0, request_1.enc)(id)}/secret` : `/v1/connections/${(0, request_1.enc)(id)}/secret`;
131
+ return request({ method: 'GET', path, query: options.version === undefined ? undefined : { version: String(options.version) } });
132
+ },
133
+ /** Have Atlas sign a request with an oauth1 connection (needs `connections:sign`). */
134
+ oauth1Sign(id, body) {
135
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/oauth1/sign`, body });
136
+ },
137
+ webhooks: {
138
+ /** Verify a provider webhook signature (needs `connections:webhook_verify`). */
139
+ verify(id, body) {
140
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/webhooks/verify`, body });
141
+ },
142
+ createEndpoint(id, body) {
143
+ return request({ method: 'POST', path: `/v1/connections/${(0, request_1.enc)(id)}/webhook_endpoints`, body });
144
+ },
145
+ listEndpoints(id) {
146
+ return request({ method: 'GET', path: `/v1/connections/${(0, request_1.enc)(id)}/webhook_endpoints` });
147
+ },
148
+ updateEndpoint(id, endpointId, body) {
149
+ return request({ method: 'PATCH', path: `/v1/connections/${(0, request_1.enc)(id)}/webhook_endpoints/${(0, request_1.enc)(endpointId)}`, body });
150
+ },
151
+ deleteEndpoint(id, endpointId) {
152
+ return request({ method: 'DELETE', path: `/v1/connections/${(0, request_1.enc)(id)}/webhook_endpoints/${(0, request_1.enc)(endpointId)}` });
153
+ },
154
+ },
155
+ oauthClients: {
156
+ set(body) {
157
+ return request({ method: 'PUT', path: '/v1/connections/oauth_clients', body });
158
+ },
159
+ list(params = {}) {
160
+ return request({ method: 'GET', path: '/v1/connections/oauth_clients', query: { ...params } });
161
+ },
162
+ get(id) {
163
+ return request({ method: 'GET', path: `/v1/connections/oauth_clients/${(0, request_1.enc)(id)}` });
164
+ },
165
+ delete(id) {
166
+ return request({ method: 'DELETE', path: `/v1/connections/oauth_clients/${(0, request_1.enc)(id)}` });
167
+ },
168
+ },
169
+ };
170
+ }
171
+ //# sourceMappingURL=connections.js.map