@verne-software/sdk 1.2.0 → 1.4.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/README.md +282 -65
- package/dist/index.d.mts +1091 -72
- package/dist/index.d.ts +1091 -72
- package/dist/index.js +938 -83
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +935 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Paginated response wrapper returned by list endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Lists are cursor-paged: pass `next_cursor` back as `cursor` while `has_more` is
|
|
5
|
+
* `true`. `next_cursor` is `null` (or absent) on the last page.
|
|
3
6
|
*/
|
|
4
7
|
interface Paginated<T> {
|
|
5
8
|
data: T[];
|
|
6
9
|
has_more: boolean;
|
|
7
|
-
next_cursor?: string;
|
|
10
|
+
next_cursor?: string | null;
|
|
11
|
+
}
|
|
12
|
+
/** Query parameters shared by every cursor-paged list. */
|
|
13
|
+
interface ListParams {
|
|
14
|
+
/** Items per page, 1 to 100. Defaults to 20; the server clamps values outside the range. */
|
|
15
|
+
limit?: number;
|
|
16
|
+
/** The `next_cursor` of the previous page. Opaque: pass it back, do not parse it. */
|
|
17
|
+
cursor?: string;
|
|
8
18
|
}
|
|
9
19
|
/**
|
|
10
20
|
* Per-request options that can override client defaults.
|
|
@@ -19,23 +29,35 @@ interface RequestOptions {
|
|
|
19
29
|
}
|
|
20
30
|
/**
|
|
21
31
|
* Configuration for the unified Verne client.
|
|
22
|
-
*
|
|
32
|
+
*
|
|
33
|
+
* A Nautilus API key looks like `vrn_…` and carries a set of scopes — the APIs it may
|
|
34
|
+
* call (`relay`, `gate`, `clockwork`, `passepartout`). Pass it once as `apiKey`. The
|
|
35
|
+
* per-service fields are for using a *different* key for one service; they override
|
|
36
|
+
* `apiKey` for that service. Keys created before scopes existed (`vrn_gate_…`,
|
|
37
|
+
* `vrn_relay_…`, …) keep working for the one API they name. There is no test or live
|
|
38
|
+
* mode: every key acts on your real data.
|
|
23
39
|
*/
|
|
24
40
|
interface VerneConfig {
|
|
25
|
-
/** API key for
|
|
41
|
+
/** The API key used for every service that has no key of its own below. */
|
|
42
|
+
apiKey?: string;
|
|
43
|
+
/** Key for Relay (Webhooks-as-a-Service), when it differs from `apiKey`. */
|
|
26
44
|
relay?: string;
|
|
27
|
-
/**
|
|
45
|
+
/** Key for Gate (sign-in and users), when it differs from `apiKey`. */
|
|
28
46
|
gate?: string;
|
|
47
|
+
/** Key for Passepartout (Telegram sign-in), when it differs from `apiKey`. */
|
|
48
|
+
passepartout?: string;
|
|
49
|
+
/** Key for Clockwork (Cron-as-a-Service), when it differs from `apiKey`. */
|
|
50
|
+
clockwork?: string;
|
|
29
51
|
/** Base URL override. Defaults to https://api.vernesoft.com */
|
|
30
52
|
baseUrl?: string;
|
|
31
53
|
/** Default request timeout in milliseconds. Defaults to 30000. */
|
|
32
54
|
timeoutMs?: number;
|
|
33
55
|
}
|
|
34
56
|
/**
|
|
35
|
-
* Configuration for a single-service client (Relay or
|
|
57
|
+
* Configuration for a single-service client (Relay, Gate, Passepartout or Clockwork).
|
|
36
58
|
*/
|
|
37
59
|
interface ServiceConfig {
|
|
38
|
-
/** API key for the service. */
|
|
60
|
+
/** API key (`vrn_…`) with the scope for the service. */
|
|
39
61
|
apiKey: string;
|
|
40
62
|
/** Base URL override. Defaults to https://api.vernesoft.com */
|
|
41
63
|
baseUrl?: string;
|
|
@@ -49,14 +71,19 @@ interface HttpClientConfig {
|
|
|
49
71
|
timeoutMs?: number;
|
|
50
72
|
}
|
|
51
73
|
interface HttpRequestOptions extends RequestOptions {
|
|
52
|
-
/** When true, omit the Authorization header (
|
|
74
|
+
/** When true, omit the Authorization header (calls authenticated by something else). */
|
|
53
75
|
skipAuth?: boolean;
|
|
54
76
|
/** Body to send as JSON. */
|
|
55
77
|
body?: unknown;
|
|
78
|
+
/** Query parameters. `undefined` and `null` values are dropped. */
|
|
79
|
+
query?: QueryParams;
|
|
80
|
+
/** An end user's session token, sent as `X-Session-Token`. */
|
|
81
|
+
sessionToken?: string;
|
|
56
82
|
}
|
|
83
|
+
type QueryParams = Record<string, string | number | boolean | Date | null | undefined>;
|
|
57
84
|
declare class HttpClient {
|
|
58
85
|
private readonly apiKey;
|
|
59
|
-
|
|
86
|
+
readonly baseUrl: string;
|
|
60
87
|
private readonly timeoutMs;
|
|
61
88
|
constructor(config: HttpClientConfig);
|
|
62
89
|
get<T>(path: string, options?: HttpRequestOptions): Promise<T>;
|
|
@@ -67,29 +94,226 @@ declare class HttpClient {
|
|
|
67
94
|
private request;
|
|
68
95
|
}
|
|
69
96
|
|
|
70
|
-
/** A
|
|
97
|
+
/** A recurring HTTP job scheduled on a cron expression. */
|
|
98
|
+
interface CronJob {
|
|
99
|
+
id: string;
|
|
100
|
+
tenant_id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
/** Cron expression, e.g. `'0 * * * *'` (hourly). */
|
|
103
|
+
schedule: string;
|
|
104
|
+
url: string;
|
|
105
|
+
method: string;
|
|
106
|
+
headers: Record<string, string>;
|
|
107
|
+
body: string | null;
|
|
108
|
+
is_active: boolean;
|
|
109
|
+
last_run_at: string | null;
|
|
110
|
+
next_run_at: string | null;
|
|
111
|
+
created_at: string;
|
|
112
|
+
updated_at: string;
|
|
113
|
+
}
|
|
114
|
+
/** Parameters for creating a new cron job. */
|
|
115
|
+
interface CreateCronJobParams {
|
|
116
|
+
name: string;
|
|
117
|
+
/** Cron expression, e.g. `'0 * * * *'` (hourly). */
|
|
118
|
+
schedule: string;
|
|
119
|
+
url: string;
|
|
120
|
+
/** HTTP method to invoke the target URL with. Defaults to `POST`. */
|
|
121
|
+
method?: string;
|
|
122
|
+
headers?: Record<string, string>;
|
|
123
|
+
body?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parameters for updating an existing cron job. All fields are optional —
|
|
127
|
+
* only the fields you provide are changed.
|
|
128
|
+
*/
|
|
129
|
+
interface UpdateCronJobParams {
|
|
130
|
+
name?: string;
|
|
131
|
+
/** Cron expression, e.g. `'0 * * * *'` (hourly). */
|
|
132
|
+
schedule?: string;
|
|
133
|
+
url?: string;
|
|
134
|
+
method?: string;
|
|
135
|
+
headers?: Record<string, string>;
|
|
136
|
+
body?: string;
|
|
137
|
+
is_active?: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** A one-shot HTTP job scheduled to run once at a specific time. */
|
|
140
|
+
interface DelayedJob {
|
|
141
|
+
id: string;
|
|
142
|
+
tenant_id: string;
|
|
143
|
+
name: string;
|
|
144
|
+
/** ISO 8601 timestamp at which the job should fire. */
|
|
145
|
+
run_at: string;
|
|
146
|
+
url: string;
|
|
147
|
+
method: string;
|
|
148
|
+
headers: Record<string, string>;
|
|
149
|
+
body: string | null;
|
|
150
|
+
status: string;
|
|
151
|
+
created_at: string;
|
|
152
|
+
updated_at: string;
|
|
153
|
+
}
|
|
154
|
+
/** Parameters for scheduling a new delayed job. */
|
|
155
|
+
interface CreateDelayedJobParams {
|
|
156
|
+
name: string;
|
|
157
|
+
/** ISO 8601 timestamp at which the job should fire. */
|
|
158
|
+
run_at: string;
|
|
159
|
+
url: string;
|
|
160
|
+
/** HTTP method to invoke the target URL with. Defaults to `POST`. */
|
|
161
|
+
method?: string;
|
|
162
|
+
headers?: Record<string, string>;
|
|
163
|
+
body?: string;
|
|
164
|
+
}
|
|
165
|
+
/** A single execution (run) of a cron or delayed job. */
|
|
166
|
+
interface Execution {
|
|
167
|
+
id: string;
|
|
168
|
+
job_id: string;
|
|
169
|
+
status: string;
|
|
170
|
+
started_at: string;
|
|
171
|
+
completed_at: string | null;
|
|
172
|
+
duration_ms: number | null;
|
|
173
|
+
response_status: number | null;
|
|
174
|
+
response_body: string | null;
|
|
175
|
+
error_message: string | null;
|
|
176
|
+
/** Which attempt of the run this row is, from 1. A retried run has one row per attempt. */
|
|
177
|
+
attempt?: number;
|
|
178
|
+
}
|
|
179
|
+
/** Where the tenant stands against its plan's job limits. `limit` is `null` for no limit. */
|
|
180
|
+
interface ClockworkUsage {
|
|
181
|
+
plan: string;
|
|
182
|
+
tier?: string;
|
|
183
|
+
cron: {
|
|
184
|
+
active: number;
|
|
185
|
+
limit: number | null;
|
|
186
|
+
};
|
|
187
|
+
delayed: {
|
|
188
|
+
pending: number;
|
|
189
|
+
limit: number | null;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
declare class ClockworkDelayedResource {
|
|
194
|
+
private readonly http;
|
|
195
|
+
constructor(http: HttpClient);
|
|
196
|
+
/**
|
|
197
|
+
* Returns all delayed (one-shot) jobs for the current tenant.
|
|
198
|
+
*/
|
|
199
|
+
list(options?: RequestOptions): Promise<DelayedJob[]>;
|
|
200
|
+
/**
|
|
201
|
+
* Schedules a new delayed job to run once at the given `run_at` time.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* const job = await clockwork.delayed.create({
|
|
205
|
+
* name: 'send-reminder',
|
|
206
|
+
* run_at: '2026-01-01T09:00:00Z',
|
|
207
|
+
* url: 'https://example.com/hooks/reminder',
|
|
208
|
+
* });
|
|
209
|
+
*/
|
|
210
|
+
create(params: CreateDelayedJobParams, options?: RequestOptions): Promise<DelayedJob>;
|
|
211
|
+
/**
|
|
212
|
+
* Cancels a pending delayed job. Resolves on `204 No Content`.
|
|
213
|
+
*/
|
|
214
|
+
cancel(jobId: string, options?: RequestOptions): Promise<void>;
|
|
215
|
+
/**
|
|
216
|
+
* Returns the execution history for a delayed job.
|
|
217
|
+
*/
|
|
218
|
+
executions(jobId: string, options?: RequestOptions): Promise<Execution[]>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
declare class ClockworkJobsResource {
|
|
222
|
+
private readonly http;
|
|
223
|
+
constructor(http: HttpClient);
|
|
224
|
+
/**
|
|
225
|
+
* Returns all cron jobs for the current tenant.
|
|
226
|
+
*/
|
|
227
|
+
list(options?: RequestOptions): Promise<CronJob[]>;
|
|
228
|
+
/**
|
|
229
|
+
* Creates a new recurring cron job.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* const job = await clockwork.jobs.create({
|
|
233
|
+
* name: 'nightly-report',
|
|
234
|
+
* schedule: '0 2 * * *',
|
|
235
|
+
* url: 'https://example.com/hooks/report',
|
|
236
|
+
* });
|
|
237
|
+
*/
|
|
238
|
+
create(params: CreateCronJobParams, options?: RequestOptions): Promise<CronJob>;
|
|
239
|
+
/**
|
|
240
|
+
* Partially updates an existing cron job. Only the fields you provide are changed.
|
|
241
|
+
*/
|
|
242
|
+
update(jobId: string, params: UpdateCronJobParams, options?: RequestOptions): Promise<CronJob>;
|
|
243
|
+
/**
|
|
244
|
+
* Deletes a cron job. Resolves on `204 No Content`.
|
|
245
|
+
*/
|
|
246
|
+
delete(jobId: string, options?: RequestOptions): Promise<void>;
|
|
247
|
+
/**
|
|
248
|
+
* Returns the execution history for a cron job (most recent runs first).
|
|
249
|
+
*/
|
|
250
|
+
executions(jobId: string, options?: RequestOptions): Promise<Execution[]>;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
declare class Clockwork {
|
|
254
|
+
readonly jobs: ClockworkJobsResource;
|
|
255
|
+
readonly delayed: ClockworkDelayedResource;
|
|
256
|
+
private readonly http;
|
|
257
|
+
constructor(config: ServiceConfig);
|
|
258
|
+
/**
|
|
259
|
+
* How many jobs exist against the plan's limits. Creating a job over a limit, or
|
|
260
|
+
* resuming a paused one, is refused with `402` (`UPGRADE_REQUIRED` or
|
|
261
|
+
* `JOB_LIMIT_REACHED`) — never retried.
|
|
262
|
+
*/
|
|
263
|
+
usage(options?: RequestOptions): Promise<ClockworkUsage>;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* An end user (a Kratos identity) managed by Gate.
|
|
268
|
+
*
|
|
269
|
+
* The object is the identity service's own; the stable fields are typed and the rest
|
|
270
|
+
* stays reachable through the index signature.
|
|
271
|
+
*/
|
|
71
272
|
interface Identity {
|
|
72
273
|
id: string;
|
|
73
274
|
schema_id: string;
|
|
74
275
|
state: 'active' | 'inactive';
|
|
75
276
|
traits: IdentityTraits;
|
|
277
|
+
created_at?: string;
|
|
278
|
+
updated_at?: string;
|
|
279
|
+
state_changed_at?: string;
|
|
280
|
+
/** Your custom metadata. Read and change it with `identities.getMetadata()` / `updateMetadata()`. */
|
|
281
|
+
metadata_public?: Record<string, unknown> | null;
|
|
282
|
+
verifiable_addresses?: Array<{
|
|
283
|
+
value: string;
|
|
284
|
+
verified: boolean;
|
|
285
|
+
via: string;
|
|
286
|
+
status?: string;
|
|
287
|
+
}>;
|
|
288
|
+
recovery_addresses?: Array<{
|
|
289
|
+
value: string;
|
|
290
|
+
via: string;
|
|
291
|
+
}>;
|
|
292
|
+
[key: string]: unknown;
|
|
76
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* An end user's traits. The `user` schema has exactly two: `email` (required) and
|
|
296
|
+
* `locale`. Application data does not go here — keep it in custom metadata
|
|
297
|
+
* (`identities.updateMetadata()`).
|
|
298
|
+
*/
|
|
77
299
|
interface IdentityTraits {
|
|
78
300
|
email: string;
|
|
79
|
-
|
|
80
|
-
|
|
301
|
+
locale?: string;
|
|
302
|
+
[key: string]: unknown;
|
|
81
303
|
}
|
|
82
304
|
/**
|
|
83
|
-
* Parameters for creating a new identity (end
|
|
84
|
-
* The `traits.tenant_id` is injected automatically by the Edge Gateway.
|
|
305
|
+
* Parameters for creating a new identity (end user) bound to your tenant.
|
|
85
306
|
*/
|
|
86
307
|
interface CreateIdentityParams {
|
|
87
308
|
/** Must be 'user'. */
|
|
88
309
|
schema_id: 'user';
|
|
310
|
+
/**
|
|
311
|
+
* The schema allows only these two traits; anything else is refused with
|
|
312
|
+
* `400 invalid_payload`. Use custom metadata for your own fields.
|
|
313
|
+
*/
|
|
89
314
|
traits: {
|
|
90
315
|
email: string;
|
|
91
|
-
|
|
92
|
-
custom_data?: Record<string, unknown>;
|
|
316
|
+
locale?: string;
|
|
93
317
|
};
|
|
94
318
|
credentials?: {
|
|
95
319
|
password?: {
|
|
@@ -112,9 +336,9 @@ interface JsonPatchOp {
|
|
|
112
336
|
}
|
|
113
337
|
/** Security-related Gate Identity settings for your tenant. */
|
|
114
338
|
interface SecuritySettings {
|
|
115
|
-
/** Whether
|
|
339
|
+
/** Whether sign-in and sign-up by an emailed one-time code is enabled. */
|
|
116
340
|
passwordless_enabled: boolean;
|
|
117
|
-
/** Whether
|
|
341
|
+
/** Whether a second factor (TOTP) is required — enforced by `sessions.check()`. */
|
|
118
342
|
mfa_enabled: boolean;
|
|
119
343
|
}
|
|
120
344
|
/**
|
|
@@ -134,6 +358,37 @@ interface OidcProvider {
|
|
|
134
358
|
* …); pass it straight to your browser-side code to render social buttons.
|
|
135
359
|
*/
|
|
136
360
|
type LoginFlow = Record<string, unknown>;
|
|
361
|
+
/** Optional parameters of `gate.createLoginFlow()`. */
|
|
362
|
+
interface LoginFlowParams {
|
|
363
|
+
/**
|
|
364
|
+
* One of the project's registered return URLs, exactly as registered (see
|
|
365
|
+
* `settings.updateReturnUrls()`). The first one is used when absent.
|
|
366
|
+
*/
|
|
367
|
+
return_to?: string;
|
|
368
|
+
/**
|
|
369
|
+
* An opaque value of yours, 1–256 characters of letters, digits, `-`, `.`, `_`, `~`,
|
|
370
|
+
* returned unchanged on the redirect to your return URL. Always send one and check it.
|
|
371
|
+
*/
|
|
372
|
+
state?: string;
|
|
373
|
+
/** `'aal2'` starts a step-up (second factor) flow; needs `session_token`. */
|
|
374
|
+
aal?: 'aal1' | 'aal2';
|
|
375
|
+
/** The end user's session token, for a step-up flow. Sent as `X-Session-Token`. */
|
|
376
|
+
session_token?: string;
|
|
377
|
+
}
|
|
378
|
+
/** Optional parameters of `gate.createRegistrationFlow()`. */
|
|
379
|
+
interface RegistrationFlowParams {
|
|
380
|
+
/** As for the login flow. */
|
|
381
|
+
return_to?: string;
|
|
382
|
+
/** As for the login flow. */
|
|
383
|
+
state?: string;
|
|
384
|
+
}
|
|
385
|
+
/** What `exchangeOidcCode()` returns: the same shape a password login returns. */
|
|
386
|
+
interface OidcExchangeResult {
|
|
387
|
+
/** The end user's session token. Keep it on your server. */
|
|
388
|
+
session_token: string;
|
|
389
|
+
session: GateSession;
|
|
390
|
+
[key: string]: unknown;
|
|
391
|
+
}
|
|
137
392
|
/** Short-lived access token returned by tokens.create(). */
|
|
138
393
|
interface AccessToken {
|
|
139
394
|
access_token: string;
|
|
@@ -150,43 +405,355 @@ interface CreateTokenParams {
|
|
|
150
405
|
/** Custom lifetime in seconds. Default 3600, max 86400. */
|
|
151
406
|
ttl_seconds?: number;
|
|
152
407
|
}
|
|
153
|
-
/**
|
|
408
|
+
/**
|
|
409
|
+
* One organization a user belongs to: the unit Gate uses everywhere it says who a user
|
|
410
|
+
* is — in introspection, the session check, the signed token's `orgs` claim and
|
|
411
|
+
* `identities.listOrganizations()`.
|
|
412
|
+
*/
|
|
413
|
+
interface OrgClaim {
|
|
414
|
+
/** The organization's id. */
|
|
415
|
+
id: string;
|
|
416
|
+
/** The name of the role the user holds there. */
|
|
417
|
+
role: string;
|
|
418
|
+
/** That role's permissions, e.g. `'invoices:write'`. */
|
|
419
|
+
permissions: string[];
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Result of token introspection.
|
|
423
|
+
*
|
|
424
|
+
* An inactive token (unknown, expired, another tenant's, or its user deactivated or
|
|
425
|
+
* deleted) is `{ active: false }` and nothing else.
|
|
426
|
+
*/
|
|
154
427
|
interface IntrospectResult {
|
|
155
428
|
active: boolean;
|
|
156
|
-
subject
|
|
157
|
-
tenant_id
|
|
158
|
-
scopes
|
|
159
|
-
expires_at
|
|
429
|
+
subject?: string;
|
|
430
|
+
tenant_id?: string;
|
|
431
|
+
scopes?: string[];
|
|
432
|
+
expires_at?: string;
|
|
433
|
+
/**
|
|
434
|
+
* When `subject` is an end user's id: their organizations in the key's project, read
|
|
435
|
+
* live, the first 100 in the order they joined. Absent for any other subject.
|
|
436
|
+
*/
|
|
437
|
+
orgs?: OrgClaim[];
|
|
438
|
+
/** `true`, and only then, when there are more than `orgs` shows. */
|
|
439
|
+
orgs_truncated?: boolean;
|
|
160
440
|
}
|
|
161
441
|
/** Parameters for checking whether a subject can perform an action. */
|
|
162
442
|
interface AuthorizeParams {
|
|
163
|
-
/**
|
|
443
|
+
/** The end user's identity id. */
|
|
164
444
|
subject: string;
|
|
165
|
-
/**
|
|
445
|
+
/**
|
|
446
|
+
* For an organization resource: the permission to check, e.g. `'invoices:write'`.
|
|
447
|
+
* Otherwise a label for your own records.
|
|
448
|
+
*/
|
|
166
449
|
action: string;
|
|
167
|
-
/**
|
|
450
|
+
/**
|
|
451
|
+
* `'organization:<uuid>'` to check a permission in an organization (prefer
|
|
452
|
+
* `organizations.authorize()` / `can()`, which build it); anything else asks only
|
|
453
|
+
* whether `subject` is one of your active end users.
|
|
454
|
+
*/
|
|
168
455
|
resource: string;
|
|
169
|
-
/**
|
|
456
|
+
/** Accepted and ignored by the API today. */
|
|
170
457
|
context?: Record<string, unknown>;
|
|
171
458
|
}
|
|
459
|
+
/** Why an organization permission check answered as it did. */
|
|
460
|
+
type OrganizationAuthorizeReason = 'member_with_permission' | 'member_without_permission' | 'not_a_member' | 'subject_inactive' | 'no_such_organization';
|
|
461
|
+
/**
|
|
462
|
+
* Why a check on any resource that is not an organization answered as it did — the only
|
|
463
|
+
* question it asks is *is `subject` one of your active end users?* `owned_by_tenant` is
|
|
464
|
+
* the one `allowed: true` answer.
|
|
465
|
+
*/
|
|
466
|
+
type OwnershipAuthorizeReason = 'owned_by_tenant' | 'subject_inactive' | 'not_owned_by_tenant' | 'not_a_known_identity';
|
|
172
467
|
/** Authorization decision returned by gate.authorize(). */
|
|
173
468
|
interface AuthorizeResult {
|
|
174
469
|
allowed: boolean;
|
|
470
|
+
/** Identifies the decision in Gate's logs, for support. */
|
|
175
471
|
decision_id: string;
|
|
176
|
-
|
|
472
|
+
/**
|
|
473
|
+
* A code to branch on: one of {@link OrganizationAuthorizeReason} for an organization
|
|
474
|
+
* resource, one of {@link OwnershipAuthorizeReason} for any other. The set is open —
|
|
475
|
+
* treat an unknown value as a denial.
|
|
476
|
+
*/
|
|
477
|
+
reason: OrganizationAuthorizeReason | OwnershipAuthorizeReason | (string & {});
|
|
478
|
+
/**
|
|
479
|
+
* For a resource that is not an organization: the decision as a sentence, for your
|
|
480
|
+
* logs. Its wording can change; only `reason` is a contract. Absent for an
|
|
481
|
+
* organization decision.
|
|
482
|
+
*/
|
|
483
|
+
message?: string;
|
|
484
|
+
/**
|
|
485
|
+
* The role the user holds in the organization — present for
|
|
486
|
+
* `member_with_permission`, `member_without_permission` and `subject_inactive`.
|
|
487
|
+
*/
|
|
488
|
+
role?: string;
|
|
489
|
+
}
|
|
490
|
+
/** What `tokens.createSigned()` returns. */
|
|
491
|
+
interface SignedToken {
|
|
492
|
+
/** The compact ES256 JWT. Valid for 15 minutes; it cannot be revoked. */
|
|
493
|
+
token: string;
|
|
494
|
+
/** The session the token was made from, as `whoami` returns it. */
|
|
495
|
+
session: GateSession;
|
|
496
|
+
}
|
|
497
|
+
/** The verified payload of a Gate signed token. */
|
|
498
|
+
interface SignedTokenClaims {
|
|
499
|
+
/** `<base URL>/auth/<tenant id>` — checked by the verifier. */
|
|
500
|
+
iss: string;
|
|
501
|
+
/** The end user's identity id. */
|
|
502
|
+
sub: string;
|
|
503
|
+
/** The session the token was made from (revocable with `sessions.revoke()`). */
|
|
504
|
+
sid: string;
|
|
505
|
+
tenant_id: string;
|
|
506
|
+
schema_id: string;
|
|
507
|
+
email: string | null;
|
|
508
|
+
/** Always `'authenticated'` (the database role PostgREST-style consumers use). */
|
|
509
|
+
role: string;
|
|
510
|
+
/** The user's organizations across all your projects, as of when the token was made. */
|
|
511
|
+
orgs: OrgClaim[];
|
|
512
|
+
/** `true` when `orgs` is incomplete; list them with `identities.listOrganizations()`. */
|
|
513
|
+
orgs_truncated?: boolean;
|
|
514
|
+
iat: number;
|
|
515
|
+
nbf: number;
|
|
516
|
+
exp: number;
|
|
517
|
+
jti: string;
|
|
518
|
+
[claim: string]: unknown;
|
|
519
|
+
}
|
|
520
|
+
/** Options of `tokens.verifySigned()`. */
|
|
521
|
+
interface VerifySignedOptions {
|
|
522
|
+
/** Your tenant id: the issuer is built from it. */
|
|
523
|
+
tenantId: string;
|
|
524
|
+
/** Allowed clock skew in seconds for `exp` and `nbf`. Default 10. */
|
|
525
|
+
clockToleranceSeconds?: number;
|
|
526
|
+
}
|
|
527
|
+
/** An end user's session, as the identity service returns it. */
|
|
528
|
+
interface GateSession {
|
|
529
|
+
id: string;
|
|
530
|
+
active?: boolean;
|
|
531
|
+
authenticated_at?: string;
|
|
532
|
+
expires_at?: string;
|
|
533
|
+
issued_at?: string;
|
|
534
|
+
authenticator_assurance_level?: string;
|
|
535
|
+
authentication_methods?: Array<{
|
|
536
|
+
method: string;
|
|
537
|
+
completed_at?: string;
|
|
538
|
+
[key: string]: unknown;
|
|
539
|
+
}>;
|
|
540
|
+
devices?: Array<{
|
|
541
|
+
id?: string;
|
|
542
|
+
ip_address?: string;
|
|
543
|
+
user_agent?: string;
|
|
544
|
+
location?: string;
|
|
545
|
+
}>;
|
|
546
|
+
identity?: Record<string, unknown>;
|
|
547
|
+
[key: string]: unknown;
|
|
548
|
+
}
|
|
549
|
+
/** The answer of `sessions.check()` — whether a session is good enough to act on. */
|
|
550
|
+
interface SessionCheck {
|
|
551
|
+
active: boolean;
|
|
552
|
+
/** `'aal1'` or `'aal2'`. */
|
|
553
|
+
aal: string;
|
|
554
|
+
/** Whether your tenant requires a second factor. */
|
|
555
|
+
mfa_required: boolean;
|
|
556
|
+
/** Whether this session meets what your tenant requires — the one field to gate on. */
|
|
557
|
+
mfa_satisfied: boolean;
|
|
558
|
+
identity_id: string | null;
|
|
559
|
+
/** The user's organizations in the key's project, read now (first 100). */
|
|
560
|
+
orgs?: OrgClaim[];
|
|
561
|
+
orgs_truncated?: boolean;
|
|
562
|
+
}
|
|
563
|
+
/** A group of your end users (a customer's team, workspace, company). */
|
|
564
|
+
interface Organization {
|
|
565
|
+
id: string;
|
|
566
|
+
/** Free text, 1–120 characters, not unique. */
|
|
567
|
+
name: string;
|
|
568
|
+
created_at: string;
|
|
569
|
+
updated_at: string;
|
|
570
|
+
}
|
|
571
|
+
interface CreateOrganizationParams {
|
|
572
|
+
name: string;
|
|
573
|
+
}
|
|
574
|
+
interface UpdateOrganizationParams {
|
|
575
|
+
name: string;
|
|
576
|
+
}
|
|
577
|
+
/** A named set of permissions inside one organization. */
|
|
578
|
+
interface Role {
|
|
579
|
+
id: string;
|
|
580
|
+
organization_id: string;
|
|
581
|
+
/** Lowercase letters, digits, `_` and `-`; unique in the organization. */
|
|
582
|
+
name: string;
|
|
583
|
+
/** Sorted and de-duplicated by the API. */
|
|
584
|
+
permissions: string[];
|
|
585
|
+
created_at: string;
|
|
586
|
+
updated_at: string;
|
|
587
|
+
}
|
|
588
|
+
interface CreateRoleParams {
|
|
589
|
+
/** 1–64 characters: lowercase letters, digits, `_`, `-`, starting with a letter or digit. */
|
|
590
|
+
name: string;
|
|
591
|
+
/** Lowercase segments joined by `:`, e.g. `'invoices:write'`. `*` and `nautilus:` are reserved. */
|
|
592
|
+
permissions?: string[];
|
|
593
|
+
}
|
|
594
|
+
interface UpdateRoleParams {
|
|
595
|
+
name?: string;
|
|
596
|
+
/** Replaces the whole set. Everyone holding the role has the new set at once. */
|
|
597
|
+
permissions?: string[];
|
|
598
|
+
}
|
|
599
|
+
/** An end user's membership of an organization. */
|
|
600
|
+
interface Member {
|
|
601
|
+
organization_id: string;
|
|
602
|
+
identity_id: string;
|
|
603
|
+
role_id: string;
|
|
604
|
+
/** When the membership ends, or `null` for never. */
|
|
605
|
+
expires_at: string | null;
|
|
606
|
+
created_at: string;
|
|
607
|
+
updated_at: string;
|
|
608
|
+
}
|
|
609
|
+
interface AddMemberParams {
|
|
610
|
+
/** One of your end users. */
|
|
611
|
+
identity_id: string;
|
|
612
|
+
/** A role of this organization. */
|
|
613
|
+
role_id: string;
|
|
614
|
+
/** A future time (at most 10 years ahead) when the membership ends. */
|
|
615
|
+
expires_at?: string | Date | null;
|
|
616
|
+
}
|
|
617
|
+
interface UpdateMemberParams {
|
|
618
|
+
/** Move the member to another role of this organization. */
|
|
619
|
+
role_id?: string;
|
|
620
|
+
/** Leave it out to keep the deadline, `null` to remove it, a time to set it. */
|
|
621
|
+
expires_at?: string | Date | null;
|
|
622
|
+
}
|
|
623
|
+
type AuditActorType = 'team_member' | 'api_key' | 'end_user' | 'system' | 'staff';
|
|
624
|
+
/** Filters of `auditLog.list()`. */
|
|
625
|
+
interface ListAuditLogParams extends ListParams {
|
|
626
|
+
/** One action, e.g. `'key.created'`, `'identity.login'`, `'organization.member_added'`. */
|
|
627
|
+
action?: string;
|
|
628
|
+
actor_id?: string;
|
|
629
|
+
actor_type?: AuditActorType;
|
|
630
|
+
target_id?: string;
|
|
631
|
+
/** Entries at or after this instant. */
|
|
632
|
+
from?: string | Date;
|
|
633
|
+
/** Entries before this instant. Must be later than `from`. */
|
|
634
|
+
to?: string | Date;
|
|
635
|
+
}
|
|
636
|
+
/** One entry of the audit log. */
|
|
637
|
+
interface AuditLogEntry {
|
|
638
|
+
id: string;
|
|
639
|
+
occurred_at: string;
|
|
640
|
+
/** Open set: new actions are added over time. */
|
|
641
|
+
action: string;
|
|
642
|
+
actor: {
|
|
643
|
+
type: AuditActorType | 'unknown' | (string & {});
|
|
644
|
+
id: string | null;
|
|
645
|
+
};
|
|
646
|
+
target: {
|
|
647
|
+
type: string;
|
|
648
|
+
id: string;
|
|
649
|
+
} | null;
|
|
650
|
+
project_id: string | null;
|
|
651
|
+
details: Record<string, unknown>;
|
|
652
|
+
ip: string | null;
|
|
653
|
+
user_agent: string | null;
|
|
654
|
+
}
|
|
655
|
+
type LifecycleRuleKind = 'delete_unverified' | 'remind_unverified' | 'expire_roles' | 'delete_inactive';
|
|
656
|
+
/** Settings of each rule kind. */
|
|
657
|
+
interface LifecycleRuleParamsByKind {
|
|
658
|
+
delete_unverified: {
|
|
659
|
+
delete_after_days: number;
|
|
660
|
+
warn_before_days: number;
|
|
661
|
+
};
|
|
662
|
+
remind_unverified: {
|
|
663
|
+
remind_after_hours: number;
|
|
664
|
+
};
|
|
665
|
+
expire_roles: Record<string, never>;
|
|
666
|
+
delete_inactive: {
|
|
667
|
+
inactive_after_months: number;
|
|
668
|
+
warn_before_days: number;
|
|
669
|
+
include_without_address?: boolean;
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
interface LifecycleRule {
|
|
673
|
+
kind: LifecycleRuleKind;
|
|
674
|
+
configured: boolean;
|
|
675
|
+
enabled: boolean;
|
|
676
|
+
params: Record<string, unknown> | null;
|
|
677
|
+
/** Whether your plan includes the rule. */
|
|
678
|
+
available: boolean;
|
|
679
|
+
/** `'plan'` when a plan change switched the rule off. */
|
|
680
|
+
disabled_reason: 'plan' | null;
|
|
681
|
+
enabled_at: string | null;
|
|
682
|
+
updated_at: string | null;
|
|
683
|
+
/** How many people have something scheduled by this rule. */
|
|
684
|
+
pending: number;
|
|
685
|
+
}
|
|
686
|
+
interface LifecycleRules {
|
|
687
|
+
/** Your plan: `free`, `pro`, `advanced` or `contract`. */
|
|
688
|
+
tier: string;
|
|
689
|
+
/** All four kinds, set up or not. */
|
|
690
|
+
rules: LifecycleRule[];
|
|
691
|
+
}
|
|
692
|
+
interface SetLifecycleRuleParams<K extends LifecycleRuleKind = LifecycleRuleKind> {
|
|
693
|
+
enabled: boolean;
|
|
694
|
+
/** Leave out to keep the saved settings. Required on a first write (except `expire_roles`). */
|
|
695
|
+
params?: LifecycleRuleParamsByKind[K];
|
|
696
|
+
}
|
|
697
|
+
interface LifecycleRulePreview {
|
|
698
|
+
kind: LifecycleRuleKind;
|
|
699
|
+
available: boolean;
|
|
700
|
+
/** How many people the rule would schedule right now. */
|
|
701
|
+
matching_now: number;
|
|
702
|
+
/** `true` when the count stopped at 1,000. */
|
|
703
|
+
capped: boolean;
|
|
704
|
+
}
|
|
705
|
+
interface ListLifecycleActionsParams extends ListParams {
|
|
706
|
+
status?: 'pending' | 'done' | 'cancelled' | 'failed';
|
|
707
|
+
kind?: LifecycleRuleKind;
|
|
708
|
+
identity_id?: string;
|
|
709
|
+
}
|
|
710
|
+
interface LifecycleAction {
|
|
711
|
+
id: string;
|
|
712
|
+
kind: LifecycleRuleKind;
|
|
713
|
+
step: 'remind' | 'warn' | 'delete' | 'revoke';
|
|
714
|
+
identity_id: string;
|
|
715
|
+
status: 'pending' | 'done' | 'cancelled' | 'failed';
|
|
716
|
+
basis_at: string;
|
|
717
|
+
due_at: string;
|
|
718
|
+
/** Why it was cancelled or failed (`rule_disabled`, `verified`, `signed_in`, …). */
|
|
719
|
+
reason: string | null;
|
|
720
|
+
created_at: string;
|
|
721
|
+
finished_at: string | null;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* The account's audit log, read-only: who did what, to what, when and from where. The
|
|
726
|
+
* key reads its own project's entries and the account-wide ones.
|
|
727
|
+
*
|
|
728
|
+
* Any key with the `gate` scope reads the whole log, including the IP addresses and
|
|
729
|
+
* user agents of your team members. Keep `gate` keys on your backend.
|
|
730
|
+
*/
|
|
731
|
+
declare class AuditLogResource {
|
|
732
|
+
private readonly http;
|
|
733
|
+
constructor(http: HttpClient);
|
|
734
|
+
/**
|
|
735
|
+
* One page of entries, newest first. Filters combine; keep the same filters while
|
|
736
|
+
* paging with `cursor`.
|
|
737
|
+
*
|
|
738
|
+
* @example
|
|
739
|
+
* const page = await gate.auditLog.list({ action: 'identity.login', actor_id: userId });
|
|
740
|
+
*/
|
|
741
|
+
list(params?: ListAuditLogParams, options?: RequestOptions): Promise<Paginated<AuditLogEntry>>;
|
|
177
742
|
}
|
|
178
743
|
|
|
179
744
|
declare class IdentitiesResource {
|
|
180
745
|
private readonly http;
|
|
181
746
|
constructor(http: HttpClient);
|
|
182
747
|
/**
|
|
183
|
-
* Creates a new identity (end
|
|
184
|
-
*
|
|
748
|
+
* Creates a new identity (end user) bound to your tenant. Answers `201`.
|
|
749
|
+
*
|
|
750
|
+
* A `409 conflict` means you already have an end user with this address; the same
|
|
751
|
+
* address at another tenant is a different person and does not conflict. Traits are
|
|
752
|
+
* `email` and `locale` only — keep your own fields in custom metadata.
|
|
185
753
|
*/
|
|
186
754
|
create(params: CreateIdentityParams, options?: RequestOptions): Promise<Identity>;
|
|
187
755
|
/**
|
|
188
|
-
* Returns an identity by ID.
|
|
189
|
-
* The Gateway will reject the request if the identity does not belong to your tenant.
|
|
756
|
+
* Returns an identity by ID. An identity of another tenant is refused.
|
|
190
757
|
*/
|
|
191
758
|
get(identityId: string, options?: RequestOptions): Promise<Identity>;
|
|
192
759
|
/**
|
|
@@ -194,19 +761,19 @@ declare class IdentitiesResource {
|
|
|
194
761
|
*
|
|
195
762
|
* @example
|
|
196
763
|
* await gate.identities.patch('identity_123', [
|
|
197
|
-
* { op: 'replace', path: '/traits/
|
|
764
|
+
* { op: 'replace', path: '/traits/email', value: 'new@example.com' },
|
|
198
765
|
* ]);
|
|
199
766
|
*/
|
|
200
767
|
patch(identityId: string, ops: JsonPatchOp[], options?: RequestOptions): Promise<Identity>;
|
|
201
768
|
/**
|
|
202
|
-
* Deletes an identity
|
|
203
|
-
* The Gateway will reject the request if the identity does not belong to your tenant.
|
|
769
|
+
* Deletes an identity, its sessions and its memberships. Fires `identity.deleted`.
|
|
204
770
|
*/
|
|
205
771
|
delete(identityId: string, options?: RequestOptions): Promise<void>;
|
|
206
772
|
/**
|
|
207
|
-
* Activates or deactivates an identity. An `inactive` identity cannot
|
|
208
|
-
*
|
|
209
|
-
*
|
|
773
|
+
* Activates or deactivates an identity. An `inactive` identity cannot sign in, its
|
|
774
|
+
* sessions stop working (until it is active again), its access tokens introspect as
|
|
775
|
+
* `active: false`, and no signed token is issued for it. Nothing is deleted. Fires the
|
|
776
|
+
* `identity.state_changed` webhook event.
|
|
210
777
|
*
|
|
211
778
|
* @example
|
|
212
779
|
* await gate.identities.setState('identity_123', 'inactive');
|
|
@@ -222,13 +789,178 @@ declare class IdentitiesResource {
|
|
|
222
789
|
* a fresh verification email. Resolves on `204 No Content`.
|
|
223
790
|
*/
|
|
224
791
|
resendVerification(identityId: string, options?: RequestOptions): Promise<void>;
|
|
792
|
+
/**
|
|
793
|
+
* Reads an identity's custom metadata (`metadata_public`) — the place for your own
|
|
794
|
+
* fields about a user. `{}` when nothing is set.
|
|
795
|
+
*/
|
|
796
|
+
getMetadata(identityId: string, options?: RequestOptions): Promise<Record<string, unknown>>;
|
|
797
|
+
/**
|
|
798
|
+
* Merges `patch` into an identity's custom metadata and returns the result. Keys you
|
|
799
|
+
* leave out are kept; a key set to `null` is removed.
|
|
800
|
+
*
|
|
801
|
+
* @example
|
|
802
|
+
* await gate.identities.updateMetadata(id, { plan: 'pro', seats: null });
|
|
803
|
+
*/
|
|
804
|
+
updateMetadata(identityId: string, patch: Record<string, unknown>, options?: RequestOptions): Promise<Record<string, unknown>>;
|
|
805
|
+
/**
|
|
806
|
+
* The organizations of the key's project that an end user belongs to, with the role
|
|
807
|
+
* held in each and its permissions — live, oldest membership first, cursor-paged. This
|
|
808
|
+
* is the complete list that `orgs_truncated: true` (in a token, an introspection or a
|
|
809
|
+
* session check) points to.
|
|
810
|
+
*/
|
|
811
|
+
listOrganizations(identityId: string, params?: ListParams, options?: RequestOptions): Promise<Paginated<OrgClaim>>;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Automatic deletion of unconfirmed and inactive accounts, and removal of expired roles —
|
|
816
|
+
* four rules per project, all off until you switch them on. Only `delete_unverified` is
|
|
817
|
+
* in the Free plan; switching on another is `403 plan_required`.
|
|
818
|
+
*/
|
|
819
|
+
declare class LifecycleResource {
|
|
820
|
+
private readonly http;
|
|
821
|
+
constructor(http: HttpClient);
|
|
822
|
+
/** All four rules of the key's project, set up or not, and the plan. */
|
|
823
|
+
listRules(options?: RequestOptions): Promise<LifecycleRules>;
|
|
824
|
+
/**
|
|
825
|
+
* Creates, changes, or switches a rule on or off. Leave `params` out to keep the saved
|
|
826
|
+
* settings. Switching off or changing settings cancels what the rule had scheduled.
|
|
827
|
+
*
|
|
828
|
+
* @example
|
|
829
|
+
* await gate.lifecycle.setRule('delete_unverified', {
|
|
830
|
+
* enabled: true,
|
|
831
|
+
* params: { delete_after_days: 14, warn_before_days: 3 },
|
|
832
|
+
* });
|
|
833
|
+
*/
|
|
834
|
+
setRule<K extends LifecycleRuleKind>(kind: K, params: SetLifecycleRuleParams<K>, options?: RequestOptions): Promise<LifecycleRule>;
|
|
835
|
+
/** Removes a rule and cancels what it scheduled. Succeeds also when there was none. */
|
|
836
|
+
deleteRule(kind: LifecycleRuleKind, options?: RequestOptions): Promise<void>;
|
|
837
|
+
/**
|
|
838
|
+
* How many people a rule with these settings would affect right now. Writes nothing;
|
|
839
|
+
* works whether or not the rule is on or in your plan. `expire_roles` takes `{}`.
|
|
840
|
+
*/
|
|
841
|
+
previewRule<K extends LifecycleRuleKind>(kind: K, params: LifecycleRuleParamsByKind[K], options?: RequestOptions): Promise<LifecycleRulePreview>;
|
|
842
|
+
/** What the rules have scheduled and done, oldest first, cursor-paged. */
|
|
843
|
+
listActions(params?: ListLifecycleActionsParams, options?: RequestOptions): Promise<Paginated<LifecycleAction>>;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Organizations of your end users — their teams, workspaces, companies — with named
|
|
848
|
+
* roles and members. Everything here acts on **the project the API key belongs to**.
|
|
849
|
+
*
|
|
850
|
+
* Gate keeps the data and reports it (introspection, the session check, the signed
|
|
851
|
+
* token's `orgs` claim); it does not enforce permissions. Ask with {@link can}.
|
|
852
|
+
*/
|
|
853
|
+
declare class OrganizationsResource {
|
|
854
|
+
private readonly http;
|
|
855
|
+
readonly roles: RolesResource;
|
|
856
|
+
readonly members: MembersResource;
|
|
857
|
+
constructor(http: HttpClient);
|
|
858
|
+
/** Creates an organization. `name` is free text, 1–120 characters, not unique. */
|
|
859
|
+
create(params: CreateOrganizationParams, options?: RequestOptions): Promise<Organization>;
|
|
860
|
+
/** Lists the project's organizations, oldest first, cursor-paged. */
|
|
861
|
+
list(params?: ListParams, options?: RequestOptions): Promise<Paginated<Organization>>;
|
|
862
|
+
get(orgId: string, options?: RequestOptions): Promise<Organization>;
|
|
863
|
+
/** Renames an organization. */
|
|
864
|
+
update(orgId: string, params: UpdateOrganizationParams, options?: RequestOptions): Promise<Organization>;
|
|
865
|
+
/** Deletes an organization with its roles and memberships. */
|
|
866
|
+
delete(orgId: string, options?: RequestOptions): Promise<void>;
|
|
867
|
+
/**
|
|
868
|
+
* *May this end user do this in this organization?* — answered from the role the user
|
|
869
|
+
* holds there and its permissions, as they are now. `permission` must match exactly
|
|
870
|
+
* (no wildcards). An organization of another project looks like a missing one
|
|
871
|
+
* (`no_such_organization`). An invalid permission (upper case, `*`, the `nautilus:`
|
|
872
|
+
* prefix) is a `400` error, never `allowed: false`. Not billed, not audited.
|
|
873
|
+
*/
|
|
874
|
+
authorize(orgId: string, identityId: string, permission: string, options?: RequestOptions): Promise<AuthorizeResult>;
|
|
875
|
+
/**
|
|
876
|
+
* `true` when the end user holds `permission` in the organization — the boolean of
|
|
877
|
+
* {@link authorize}. Errors are thrown, not turned into `false`.
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* if (!(await gate.organizations.can(orgId, userId, 'invoices:write'))) {
|
|
881
|
+
* throw new Error('Forbidden');
|
|
882
|
+
* }
|
|
883
|
+
*/
|
|
884
|
+
can(orgId: string, identityId: string, permission: string, options?: RequestOptions): Promise<boolean>;
|
|
885
|
+
}
|
|
886
|
+
/** Roles of one organization: named sets of permissions. */
|
|
887
|
+
declare class RolesResource {
|
|
888
|
+
private readonly http;
|
|
889
|
+
constructor(http: HttpClient);
|
|
890
|
+
/**
|
|
891
|
+
* Defines a role. `409 conflict` if the name is taken in the organization,
|
|
892
|
+
* `409 limit_reached` past 100 roles.
|
|
893
|
+
*/
|
|
894
|
+
create(orgId: string, params: CreateRoleParams, options?: RequestOptions): Promise<Role>;
|
|
895
|
+
list(orgId: string, params?: ListParams, options?: RequestOptions): Promise<Paginated<Role>>;
|
|
896
|
+
get(orgId: string, roleId: string, options?: RequestOptions): Promise<Role>;
|
|
897
|
+
/**
|
|
898
|
+
* Renames a role and/or **replaces** its permissions. Everyone who holds it has the new
|
|
899
|
+
* permissions the next time they are read.
|
|
900
|
+
*/
|
|
901
|
+
update(orgId: string, roleId: string, params: UpdateRoleParams, options?: RequestOptions): Promise<Role>;
|
|
902
|
+
/** Deletes a role. A role someone holds is refused with `409 conflict`. */
|
|
903
|
+
delete(orgId: string, roleId: string, options?: RequestOptions): Promise<void>;
|
|
904
|
+
}
|
|
905
|
+
/** Members of one organization: end users holding one role each. */
|
|
906
|
+
declare class MembersResource {
|
|
907
|
+
private readonly http;
|
|
908
|
+
constructor(http: HttpClient);
|
|
909
|
+
/**
|
|
910
|
+
* Gives an end user a role in the organization. `404` if the identity is not one of
|
|
911
|
+
* your end users, `409` if they already are a member (change the role with
|
|
912
|
+
* {@link update}).
|
|
913
|
+
*/
|
|
914
|
+
add(orgId: string, params: AddMemberParams, options?: RequestOptions): Promise<Member>;
|
|
915
|
+
list(orgId: string, params?: ListParams, options?: RequestOptions): Promise<Paginated<Member>>;
|
|
916
|
+
/**
|
|
917
|
+
* Changes a member's role and/or deadline. `expires_at`: leave it out to keep the
|
|
918
|
+
* deadline, `null` to remove it, a time to set it.
|
|
919
|
+
*/
|
|
920
|
+
update(orgId: string, identityId: string, params: UpdateMemberParams, options?: RequestOptions): Promise<Member>;
|
|
921
|
+
/** Removes the membership. The person stays your end user. */
|
|
922
|
+
remove(orgId: string, identityId: string, options?: RequestOptions): Promise<void>;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/** End users' sessions: list, revoke, and check one is good enough to act on. */
|
|
926
|
+
declare class SessionsResource {
|
|
927
|
+
private readonly http;
|
|
928
|
+
constructor(http: HttpClient);
|
|
929
|
+
/** The active sessions of one of your end users (a bare array, not paged). */
|
|
930
|
+
list(identityId: string, options?: RequestOptions): Promise<GateSession[]>;
|
|
931
|
+
/**
|
|
932
|
+
* Revokes every session of an end user — "log out everywhere". Signed tokens already
|
|
933
|
+
* issued keep verifying until their own `exp` (at most 15 minutes).
|
|
934
|
+
*
|
|
935
|
+
* Idempotent: a user of yours with no session at all is a success too. An id that is not
|
|
936
|
+
* one of your users — another account's, unknown, or one you deleted — is
|
|
937
|
+
* `403 forbidden`. `404 not_found` is rare: a user removed from the identity service
|
|
938
|
+
* other than through `identities.delete()`, which Gate still remembered as yours.
|
|
939
|
+
*/
|
|
940
|
+
revokeAll(identityId: string, options?: RequestOptions): Promise<void>;
|
|
941
|
+
/**
|
|
942
|
+
* Revokes one session by its id. Revoking an already revoked session of your user is a
|
|
943
|
+
* success too; an id that is not one of your users' sessions is `404`.
|
|
944
|
+
*/
|
|
945
|
+
revoke(sessionId: string, options?: RequestOptions): Promise<void>;
|
|
946
|
+
/**
|
|
947
|
+
* Whether an end user's session meets what your tenant requires — the one call to
|
|
948
|
+
* gate your own routes on. Gate on `mfa_satisfied`. Also lists the user's
|
|
949
|
+
* organizations in the key's project, read now.
|
|
950
|
+
*
|
|
951
|
+
* Throws `VerneAPIError` with `status 401` for a dead, foreign or unknown session, and
|
|
952
|
+
* `code 'mfa_required'` (`403`) when a second factor is owed: start a step-up flow with
|
|
953
|
+
* `gate.createLoginFlow({ aal: 'aal2', session_token })`.
|
|
954
|
+
*/
|
|
955
|
+
check(sessionToken: string, options?: RequestOptions): Promise<SessionCheck>;
|
|
225
956
|
}
|
|
226
957
|
|
|
227
958
|
declare class SettingsResource {
|
|
228
959
|
private readonly http;
|
|
229
960
|
constructor(http: HttpClient);
|
|
230
961
|
/**
|
|
231
|
-
* Returns the tenant's security settings (passwordless / MFA).
|
|
962
|
+
* Returns the tenant's security settings (passwordless / MFA). With `mfa_enabled`,
|
|
963
|
+
* `sessions.check()` refuses a session without a second factor (`403 mfa_required`).
|
|
232
964
|
*/
|
|
233
965
|
getSecurity(options?: RequestOptions): Promise<SecuritySettings>;
|
|
234
966
|
/**
|
|
@@ -256,42 +988,94 @@ declare class SettingsResource {
|
|
|
256
988
|
* ]);
|
|
257
989
|
*/
|
|
258
990
|
updateOidcProviders(providers: OidcProvider[], options?: RequestOptions): Promise<OidcProvider[]>;
|
|
991
|
+
/**
|
|
992
|
+
* The project's social-login return URLs — the addresses on your backend that receive
|
|
993
|
+
* the user (with a one-time `code`) after a social login. The first is the default.
|
|
994
|
+
*/
|
|
995
|
+
getReturnUrls(options?: RequestOptions): Promise<string[]>;
|
|
996
|
+
/**
|
|
997
|
+
* Replaces the project's return URLs (at most 10; an empty list switches the feature
|
|
998
|
+
* off) and returns them as they will be matched — exactly, never by prefix. `https`
|
|
999
|
+
* only, except `http://localhost` and `http://127.0.0.1`; no query, fragment, `@` or
|
|
1000
|
+
* wildcard (`400 invalid_payload` names the entry).
|
|
1001
|
+
*/
|
|
1002
|
+
updateReturnUrls(urls: string[], options?: RequestOptions): Promise<string[]>;
|
|
259
1003
|
}
|
|
260
1004
|
|
|
261
1005
|
declare class TokensResource {
|
|
262
1006
|
private readonly http;
|
|
263
|
-
private readonly
|
|
264
|
-
constructor(http: HttpClient
|
|
1007
|
+
private readonly verifiers;
|
|
1008
|
+
constructor(http: HttpClient);
|
|
265
1009
|
/**
|
|
266
|
-
* Exchanges the Gate API key for a short-lived access token
|
|
1010
|
+
* Exchanges the Gate API key for a short-lived access token (`gat_live_…`), for
|
|
1011
|
+
* `subject` — a user or a service account. Answers `201`.
|
|
267
1012
|
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
1013
|
+
* The key travels in the `Authorization` header like on every other call. (Until 1.4.0
|
|
1014
|
+
* this SDK sent it in the body without the header, which the API refuses with `401`.)
|
|
270
1015
|
*/
|
|
271
1016
|
create(params: CreateTokenParams, options?: RequestOptions): Promise<AccessToken>;
|
|
272
1017
|
/**
|
|
273
|
-
* Validates a Gate access token and returns its
|
|
1018
|
+
* Validates a Gate access token and returns its attributes. An unknown, expired or
|
|
1019
|
+
* foreign token, or one whose user you deactivated or deleted, is `{ active: false }`.
|
|
1020
|
+
*
|
|
1021
|
+
* When the subject is an end user, `orgs` lists their organizations in the key's
|
|
1022
|
+
* project, read at the moment you ask.
|
|
274
1023
|
*/
|
|
275
1024
|
introspect(accessToken: string, options?: RequestOptions): Promise<IntrospectResult>;
|
|
1025
|
+
/**
|
|
1026
|
+
* Gets a **signed JWT** (ES256) for a signed-in end user's session, for a platform that
|
|
1027
|
+
* verifies signatures instead of calling Gate (Supabase, an API gateway). The session
|
|
1028
|
+
* token is the credential: no API key is sent.
|
|
1029
|
+
*
|
|
1030
|
+
* The token is valid for 15 minutes and **cannot be revoked**; its `orgs` claim is as old
|
|
1031
|
+
* as the token. Every call mints a new one — ask again before the one you hold expires.
|
|
1032
|
+
* A revoked or expired session, or a deactivated user, is a `401`.
|
|
1033
|
+
*
|
|
1034
|
+
* @example
|
|
1035
|
+
* const { token } = await gate.tokens.createSigned(sessionToken);
|
|
1036
|
+
*/
|
|
1037
|
+
createSigned(sessionToken: string, options?: RequestOptions): Promise<SignedToken>;
|
|
1038
|
+
/**
|
|
1039
|
+
* Verifies a Gate signed token offline against your tenant's public keys (fetched once
|
|
1040
|
+
* and cached) and returns its claims. Throws `VerneTokenError` when the token must not
|
|
1041
|
+
* be trusted — wrong issuer (another tenant), bad signature, expired, any algorithm but
|
|
1042
|
+
* ES256. See {@link GateTokenVerifier} to verify without a Gate client.
|
|
1043
|
+
*
|
|
1044
|
+
* @example
|
|
1045
|
+
* const claims = await gate.tokens.verifySigned(token, { tenantId: 'your-tenant-id' });
|
|
1046
|
+
* claims.sub; // the end user's id
|
|
1047
|
+
*/
|
|
1048
|
+
verifySigned(token: string, options: VerifySignedOptions): Promise<SignedTokenClaims>;
|
|
276
1049
|
}
|
|
277
1050
|
|
|
278
1051
|
declare class Gate {
|
|
279
1052
|
readonly identities: IdentitiesResource;
|
|
280
1053
|
readonly tokens: TokensResource;
|
|
281
1054
|
readonly settings: SettingsResource;
|
|
1055
|
+
readonly organizations: OrganizationsResource;
|
|
1056
|
+
readonly sessions: SessionsResource;
|
|
1057
|
+
readonly auditLog: AuditLogResource;
|
|
1058
|
+
readonly lifecycle: LifecycleResource;
|
|
282
1059
|
private readonly http;
|
|
283
1060
|
constructor(config: ServiceConfig);
|
|
284
1061
|
/**
|
|
285
|
-
*
|
|
286
|
-
*
|
|
1062
|
+
* Asks whether a subject may perform an action on a resource. The answer is a decision;
|
|
1063
|
+
* your service enforces it.
|
|
1064
|
+
*
|
|
1065
|
+
* - `resource: 'organization:<id>'` — may this end user do `action` (a permission) in
|
|
1066
|
+
* that organization? `reason` is one of a fixed set and `role` is the role they hold.
|
|
1067
|
+
* Prefer `gate.organizations.authorize()` / `can()`, which build the resource.
|
|
1068
|
+
* - any other resource — only *is `subject` one of your active end users?*; `reason` is
|
|
1069
|
+
* `owned_by_tenant` (allowed), `subject_inactive`, `not_owned_by_tenant` or
|
|
1070
|
+
* `not_a_known_identity`, and `message` says it in a sentence for your logs.
|
|
287
1071
|
*
|
|
288
1072
|
* @example
|
|
289
|
-
* const
|
|
290
|
-
* subject:
|
|
291
|
-
* action: '
|
|
292
|
-
* resource:
|
|
1073
|
+
* const decision = await gate.authorize({
|
|
1074
|
+
* subject: userId,
|
|
1075
|
+
* action: 'invoices:write',
|
|
1076
|
+
* resource: `organization:${orgId}`,
|
|
293
1077
|
* });
|
|
294
|
-
* if (!
|
|
1078
|
+
* if (!decision.allowed) throw new Error('Forbidden');
|
|
295
1079
|
*/
|
|
296
1080
|
authorize(params: AuthorizeParams, options?: RequestOptions): Promise<AuthorizeResult>;
|
|
297
1081
|
/**
|
|
@@ -305,16 +1089,110 @@ declare class Gate {
|
|
|
305
1089
|
*/
|
|
306
1090
|
getEnabledProviders(tenantId: string, options?: RequestOptions): Promise<string[]>;
|
|
307
1091
|
/**
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
1092
|
+
* Starts a Kratos login flow with your Gate API key and returns it; render its
|
|
1093
|
+
* `ui.nodes` or post credentials to its `ui.action`. With a return URL registered,
|
|
1094
|
+
* pass `return_to` and always a `state` for social login. A step-up (second factor) is
|
|
1095
|
+
* `{ aal: 'aal2', session_token }`.
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* const flow = await gate.createLoginFlow({ state: csrfBoundValue });
|
|
1099
|
+
*/
|
|
1100
|
+
createLoginFlow(params?: LoginFlowParams, options?: RequestOptions): Promise<LoginFlow>;
|
|
1101
|
+
/**
|
|
1102
|
+
* Starts a Kratos registration flow. Refused with `402 ACTIVE_USER_LIMIT_REACHED` when
|
|
1103
|
+
* the account is past its active-user limit and the month to move up has ended.
|
|
1104
|
+
*/
|
|
1105
|
+
createRegistrationFlow(params?: RegistrationFlowParams, options?: RequestOptions): Promise<LoginFlow>;
|
|
1106
|
+
/**
|
|
1107
|
+
* Exchanges the one-time `code` your return URL received after a social login for the
|
|
1108
|
+
* user's session. The code works once, for about 60 seconds, and only with a key of the
|
|
1109
|
+
* project that started the login (otherwise `404`). Keep the session token server-side.
|
|
1110
|
+
*/
|
|
1111
|
+
exchangeOidcCode(code: string, options?: RequestOptions): Promise<OidcExchangeResult>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/** The Telegram end-user captured during login. */
|
|
1115
|
+
interface TelegramUser {
|
|
1116
|
+
id: string;
|
|
1117
|
+
username?: string;
|
|
1118
|
+
first_name?: string;
|
|
1119
|
+
photo_url?: string;
|
|
1120
|
+
}
|
|
1121
|
+
/** Response from starting a Telegram login. */
|
|
1122
|
+
interface LoginStart {
|
|
1123
|
+
/** Opaque nonce identifying this login attempt. Poll `loginStatus(nonce)` with it. */
|
|
1124
|
+
nonce: string;
|
|
1125
|
+
/** `https://t.me/<bot>?start=<nonce>` — send the end-user here to authenticate. */
|
|
1126
|
+
deep_link: string;
|
|
1127
|
+
/** ISO-8601 timestamp after which the nonce expires. */
|
|
1128
|
+
expires_at: string;
|
|
1129
|
+
}
|
|
1130
|
+
/** Current state of a Telegram login attempt. */
|
|
1131
|
+
interface LoginStatus {
|
|
1132
|
+
/** `pending` until the user completes the Telegram flow, then `completed`. */
|
|
1133
|
+
status: 'pending' | 'completed';
|
|
1134
|
+
/** Present once completed — the end-user's access token. */
|
|
1135
|
+
access_token?: string;
|
|
1136
|
+
/** Present once completed — when the access token expires (ISO-8601). */
|
|
1137
|
+
expires_at?: string;
|
|
1138
|
+
/** Present once completed — the provisioned Kratos identity id. */
|
|
1139
|
+
identity_id?: string;
|
|
1140
|
+
/** Present once completed — the authenticated Telegram user. */
|
|
1141
|
+
user?: TelegramUser;
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Result of introspecting a Passepartout access token. An unknown, expired or foreign
|
|
1145
|
+
* token, or one whose user was deactivated or deleted, is `{ active: false }`.
|
|
1146
|
+
*/
|
|
1147
|
+
interface TokenIntrospection {
|
|
1148
|
+
active: boolean;
|
|
1149
|
+
subject?: string;
|
|
1150
|
+
tenant_id?: string;
|
|
1151
|
+
scopes?: string[];
|
|
1152
|
+
expires_at?: string;
|
|
1153
|
+
/**
|
|
1154
|
+
* The user's organizations in the key's project, with the role held in each and its
|
|
1155
|
+
* permissions — read live, the first 100 in the order they joined.
|
|
1156
|
+
*/
|
|
1157
|
+
orgs?: OrgClaim[];
|
|
1158
|
+
/** `true`, and only then, when there are more than `orgs` shows. */
|
|
1159
|
+
orgs_truncated?: boolean;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
/**
|
|
1163
|
+
* Verne Passepartout — Telegram Auth-as-a-Service.
|
|
1164
|
+
*
|
|
1165
|
+
* Lets your end-users sign in with Telegram: start a login to get a deep link,
|
|
1166
|
+
* send the user to it, then poll for completion to receive an access token.
|
|
1167
|
+
*/
|
|
1168
|
+
declare class Passepartout {
|
|
1169
|
+
private readonly http;
|
|
1170
|
+
constructor(config: ServiceConfig);
|
|
1171
|
+
/**
|
|
1172
|
+
* Starts a Telegram login and returns a nonce + deep link. Send the user to
|
|
1173
|
+
* `deep_link`, then poll {@link loginStatus} with `nonce` until it completes.
|
|
312
1174
|
*
|
|
313
1175
|
* @example
|
|
314
|
-
* const
|
|
315
|
-
* //
|
|
1176
|
+
* const { nonce, deep_link } = await passepartout.loginStart();
|
|
1177
|
+
* // redirect the user to `deep_link`, then poll:
|
|
1178
|
+
* const status = await passepartout.loginStatus(nonce);
|
|
316
1179
|
*/
|
|
317
|
-
|
|
1180
|
+
loginStart(options?: RequestOptions): Promise<LoginStart>;
|
|
1181
|
+
/**
|
|
1182
|
+
* Returns the current state of a login attempt. While the user hasn't
|
|
1183
|
+
* finished, `status` is `pending`; once done it becomes `completed` and
|
|
1184
|
+
* carries the `access_token` and `user`.
|
|
1185
|
+
*
|
|
1186
|
+
* Throws `VerneAPIError` with `403 account_disabled` when the person is deactivated,
|
|
1187
|
+
* and `402 ACTIVE_USER_LIMIT_REACHED` when a *new* person signs in past the account's
|
|
1188
|
+
* active-user limit (retrying does not help; existing users are unaffected).
|
|
1189
|
+
*/
|
|
1190
|
+
loginStatus(nonce: string, options?: RequestOptions): Promise<LoginStatus>;
|
|
1191
|
+
/**
|
|
1192
|
+
* Validates a Passepartout access token and returns its attributes.
|
|
1193
|
+
* Tokens owned by another tenant are reported as `{ active: false }`.
|
|
1194
|
+
*/
|
|
1195
|
+
introspect(accessToken: string, options?: RequestOptions): Promise<TokenIntrospection>;
|
|
318
1196
|
}
|
|
319
1197
|
|
|
320
1198
|
/** A message (event) as returned by the Relay API. */
|
|
@@ -323,7 +1201,14 @@ interface Message {
|
|
|
323
1201
|
id: string;
|
|
324
1202
|
/** Dot-notated event name (e.g. 'user.created'). */
|
|
325
1203
|
event_type: string;
|
|
326
|
-
/**
|
|
1204
|
+
/**
|
|
1205
|
+
* Always `'accepted'`.
|
|
1206
|
+
*
|
|
1207
|
+
* It records that Relay took the event, not what each subscriber endpoint did
|
|
1208
|
+
* with it afterwards — per-endpoint delivery state lives in the Console under
|
|
1209
|
+
* Dashboard → Relay. A literal type rather than `string`, so a `switch` over
|
|
1210
|
+
* it cannot grow a branch that never runs.
|
|
1211
|
+
*/
|
|
327
1212
|
status: 'accepted';
|
|
328
1213
|
/** ISO 8601 timestamp of when the event was accepted. */
|
|
329
1214
|
timestamp: string;
|
|
@@ -335,8 +1220,13 @@ interface SendMessageParams {
|
|
|
335
1220
|
/** Arbitrary JSON payload delivered to subscribers. */
|
|
336
1221
|
payload: Record<string, unknown>;
|
|
337
1222
|
/**
|
|
338
|
-
* Optional idempotency key
|
|
339
|
-
*
|
|
1223
|
+
* Optional idempotency key, deduplicating within a 12-hour window.
|
|
1224
|
+
*
|
|
1225
|
+
* Sending the same key twice does not create a second event and does not
|
|
1226
|
+
* fail: the second call returns `202` with the *originally* accepted message,
|
|
1227
|
+
* same `id` and same `timestamp`. So a retry of a request whose response you
|
|
1228
|
+
* never saw needs no special handling — there is no duplicate to tell apart
|
|
1229
|
+
* from a success.
|
|
340
1230
|
*/
|
|
341
1231
|
idempotency_key?: string;
|
|
342
1232
|
/** Restrict delivery to endpoints listening on these channels. */
|
|
@@ -344,9 +1234,14 @@ interface SendMessageParams {
|
|
|
344
1234
|
}
|
|
345
1235
|
/** Query parameters for listing sent events. */
|
|
346
1236
|
interface ListMessagesParams {
|
|
347
|
-
/** Number of items per page.
|
|
1237
|
+
/** Number of items per page. Defaults to 20; anything above 100 is clamped to 100. */
|
|
348
1238
|
limit?: number;
|
|
349
|
-
/**
|
|
1239
|
+
/**
|
|
1240
|
+
* Pagination cursor from a previous response's `next_cursor`.
|
|
1241
|
+
*
|
|
1242
|
+
* `next_cursor` is `null` on the last page, so paginate until `has_more` is
|
|
1243
|
+
* `false` rather than until `data` comes back empty.
|
|
1244
|
+
*/
|
|
350
1245
|
cursor?: string;
|
|
351
1246
|
/** Filter results by event type. */
|
|
352
1247
|
event_type?: string;
|
|
@@ -359,7 +1254,13 @@ declare class MessagesResource {
|
|
|
359
1254
|
constructor(http: HttpClient);
|
|
360
1255
|
/**
|
|
361
1256
|
* Publish an event to all endpoints subscribed to the given event_type.
|
|
362
|
-
*
|
|
1257
|
+
* Retries once on a short `429` (a `Retry-After` of a minute or less). The monthly
|
|
1258
|
+
* message limit (`429 RELAY_MESSAGE_LIMIT_REACHED`, `Retry-After` until the 1st) is
|
|
1259
|
+
* thrown at once, with `retryAfter` on the error.
|
|
1260
|
+
*
|
|
1261
|
+
* Safe to retry beyond that, if you pass an `idempotency_key`: a repeat
|
|
1262
|
+
* returns the originally accepted message rather than creating a second event
|
|
1263
|
+
* or failing.
|
|
363
1264
|
*
|
|
364
1265
|
* @returns The accepted message with its assigned ID and timestamp.
|
|
365
1266
|
*/
|
|
@@ -375,13 +1276,83 @@ declare class Relay {
|
|
|
375
1276
|
constructor(config: ServiceConfig);
|
|
376
1277
|
}
|
|
377
1278
|
|
|
1279
|
+
/**
|
|
1280
|
+
* The unified client. Pass one API key (`apiKey`) and use any service its scopes allow;
|
|
1281
|
+
* a call to a service the key has no scope for is refused by the API with `403 forbidden`.
|
|
1282
|
+
*
|
|
1283
|
+
* @example
|
|
1284
|
+
* const verne = new Verne({ apiKey: process.env.VERNE_API_KEY });
|
|
1285
|
+
* await verne.gate.organizations.create({ name: 'Acme' });
|
|
1286
|
+
*/
|
|
378
1287
|
declare class Verne {
|
|
379
1288
|
private readonly config;
|
|
380
1289
|
private _relay?;
|
|
381
1290
|
private _gate?;
|
|
1291
|
+
private _passepartout?;
|
|
1292
|
+
private _clockwork?;
|
|
382
1293
|
constructor(config: VerneConfig);
|
|
383
1294
|
get relay(): Relay;
|
|
384
1295
|
get gate(): Gate;
|
|
1296
|
+
get passepartout(): Passepartout;
|
|
1297
|
+
get clockwork(): Clockwork;
|
|
1298
|
+
private serviceConfig;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
interface GateTokenVerifierConfig {
|
|
1302
|
+
/** Your tenant id. The issuer is `<baseUrl>/auth/<tenantId>`. */
|
|
1303
|
+
tenantId: string;
|
|
1304
|
+
/** Defaults to https://api.vernesoft.com — the same base URL as the API client. */
|
|
1305
|
+
baseUrl?: string;
|
|
1306
|
+
/** Allowed clock skew in seconds for `exp` and `nbf`. Default 10. */
|
|
1307
|
+
clockToleranceSeconds?: number;
|
|
1308
|
+
/** Timeout of a key-set request in milliseconds. Default 10000. */
|
|
1309
|
+
timeoutMs?: number;
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Verifies Gate signed tokens (ES256 JWTs) offline, against your tenant's published
|
|
1313
|
+
* public keys. No API key is involved: anything that receives a token can verify it.
|
|
1314
|
+
*
|
|
1315
|
+
* What it checks: the algorithm is ES256 (anything else, `none` included, is refused),
|
|
1316
|
+
* the key is the one the token's `kid` names in your tenant's key set, the signature,
|
|
1317
|
+
* `iss` is **your** issuer (a token of another Gate tenant is refused even though its
|
|
1318
|
+
* signature is valid), `exp` and `nbf`, and that `sub` is present.
|
|
1319
|
+
*
|
|
1320
|
+
* What it cannot check: whether the session behind the token is still alive. A signed
|
|
1321
|
+
* token lives 15 minutes and cannot be revoked; for anything that must follow a
|
|
1322
|
+
* revocation or a role change at once, ask `gate.sessions.check()` or introspection.
|
|
1323
|
+
*
|
|
1324
|
+
* The key set is cached for its `Cache-Control: max-age` (five minutes) and refetched
|
|
1325
|
+
* once when a token names a key it has not seen — which is how a key rotation is
|
|
1326
|
+
* followed. Keep one verifier per tenant and reuse it.
|
|
1327
|
+
*
|
|
1328
|
+
* @example
|
|
1329
|
+
* const verifier = new GateTokenVerifier({ tenantId: process.env.VERNE_TENANT_ID! });
|
|
1330
|
+
* const claims = await verifier.verify(token);
|
|
1331
|
+
* claims.sub; // the end user's id
|
|
1332
|
+
* claims.orgs; // [{ id, role, permissions }]
|
|
1333
|
+
*/
|
|
1334
|
+
declare class GateTokenVerifier {
|
|
1335
|
+
readonly issuer: string;
|
|
1336
|
+
readonly jwksUrl: string;
|
|
1337
|
+
private readonly toleranceSeconds;
|
|
1338
|
+
private readonly timeoutMs;
|
|
1339
|
+
private keys;
|
|
1340
|
+
private fetchedAt;
|
|
1341
|
+
private maxAgeMs;
|
|
1342
|
+
private inflight?;
|
|
1343
|
+
constructor(config: GateTokenVerifierConfig);
|
|
1344
|
+
/**
|
|
1345
|
+
* Verifies `token` and returns its claims. Throws {@link VerneTokenError} (with a
|
|
1346
|
+
* `reason`) when the token must not be trusted.
|
|
1347
|
+
*/
|
|
1348
|
+
verify(token: string): Promise<SignedTokenClaims>;
|
|
1349
|
+
private keyFor;
|
|
1350
|
+
/**
|
|
1351
|
+
* Fetches the key set. With `required` false a failure keeps the keys already cached
|
|
1352
|
+
* (a stale key set is still the right one unless a token says otherwise).
|
|
1353
|
+
*/
|
|
1354
|
+
private refresh;
|
|
1355
|
+
private load;
|
|
385
1356
|
}
|
|
386
1357
|
|
|
387
1358
|
/**
|
|
@@ -395,27 +1366,75 @@ declare class VerneError extends Error {
|
|
|
395
1366
|
* Contains structured information from the API error envelope.
|
|
396
1367
|
*/
|
|
397
1368
|
declare class VerneAPIError extends VerneError {
|
|
398
|
-
/**
|
|
1369
|
+
/**
|
|
1370
|
+
* Machine-readable error code, e.g. `'invalid_payload'`, `'forbidden'`, `'conflict'`,
|
|
1371
|
+
* `'mfa_required'`, `'ACTIVE_USER_LIMIT_REACHED'`. Codes are an open set: compare
|
|
1372
|
+
* against the ones you handle and treat the rest generically. `'unknown'` when the
|
|
1373
|
+
* response carried no string code — which the API's own routes no longer do; it is
|
|
1374
|
+
* left for a body that did not come from the gateway (a proxy in between, an identity
|
|
1375
|
+
* service response passed through on `/auth/*`).
|
|
1376
|
+
*/
|
|
399
1377
|
readonly code: string;
|
|
400
1378
|
/** HTTP status code. */
|
|
401
1379
|
readonly status: number;
|
|
402
|
-
/**
|
|
403
|
-
|
|
404
|
-
|
|
1380
|
+
/**
|
|
1381
|
+
* Request ID to include when contacting support.
|
|
1382
|
+
* Undefined when the response did not carry one.
|
|
1383
|
+
*/
|
|
1384
|
+
readonly requestId?: string;
|
|
1385
|
+
/**
|
|
1386
|
+
* The members of `error` other than `code`, `message` and `request_id` — for example
|
|
1387
|
+
* `plan`, `limit` and `current` on a `402` limit refusal, `kind` on a Clockwork one,
|
|
1388
|
+
* `required_aal` and `current_aal` on `403 mfa_required`. Empty when there are none.
|
|
1389
|
+
*/
|
|
1390
|
+
readonly details: Record<string, unknown>;
|
|
1391
|
+
/**
|
|
1392
|
+
* Seconds from the `Retry-After` header, when the response had one — on a `429` it is
|
|
1393
|
+
* how long to wait. For `RELAY_MESSAGE_LIMIT_REACHED` it runs to the 1st of next month.
|
|
1394
|
+
*/
|
|
1395
|
+
readonly retryAfter?: number;
|
|
1396
|
+
/** Raw parsed error body, kept so unrecognised shapes stay diagnosable. */
|
|
1397
|
+
readonly body?: unknown;
|
|
1398
|
+
constructor({ code, message, status, requestId, details, retryAfter, body, }: {
|
|
405
1399
|
code: string;
|
|
406
1400
|
message: string;
|
|
407
1401
|
status: number;
|
|
408
|
-
requestId
|
|
1402
|
+
requestId?: string;
|
|
1403
|
+
details?: Record<string, unknown>;
|
|
1404
|
+
retryAfter?: number;
|
|
1405
|
+
body?: unknown;
|
|
409
1406
|
});
|
|
410
|
-
|
|
1407
|
+
/**
|
|
1408
|
+
* Builds an error from a parsed response body of *unknown* shape.
|
|
1409
|
+
*
|
|
1410
|
+
* Every API route answers with the envelope `{ error: { code, message, request_id,
|
|
1411
|
+
* ...extra } }`. Other shapes are still read, as a fallback that costs nothing: the
|
|
1412
|
+
* string form `{ error: "<sentence>" }` Clockwork used before October 2026, and an
|
|
1413
|
+
* identity-service body whose `code` is a number (still what Kratos' own `/auth/*`
|
|
1414
|
+
* self-service routes answer). Anything unrecognised degrades — to code `'unknown'`,
|
|
1415
|
+
* to `HTTP <status>` — rather than throwing: an error path must never be the thing
|
|
1416
|
+
* that fails.
|
|
1417
|
+
*/
|
|
1418
|
+
static fromResponse(status: number, body: unknown, retryAfter?: number): VerneAPIError;
|
|
1419
|
+
}
|
|
1420
|
+
/** Why a signed token was refused by {@link VerneTokenError}. */
|
|
1421
|
+
type TokenErrorReason = 'malformed' | 'unsupported_alg' | 'unknown_kid' | 'bad_signature' | 'wrong_issuer' | 'expired' | 'not_yet_valid' | 'missing_claim' | 'jwks_unavailable';
|
|
1422
|
+
/**
|
|
1423
|
+
* Thrown by signed-token verification (`GateTokenVerifier`, `gate.tokens.verifySigned`)
|
|
1424
|
+
* when a token must not be trusted. `reason` says why.
|
|
1425
|
+
*/
|
|
1426
|
+
declare class VerneTokenError extends VerneError {
|
|
1427
|
+
readonly reason: TokenErrorReason;
|
|
1428
|
+
constructor(reason: TokenErrorReason, message: string);
|
|
411
1429
|
}
|
|
412
|
-
/** Shape of the API error envelope
|
|
1430
|
+
/** Shape of the API error envelope documented for all Verne services. */
|
|
413
1431
|
interface APIErrorBody {
|
|
414
1432
|
error: {
|
|
415
1433
|
code: string;
|
|
416
1434
|
message: string;
|
|
417
1435
|
request_id: string;
|
|
1436
|
+
[extra: string]: unknown;
|
|
418
1437
|
};
|
|
419
1438
|
}
|
|
420
1439
|
|
|
421
|
-
export { type APIErrorBody, type AccessToken, type AuthorizeParams, type AuthorizeResult, type CreateIdentityParams, type CreateTokenParams, Gate, type Identity, type IdentityTraits, type IntrospectResult, type JsonPatchOp, type ListMessagesParams, type ListMessagesResponse, type LoginFlow, type Message, type OidcProvider, type Paginated, Relay, type RequestOptions, type SecuritySettings, type SendMessageParams, type ServiceConfig, Verne, VerneAPIError, type VerneConfig, VerneError };
|
|
1440
|
+
export { type APIErrorBody, type AccessToken, type AddMemberParams, type AuditActorType, type AuditLogEntry, type AuthorizeParams, type AuthorizeResult, Clockwork, type ClockworkUsage, type CreateCronJobParams, type CreateDelayedJobParams, type CreateIdentityParams, type CreateOrganizationParams, type CreateRoleParams, type CreateTokenParams, type CronJob, type DelayedJob, type Execution, Gate, type GateSession, GateTokenVerifier, type GateTokenVerifierConfig, type Identity, type IdentityTraits, type IntrospectResult, type JsonPatchOp, type LifecycleAction, type LifecycleRule, type LifecycleRuleKind, type LifecycleRuleParamsByKind, type LifecycleRulePreview, type LifecycleRules, type ListAuditLogParams, type ListLifecycleActionsParams, type ListMessagesParams, type ListMessagesResponse, type ListParams, type LoginFlow, type LoginFlowParams, type LoginStart, type LoginStatus, type Member, type Message, type OidcExchangeResult, type OidcProvider, type OrgClaim, type Organization, type OrganizationAuthorizeReason, type OwnershipAuthorizeReason, type Paginated, Passepartout, type RegistrationFlowParams, Relay, type RequestOptions, type Role, type SecuritySettings, type SendMessageParams, type ServiceConfig, type SessionCheck, type SetLifecycleRuleParams, type SignedToken, type SignedTokenClaims, type TelegramUser, type TokenErrorReason, type TokenIntrospection, type UpdateCronJobParams, type UpdateMemberParams, type UpdateOrganizationParams, type UpdateRoleParams, type VerifySignedOptions, Verne, VerneAPIError, type VerneConfig, VerneError, VerneTokenError };
|