@atlasauth/backend 0.25.0 → 0.26.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 (60) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/dist/client/abac.d.ts +389 -0
  3. package/dist/client/abac.js +98 -0
  4. package/dist/client/abac.js.map +1 -1
  5. package/dist/client/analytics-reports.d.ts +1 -1
  6. package/dist/client/authz-decisions.d.ts +108 -0
  7. package/dist/client/authz-decisions.js +40 -0
  8. package/dist/client/authz-decisions.js.map +1 -0
  9. package/dist/client/connections.d.ts +507 -0
  10. package/dist/client/connections.js +164 -0
  11. package/dist/client/connections.js.map +1 -0
  12. package/dist/client/custom-oauth-providers.d.ts +15 -0
  13. package/dist/client/custom-oauth-providers.js.map +1 -1
  14. package/dist/client/desktop-mfa.d.ts +104 -0
  15. package/dist/client/desktop-mfa.js +44 -0
  16. package/dist/client/desktop-mfa.js.map +1 -0
  17. package/dist/client/email-templates.d.ts +1 -1
  18. package/dist/client/email-templates.js.map +1 -1
  19. package/dist/client/fga.d.ts +125 -4
  20. package/dist/client/fga.js +40 -0
  21. package/dist/client/fga.js.map +1 -1
  22. package/dist/client/iga.d.ts +436 -0
  23. package/dist/client/iga.js +82 -0
  24. package/dist/client/iga.js.map +1 -0
  25. package/dist/client/index.d.ts +490 -2
  26. package/dist/client/index.js +23 -0
  27. package/dist/client/index.js.map +1 -1
  28. package/dist/client/least-privilege.d.ts +95 -0
  29. package/dist/client/least-privilege.js +28 -0
  30. package/dist/client/least-privilege.js.map +1 -0
  31. package/dist/client/managed-grants.d.ts +52 -0
  32. package/dist/client/managed-grants.js +28 -0
  33. package/dist/client/managed-grants.js.map +1 -0
  34. package/dist/client/mcp-gateways.d.ts +72 -0
  35. package/dist/client/mcp-gateways.js +22 -0
  36. package/dist/client/mcp-gateways.js.map +1 -1
  37. package/dist/client/oauth-clients.d.ts +4 -0
  38. package/dist/client/oauth-clients.js.map +1 -1
  39. package/dist/client/openfga.d.ts +90 -3
  40. package/dist/client/openfga.js +27 -1
  41. package/dist/client/openfga.js.map +1 -1
  42. package/dist/client/policy-bundles.d.ts +105 -0
  43. package/dist/client/policy-bundles.js +38 -0
  44. package/dist/client/policy-bundles.js.map +1 -0
  45. package/dist/client/resources.d.ts +1 -0
  46. package/dist/client/resources.js.map +1 -1
  47. package/dist/client/ssf.d.ts +2 -1
  48. package/dist/client/ssf.js.map +1 -1
  49. package/dist/client/vc.d.ts +8 -0
  50. package/dist/client/vc.js.map +1 -1
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +3 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/policy-bundle.d.ts +110 -0
  55. package/dist/policy-bundle.js +289 -0
  56. package/dist/policy-bundle.js.map +1 -0
  57. package/dist/uma.d.ts +77 -0
  58. package/dist/uma.js +95 -0
  59. package/dist/uma.js.map +1 -0
  60. package/package.json +2 -2
@@ -0,0 +1,108 @@
1
+ import { type RequestFn } from './request';
2
+ /**
3
+ * The authorization decision log: every ABAC, AuthZEN, FGA-check and
4
+ * access-policy decision can be recorded with its (redacted) input, result, the
5
+ * policy revision in force and latency — sampled, shipped as `authz.decision`
6
+ * events to your log streams, and queryable here.
7
+ */
8
+ export type DecisionSource = 'abac' | 'authzen' | 'fga' | 'access_policy' | 'mcp_gateway';
9
+ export interface AuthzDecision {
10
+ object: 'authz_decision';
11
+ id: string;
12
+ source: DecisionSource;
13
+ decision: 'allow' | 'deny';
14
+ /** `Type::id` (ABAC / AuthZEN), the FGA user, or the user id (access policies). */
15
+ principal: string | null;
16
+ /** The action, the FGA relation, or the access-policy stage. */
17
+ action: string | null;
18
+ resource: string | null;
19
+ /** The request as kept by `input_mode`; null when capture keeps none. */
20
+ input: Record<string, unknown> | null;
21
+ /** Reasons (policy names), matched policies, error counts, FGA `allowed` / `cached`. */
22
+ result: Record<string, unknown>;
23
+ /** The signed-bundle revision in force (`rev_…`); access policies carry an `ap_…` digest. */
24
+ policy_revision: string | null;
25
+ /** The exact policy versions or FGA model that evaluated. */
26
+ policy_version: Record<string, unknown> | null;
27
+ latency_ms: number;
28
+ /** The probability this decision was kept at; divide counts by it for the true volume. */
29
+ sample_rate: number;
30
+ actor_id: string | null;
31
+ created_at: number;
32
+ }
33
+ export interface ListAuthzDecisionsParams {
34
+ source?: DecisionSource;
35
+ decision?: 'allow' | 'deny';
36
+ principal?: string;
37
+ action?: string;
38
+ resource?: string;
39
+ policy_revision?: string;
40
+ /** ISO 8601 or epoch milliseconds. */
41
+ since?: string | number;
42
+ until?: string | number;
43
+ /** 1–200; default 50. */
44
+ limit?: number;
45
+ starting_after?: string;
46
+ }
47
+ export interface AuthzDecisionPage {
48
+ object: 'list';
49
+ data: AuthzDecision[];
50
+ has_more: boolean;
51
+ /** Pass as `starting_after` for the next page. */
52
+ next_cursor: string | null;
53
+ }
54
+ export interface AuthzDecisionStats {
55
+ object: 'authz_decision_stats';
56
+ since: number;
57
+ until: number;
58
+ recorded: number;
59
+ /** Recorded decisions scaled back up by their sample rates. */
60
+ estimated_total: number;
61
+ by_source: Record<string, {
62
+ allow: number;
63
+ deny: number;
64
+ estimated_allow: number;
65
+ estimated_deny: number;
66
+ }>;
67
+ latency_ms: {
68
+ p50: number | null;
69
+ p95: number | null;
70
+ p99: number | null;
71
+ max: number | null;
72
+ };
73
+ }
74
+ export interface AuthzDecisionSettings {
75
+ object: 'authz_decision_settings';
76
+ /** Record decisions. Off by default. */
77
+ enabled: boolean;
78
+ /** Probability (0–1) an allow is recorded. */
79
+ sample_rate_allow: number;
80
+ /** Probability (0–1) a deny is recorded. */
81
+ sample_rate_deny: number;
82
+ /** `ids` keeps identifiers only; `full` keeps the request minus `redact`; `none` keeps no input. */
83
+ input_mode: 'ids' | 'full' | 'none';
84
+ /** Dotted paths blanked in `full` mode; `*` matches one segment. */
85
+ redact: string[];
86
+ /** Also emit each recorded decision as an `authz.decision` event. */
87
+ ship_to_events: boolean;
88
+ /** Days to keep decisions; null keeps them. */
89
+ retention_days: number | null;
90
+ }
91
+ export type UpdateAuthzDecisionSettingsBody = Partial<Omit<AuthzDecisionSettings, 'object'>>;
92
+ export declare function authzDecisionsResource(request: RequestFn): {
93
+ /** Query the decision log, newest first. */
94
+ list(params?: ListAuthzDecisionsParams): Promise<AuthzDecisionPage>;
95
+ /** Follow `next_cursor` and yield every matching decision. */
96
+ iterate(params?: Omit<ListAuthzDecisionsParams, "starting_after">): AsyncGenerator<AuthzDecision>;
97
+ get(id: string): Promise<AuthzDecision>;
98
+ /** Counts per engine and outcome, sampling-corrected, with latency percentiles (the last 24 hours by default). */
99
+ stats(params?: {
100
+ since?: string | number;
101
+ until?: string | number;
102
+ }): Promise<AuthzDecisionStats>;
103
+ settings: {
104
+ get(): Promise<AuthzDecisionSettings>;
105
+ /** Fields you omit keep their value. */
106
+ update(body: UpdateAuthzDecisionSettingsBody): Promise<AuthzDecisionSettings>;
107
+ };
108
+ };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authzDecisionsResource = authzDecisionsResource;
4
+ const request_1 = require("./request");
5
+ function authzDecisionsResource(request) {
6
+ return {
7
+ /** Query the decision log, newest first. */
8
+ list(params = {}) {
9
+ return request({ method: 'GET', path: '/v1/authz_decisions', query: { ...params } });
10
+ },
11
+ /** Follow `next_cursor` and yield every matching decision. */
12
+ async *iterate(params = {}) {
13
+ let after;
14
+ for (;;) {
15
+ const page = await this.list({ ...params, starting_after: after });
16
+ yield* page.data;
17
+ if (!page.has_more || !page.next_cursor)
18
+ return;
19
+ after = page.next_cursor;
20
+ }
21
+ },
22
+ get(id) {
23
+ return request({ method: 'GET', path: `/v1/authz_decisions/${(0, request_1.enc)(id)}` });
24
+ },
25
+ /** Counts per engine and outcome, sampling-corrected, with latency percentiles (the last 24 hours by default). */
26
+ stats(params = {}) {
27
+ return request({ method: 'GET', path: '/v1/authz_decisions/stats', query: { ...params } });
28
+ },
29
+ settings: {
30
+ get() {
31
+ return request({ method: 'GET', path: '/v1/authz_decision_settings' });
32
+ },
33
+ /** Fields you omit keep their value. */
34
+ update(body) {
35
+ return request({ method: 'PUT', path: '/v1/authz_decision_settings', body });
36
+ },
37
+ },
38
+ };
39
+ }
40
+ //# sourceMappingURL=authz-decisions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authz-decisions.js","sourceRoot":"","sources":["../../src/client/authz-decisions.ts"],"names":[],"mappings":";;AA0FA,wDAiCC;AA3HD,uCAAgD;AA0FhD,SAAgB,sBAAsB,CAAC,OAAkB;IACvD,OAAO;QACL,4CAA4C;QAC5C,IAAI,CAAC,SAAmC,EAAE;YACxC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,8DAA8D;QAC9D,KAAK,CAAC,CAAC,OAAO,CAAC,SAA2D,EAAE;YAC1E,IAAI,KAAyB,CAAC;YAC9B,SAAS,CAAC;gBACR,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;gBACnE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,OAAO;gBAChD,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,GAAG,CAAC,EAAU;YACZ,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5E,CAAC;QACD,kHAAkH;QAClH,KAAK,CAAC,SAA+D,EAAE;YACrE,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,QAAQ,EAAE;YACR,GAAG;gBACD,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,6BAA6B,EAAE,CAAC,CAAC;YACzE,CAAC;YACD,wCAAwC;YACxC,MAAM,CAAC,IAAqC;gBAC1C,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,6BAA6B,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,507 @@
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
+ /** Read up to 100 connections' tokens in one call. Each id has its own result, so one dead connection does not fail the rest. */
449
+ tokens(ids: string[], options?: {
450
+ minTtlSeconds?: number;
451
+ }): Promise<{
452
+ object: "list";
453
+ data: ConnectionTokenBatchItem[];
454
+ has_more: false;
455
+ }>;
456
+ /** Bulk-import existing provider refresh tokens (up to 500 per call). Needs the `connections:import` scope. */
457
+ importConnections(body: ImportConnectionsBody, idempotencyKey?: string): Promise<ImportConnectionsResult>;
458
+ /**
459
+ * Export connections. Without `include_secrets` it lists metadata. With it (scope `connections:export_secrets`) the tokens
460
+ * come back as one compact JWE sealed to `recipient_public_key`; open it with the matching private key.
461
+ */
462
+ exportConnections(body?: ExportConnectionsBody): Promise<ExportConnectionsResult>;
463
+ /** Enter the credential of a non-OAuth connection (write-only; sealed in the vault, never returned). */
464
+ setCredentials(id: string, body: SetConnectionCredentialsBody): Promise<Connection>;
465
+ /** Rotate the credential; the replaced version stays valid for `overlap_seconds`. */
466
+ rotateCredentials(id: string, body: RotateConnectionCredentialsBody): Promise<Connection>;
467
+ /** The credential's vault versions (numbers and times, never values). */
468
+ secretVersions(id: string): Promise<ConnectionSecretVersions>;
469
+ /**
470
+ * Read an api_key, bearer, basic, custom_header or hmac_secret credential. Needs the `connections:secret_read`
471
+ * scope; every read is audited. `version` is `current` (default), `previous` (inside a rotation's overlap
472
+ * window) or a number. With `organizationId` the connection must belong to that organization (404 otherwise).
473
+ */
474
+ secret(id: string, options?: {
475
+ version?: "current" | "previous" | number;
476
+ organizationId?: string;
477
+ }): Promise<ConnectionSecret>;
478
+ /** Have Atlas sign a request with an oauth1 connection (needs `connections:sign`). */
479
+ oauth1Sign(id: string, body: {
480
+ method?: string;
481
+ url: string;
482
+ body?: string;
483
+ content_type?: string;
484
+ }): Promise<ConnectionSignature>;
485
+ webhooks: {
486
+ /** Verify a provider webhook signature (needs `connections:webhook_verify`). */
487
+ verify(id: string, body: VerifyConnectionWebhookBody): Promise<ConnectionWebhookVerification>;
488
+ createEndpoint(id: string, body: CreateConnectionWebhookEndpointBody): Promise<ConnectionWebhookEndpoint>;
489
+ listEndpoints(id: string): Promise<ListPage<ConnectionWebhookEndpoint>>;
490
+ updateEndpoint(id: string, endpointId: string, body: {
491
+ forward_url?: string;
492
+ enabled?: boolean;
493
+ signing_secret?: string;
494
+ }): Promise<ConnectionWebhookEndpoint>;
495
+ deleteEndpoint(id: string, endpointId: string): Promise<void>;
496
+ };
497
+ oauthClients: {
498
+ set(body: SetConnectionOAuthClientBody): Promise<ConnectionOAuthClient>;
499
+ list(params?: {
500
+ owner_type?: ConnectionOwnerType;
501
+ owner_id?: string;
502
+ provider?: string;
503
+ }): Promise<ListPage<ConnectionOAuthClient>>;
504
+ get(id: string): Promise<ConnectionOAuthClient>;
505
+ delete(id: string): Promise<void>;
506
+ };
507
+ };