@authyon/server 0.2.0-beta.2 → 0.2.0-beta.20

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.
@@ -0,0 +1,1232 @@
1
+ import { JSONWebKeySet, JWTPayload, JWSHeaderParameters } from 'jose';
2
+
3
+ interface HttpAdapterRequest {
4
+ url: string;
5
+ method: string;
6
+ headers: Record<string, string>;
7
+ body?: BodyInit | null;
8
+ signal: AbortSignal;
9
+ }
10
+ /** Transport contract accepted by both Authyon clients. */
11
+ interface HttpAdapter {
12
+ request(request: HttpAdapterRequest): Promise<Response>;
13
+ }
14
+ type HttpLogEvent = {
15
+ type: "request";
16
+ method: string;
17
+ url: string;
18
+ timestamp: number;
19
+ } | {
20
+ type: "response";
21
+ method: string;
22
+ url: string;
23
+ status: number;
24
+ durationMs: number;
25
+ requestId?: string;
26
+ timestamp: number;
27
+ } | {
28
+ type: "error";
29
+ method: string;
30
+ url: string;
31
+ errorName: string;
32
+ durationMs: number;
33
+ timestamp: number;
34
+ };
35
+ /** Receives sanitized HTTP lifecycle events. Headers, bodies and query values are never exposed. */
36
+ type HttpLogger = (event: HttpLogEvent) => void;
37
+ /**
38
+ * Mutable logging configuration. Change `enabled` at runtime to enable or disable logging
39
+ * without recreating the Authyon client.
40
+ */
41
+ interface HttpLoggerOptions {
42
+ enabled: boolean;
43
+ logger?: HttpLogger;
44
+ }
45
+ /** Default adapter backed by the platform's Fetch API. */
46
+ declare class FetchHttpAdapter implements HttpAdapter {
47
+ private readonly fetchImpl;
48
+ constructor(fetchImpl?: typeof fetch);
49
+ request(request: HttpAdapterRequest): Promise<Response>;
50
+ }
51
+ /** Adds safe, configurable lifecycle logging to any HTTP adapter. */
52
+ declare class LoggingHttpAdapter implements HttpAdapter {
53
+ private readonly adapter;
54
+ private readonly options;
55
+ constructor(adapter: HttpAdapter, options: HttpLoggerOptions);
56
+ request(request: HttpAdapterRequest): Promise<Response>;
57
+ private log;
58
+ }
59
+
60
+ /**
61
+ * Security methods active on the user's account, as returned in the
62
+ * `security` field of `GET /auth/me` and `POST /auth/validate`.
63
+ */
64
+ interface SecurityMethods {
65
+ /** A password is set (false for accounts created only through SSO or magic link). */
66
+ password: boolean;
67
+ /** Authenticator app (TOTP one-time codes). */
68
+ authenticator: boolean;
69
+ /** One-time codes sent by email. */
70
+ emailCode: boolean;
71
+ /** At least one passkey registered. */
72
+ passkey: boolean;
73
+ passkeyCount: number;
74
+ /** Unused recovery codes left. */
75
+ recoveryCodes: number;
76
+ /** SSO providers linked to the account, e.g. `["google", "github"]`. */
77
+ sso: string[];
78
+ /** Any second factor is active (authenticator, email code or passkey). */
79
+ twoFactor: boolean;
80
+ }
81
+ /** Lifecycle of an approval. */
82
+ type ApprovalStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
83
+ /**
84
+ * Free-form JSON object describing what the customer approves (up to 16 KiB).
85
+ * The API stores it, shows it back to the customer and binds its canonical
86
+ * hash (keys sorted) to the approval.
87
+ */
88
+ type ApprovalPayload = Record<string, unknown>;
89
+ /** Evidence of how the customer proved their identity when approving. */
90
+ interface ApprovalAssurance {
91
+ /** `urn:authyon:loa:3` (passkey) or `urn:authyon:loa:2` (authenticator code). */
92
+ acr: string;
93
+ /** Authentication methods, e.g. `["pwd", "otp"]` or `["pwd", "webauthn"]`. */
94
+ amr: string[];
95
+ /** When the second factor was verified (ISO 8601). */
96
+ authTime: string;
97
+ }
98
+ /** A request for the customer to approve something with a second factor. */
99
+ interface Approval {
100
+ id: string;
101
+ status: ApprovalStatus;
102
+ subjectId: string;
103
+ tenantId?: string | null;
104
+ /** The payload given to `create()`, with keys in canonical order. */
105
+ payload: ApprovalPayload;
106
+ /** SHA-256 (hex) of the canonical payload. */
107
+ payloadHash: string;
108
+ createdAt: string;
109
+ expiresAt: string;
110
+ decidedAt?: string | null;
111
+ consumedAt?: string | null;
112
+ /** Present once approved. */
113
+ assurance?: ApprovalAssurance | null;
114
+ }
115
+ /** Second factor sent with `confirm()`. */
116
+ type ConfirmApprovalInput = {
117
+ method: "authenticator";
118
+ /** Six-digit code from the customer's authenticator app. */
119
+ code: string;
120
+ } | {
121
+ method: "webauthn";
122
+ /** Assertion for the options returned by `webauthnOptions()`. */
123
+ webAuthn: {
124
+ ceremonyToken: string;
125
+ /** JSON-serialized `PublicKeyCredential` from `navigator.credentials.get()`. */
126
+ assertionJson: string;
127
+ };
128
+ };
129
+ /** Passkey assertion options for approving one approval. */
130
+ interface ApprovalWebAuthnOptions {
131
+ ceremonyToken: string;
132
+ /** JSON `PublicKeyCredentialRequestOptions` to pass to `navigator.credentials.get()`. */
133
+ optionsJson: string;
134
+ }
135
+
136
+ interface PaginationOptions {
137
+ skip?: number;
138
+ take?: number;
139
+ }
140
+ /**
141
+ * The envelope every paged endpoint answers with.
142
+ *
143
+ * `page` is the 1-based current page and `perPage` is how many items a page
144
+ * holds — the same sense `take` has on the way in. Up to Authyon API
145
+ * 2026-10-21 the two were named `perPage` (holding the page number) and
146
+ * `pageSize` (holding the limit), so reading them by their names gave the
147
+ * wrong value without failing. Clients on the older API see `page` undefined
148
+ * and `perPage` holding a page number.
149
+ */
150
+ interface Paged<T> {
151
+ data: T[];
152
+ page: number;
153
+ perPage: number;
154
+ total: number;
155
+ pages: number;
156
+ hasNext: boolean;
157
+ hasPrev: boolean;
158
+ }
159
+ interface IntrospectResult {
160
+ active: boolean;
161
+ sub?: string;
162
+ username?: string | null;
163
+ email?: string | null;
164
+ roles?: string[] | null;
165
+ permissions?: string[];
166
+ client_id?: string;
167
+ scope?: string;
168
+ exp?: number;
169
+ iat?: number;
170
+ jti?: string;
171
+ token_type?: string;
172
+ }
173
+
174
+ /** GET/POST /env/tenants — confirmed against the live API. */
175
+ interface Organization {
176
+ id: string;
177
+ slug: string;
178
+ name?: string;
179
+ description?: string | null;
180
+ environmentId?: string;
181
+ workspaceId?: string;
182
+ isDisabled?: boolean;
183
+ memberCount?: number;
184
+ createdAt?: string;
185
+ updatedAt?: string;
186
+ /** JSON-encoded values for the tenant's configured custom fields. */
187
+ customFields?: string;
188
+ /** JSON-encoded metadata that may be exposed to tenant members. */
189
+ publicMetadata?: string;
190
+ /** JSON-encoded metadata available only through administrative APIs. */
191
+ privateMetadata?: string;
192
+ }
193
+ /** One of a user's tenant memberships, as embedded in `EnvironmentUser.tenantMemberships`. */
194
+ interface TenantMembership {
195
+ tenantId: string;
196
+ tenantSlug: string;
197
+ tenantName: string;
198
+ tenantDisabled: boolean;
199
+ roles: string[];
200
+ }
201
+ /** Lightweight user shape returned by `introspect()`/`validate()`. */
202
+ interface User {
203
+ id: string;
204
+ email: string;
205
+ username?: string;
206
+ /** Environment-level roles from the database-validated user profile. */
207
+ roles?: string[];
208
+ permissions?: string[];
209
+ /** Security methods active on the account (authenticator, email code, passkey, SSO…). */
210
+ security?: SecurityMethods;
211
+ }
212
+ interface RoleGrant {
213
+ role: string;
214
+ expiresAt?: string | null;
215
+ }
216
+ /**
217
+ * Full user record from the EnvironmentManagement plane
218
+ * (`environment.users.get()` / `.list()`), confirmed against the live API.
219
+ * `get()` returns every field below; `list()` returns a subset (no
220
+ * `failedLoginAttempts`, `lockedOutUntil`, `roleGrants`,
221
+ * `directPermissions`, `effectivePermissions`, `refreshTokens`,
222
+ * `tenantMemberships`, `totpConfirmedAt`, `emailOtpEnabledAt`,
223
+ * `remainingRecoveryCodes`, `disableReason`, `suspension`, `deleteReason`,
224
+ * `customFields` — and `suspendedUntil` instead of `suspension`).
225
+ */
226
+ interface EnvironmentUser {
227
+ id: string;
228
+ email: string;
229
+ username?: string;
230
+ firstName?: string | null;
231
+ lastName?: string | null;
232
+ emailConfirmed: boolean;
233
+ isDisabled: boolean;
234
+ createdAt: string;
235
+ lastLoginAt?: string | null;
236
+ failedLoginAttempts?: number;
237
+ lockedOutUntil?: string | null;
238
+ roles: string[];
239
+ roleGrants?: RoleGrant[];
240
+ directPermissions?: string[];
241
+ effectivePermissions?: string[];
242
+ /** Confirmed shape unknown — empty in every response seen so far. */
243
+ refreshTokens?: unknown[];
244
+ tenantIds: string[];
245
+ tenantMemberships?: TenantMembership[];
246
+ /** Flattened role names across all tenant memberships (list() only).
247
+ * On `tenants.members.list()` it is scoped to that one tenant. */
248
+ tenantRoles?: string[];
249
+ /** Permissions granted to this member directly inside the tenant, beside
250
+ * whatever their tenant roles carry. Only `tenants.members.list()` fills
251
+ * it; absent on an API older than 2026-10-21. */
252
+ tenantPermissions?: string[];
253
+ twoFactorMethods: string[];
254
+ totpConfirmedAt?: string | null;
255
+ emailOtpEnabledAt?: string | null;
256
+ remainingRecoveryCodes?: number;
257
+ disableReason?: string | null;
258
+ suspension?: unknown | null;
259
+ suspendedUntil?: string | null;
260
+ deletedAt?: string | null;
261
+ deleteReason?: string | null;
262
+ /** JSON-encoded string. */
263
+ customFields?: string;
264
+ }
265
+ /**
266
+ * POST /auth/validate — confirmed against the live API. The wire shape is
267
+ * `{ valid, reason, profile }`, not `{ user, organization }` as the
268
+ * OpenAPI schema (which didn't document response bodies) suggested.
269
+ * `profile` is `null` for machine tokens (there's no user behind them) and
270
+ * for tokens that fail validation.
271
+ */
272
+ interface ValidateResult {
273
+ valid: boolean;
274
+ reason?: string | null;
275
+ user: User | null;
276
+ }
277
+ /**
278
+ * A role available within an environment or one of its tenants. Confirmed
279
+ * live: system roles carry no `id`/`description` (only `name` +
280
+ * `permissions`) — both are only populated for custom roles you create.
281
+ */
282
+ interface Role {
283
+ id?: string | null;
284
+ name: string;
285
+ description?: string | null;
286
+ permissions: string[];
287
+ }
288
+ interface RoleInput {
289
+ name: string;
290
+ description?: string;
291
+ permissions?: string[];
292
+ }
293
+ /**
294
+ * GET /env/roles and GET /tenant/roles group results by origin instead of
295
+ * returning a flat array — confirmed live for the environment endpoint.
296
+ */
297
+ interface RoleList {
298
+ custom: Role[];
299
+ system: Role[];
300
+ }
301
+ /** A permission entry as it appears nested under a role in `PermissionsByRole`. */
302
+ interface Permission {
303
+ value: string;
304
+ description?: string | null;
305
+ /** Confirmed live: `null` for the built-in catalog: no separate id per entry. */
306
+ catalogId?: string | null;
307
+ }
308
+ /** A role entry as returned by GET /env/permissions, with its permissions nested. */
309
+ interface RolePermissions {
310
+ roleId: string | null;
311
+ name: string;
312
+ description?: string | null;
313
+ isSystem: boolean;
314
+ permissions: Permission[];
315
+ }
316
+ /** GET /env/permissions — confirmed live: grouped by role, plus any orphaned entries. */
317
+ interface PermissionsByRole {
318
+ roles: RolePermissions[];
319
+ orphans: Permission[];
320
+ }
321
+ /** GET /permissions/reserved — confirmed live: wrapped, not a bare string array. */
322
+ interface ReservedPermissions {
323
+ namespace: string;
324
+ items: string[];
325
+ }
326
+ interface CreatePermissionInput {
327
+ value: string;
328
+ description?: string;
329
+ /** Attach the new permission to this role immediately. */
330
+ attachToRoleId?: string;
331
+ }
332
+ interface CreateOrganizationInput {
333
+ name: string;
334
+ slug: string;
335
+ description?: string;
336
+ customFields?: Record<string, unknown>;
337
+ publicMetadata?: Record<string, unknown>;
338
+ privateMetadata?: Record<string, unknown>;
339
+ }
340
+ interface UpdateOrganizationInput {
341
+ name: string;
342
+ description?: string;
343
+ customFields?: Record<string, unknown>;
344
+ }
345
+ interface CreateUserInput {
346
+ email: string;
347
+ /**
348
+ * Same contract as `/auth/register`: optional only when the environment's
349
+ * username policy is `AutoFromEmail` (derived from the email). Collisions
350
+ * resolve by that policy.
351
+ */
352
+ username?: string;
353
+ password: string;
354
+ firstName?: string;
355
+ lastName?: string;
356
+ /** Values for custom user fields configured in the environment. */
357
+ customFields?: Record<string, unknown>;
358
+ emailConfirmed?: boolean;
359
+ roles?: string[];
360
+ /** Tenants (organizations) to add the user to on creation. */
361
+ tenantIds?: string[];
362
+ }
363
+ /** GET /env/audit — one audit-trail entry, confirmed against the live API. */
364
+ interface AuditEvent {
365
+ id: string;
366
+ occurredAt: string;
367
+ eventType: string;
368
+ /** JSON-encoded string — `JSON.parse` it for the event-specific payload. */
369
+ payloadJson?: string;
370
+ workspaceId?: string;
371
+ environmentId?: string;
372
+ actorUserId?: string | null;
373
+ actorType?: string;
374
+ actorIp?: string;
375
+ userAgent?: string;
376
+ tenantId?: string | null;
377
+ }
378
+ /**
379
+ * GET /env/audit/login-activity. Not confirmed with a populated example
380
+ * live (the test environment had none) — assumed to share `AuditEvent`'s
381
+ * shape, since login activity is the same underlying audit-event stream
382
+ * filtered to sign-in events.
383
+ */
384
+ type LoginActivity = AuditEvent;
385
+ /**
386
+ * Envelope every `skip`/`take`-paginated list endpoint returns, confirmed
387
+ * live for `/env/users`, `/env/audit` and `/env/audit/login-activity`.
388
+ * Endpoints without `skip`/`take` params return a bare array instead.
389
+ */
390
+ /** Tenant credential metadata. Listing never returns the secret. */
391
+ interface TenantCredentialSummary {
392
+ id: string;
393
+ clientId: string;
394
+ description: string | null;
395
+ createdAt: string;
396
+ lastUsedAt: string | null;
397
+ revokedAt: string | null;
398
+ expiresAt: string | null;
399
+ isActive: boolean;
400
+ permissions: string[];
401
+ }
402
+ /** Input for a tenant machine credential. Requires at least one explicit permission. */
403
+ interface CreateTenantCredentialInput {
404
+ description: string;
405
+ /** Number of days until the tenant credential expires. Omit for no automatic expiration. */
406
+ lifetimeDays?: number | null;
407
+ permissions: string[];
408
+ }
409
+ /** The plaintext secret is returned only when the credential is issued. */
410
+ interface TenantCredentialIssued {
411
+ credentialId: string;
412
+ clientId: string;
413
+ clientSecret: string;
414
+ createdAt: string;
415
+ expiresAt: string | null;
416
+ permissions: string[];
417
+ }
418
+ /** OAuth 2.0 client-credentials pair minted in the Authyon console. */
419
+ interface ClientCredentials {
420
+ clientId: string;
421
+ clientSecret: string;
422
+ }
423
+ /** Standard OAuth 2.0 client-credentials token response. */
424
+ interface TokenResult {
425
+ access_token: string;
426
+ token_type: string;
427
+ expires_in: number;
428
+ scope?: string;
429
+ }
430
+ /** POST /tenant/auth/validate — validates the current tenant-client bearer. */
431
+ interface TenantClientValidationResult {
432
+ valid: boolean;
433
+ reason?: string | null;
434
+ tenantId: string;
435
+ workspaceId: string;
436
+ environmentId: string;
437
+ credentialId: string;
438
+ clientId: string;
439
+ permissions: string[];
440
+ }
441
+ interface JsonWebKeySet {
442
+ keys: Record<string, unknown>[];
443
+ }
444
+ interface OpenIdConfiguration {
445
+ issuer: string;
446
+ jwks_uri: string;
447
+ authorization_endpoint?: string;
448
+ token_endpoint?: string;
449
+ [key: string]: unknown;
450
+ }
451
+ interface AuthyonServerClientOptions {
452
+ /**
453
+ * Publishable environment key (`pk_live_...` / `pk_test_...`), sent as
454
+ * `X-Authyon-Environment`. Required on **every** call — it selects the
455
+ * environment (Test / Live) that a request applies to, independently of
456
+ * whichever bearer token authenticates it.
457
+ */
458
+ envKey?: string;
459
+ /**
460
+ * Environment-level OAuth client credentials (`ec_...` / secret), minted
461
+ * in the console. Required for everything under `environment.*` and
462
+ * `permissions.*` — the SDK exchanges them for a short-lived access token
463
+ * via `POST /env/oauth/token` and refreshes it transparently.
464
+ */
465
+ clientId?: string;
466
+ clientSecret?: string;
467
+ /**
468
+ * Originating end-user IP to forward on every API call as `X-Forwarded-For`.
469
+ * Only set this from infrastructure you trust; the SDK rejects comma-separated
470
+ * or whitespace-containing values to avoid forwarded-header injection.
471
+ */
472
+ clientIp?: string;
473
+ /** API origin. Defaults to `https://api.authyon.com`. */
474
+ baseUrl?: string;
475
+ /** Allow an HTTP `baseUrl`. Intended only for explicitly trusted local development. */
476
+ allowInsecureHttp?: boolean;
477
+ /** Maximum duration of each HTTP request. Defaults to 15 seconds; set to `0` to disable. */
478
+ timeoutMs?: number;
479
+ /** Custom HTTP adapter for tracing, mocks or an alternative HTTP stack. */
480
+ httpAdapter?: HttpAdapter;
481
+ /** Safe HTTP lifecycle logging. Disabled unless this option is provided with `enabled: true`. */
482
+ httpLogger?: HttpLoggerOptions;
483
+ /** @deprecated Prefer `httpAdapter: new FetchHttpAdapter(customFetch)`. */
484
+ fetch?: typeof fetch;
485
+ }
486
+
487
+ /** A token of the requested authentication plane, or a provider called for each request. */
488
+ type AccessTokenSource = string | (() => string | Promise<string>);
489
+ interface CredentialListOptions extends PaginationOptions {
490
+ search?: string;
491
+ }
492
+ /** scopes is an alias for permissions. Always supply an explicit, nonempty set. */
493
+ type CredentialPermissionsInput = {
494
+ permissions: readonly string[];
495
+ scopes?: never;
496
+ } | {
497
+ scopes: readonly string[];
498
+ permissions?: never;
499
+ };
500
+ type CreateCredentialInput = CredentialPermissionsInput & {
501
+ description?: string;
502
+ lifetimeDays?: number | null;
503
+ };
504
+ interface CredentialCreator {
505
+ id: string | null;
506
+ type: string;
507
+ displayName: string | null;
508
+ }
509
+ interface CredentialDetail extends TenantCredentialSummary {
510
+ createdBy: CredentialCreator | null;
511
+ updatedAt: string | null;
512
+ secretRotatedAt: string | null;
513
+ expiresAt: string | null;
514
+ ageSeconds: number;
515
+ /** Null while active; elapsed lifetime at revocation otherwise. */
516
+ lifetimeSeconds: number | null;
517
+ accessTokenLifetimeSeconds: number;
518
+ }
519
+ interface InviteTenantMemberInput {
520
+ email: string;
521
+ roles?: string[];
522
+ }
523
+ interface TenantMember {
524
+ userId: string;
525
+ email: string;
526
+ username: string;
527
+ roles: string[];
528
+ createdAt: string;
529
+ lastLoginAt: string | null;
530
+ }
531
+ type TenantMemberPage = Paged<TenantMember>;
532
+ /**
533
+ * Invite an address to a tenant. The address may not have an account in the
534
+ * environment yet — accepting creates it. `sendEmail` defaults to `true`;
535
+ * `false` only returns the link, for delivery through your own channel.
536
+ */
537
+ interface TenantInviteInput {
538
+ email: string;
539
+ roles?: string[];
540
+ sendEmail?: boolean;
541
+ /**
542
+ * Where to send the invitee after they accept. Must be registered exactly in
543
+ * the environment's redirect URIs (the same list SSO and magic link use);
544
+ * otherwise the API rejects the invite. Comes back on `preview` and `accept`.
545
+ */
546
+ redirectUri?: string;
547
+ }
548
+ /** POST /env/password-resets — issue a reset for an account of the environment. */
549
+ interface IssuePasswordResetInput {
550
+ email: string;
551
+ /**
552
+ * Where to send the person after they change the password. Must be
553
+ * registered exactly in the environment's redirect URIs; otherwise the API
554
+ * rejects with `user.password_reset.redirect_uri.not_allowed`.
555
+ */
556
+ redirectUri?: string;
557
+ /**
558
+ * `true` has Authyon mail the link as well. Defaults to `false`: the point
559
+ * of this call is to deliver the token through your own e-mail.
560
+ */
561
+ sendEmail?: boolean;
562
+ }
563
+ /** Returned when a reset is issued. `token` is only ever readable here — the
564
+ * API keeps its hash. Whoever holds it can set the password: send it only to
565
+ * the account's own address and never log it. */
566
+ interface PasswordResetIssued {
567
+ userId: string;
568
+ email: string;
569
+ token: string;
570
+ /** The link Authyon's own e-mail would carry: the environment's reset page
571
+ * when it has one, the hosted page otherwise. */
572
+ resetUrl: string;
573
+ expiresAt: string;
574
+ emailSent: boolean;
575
+ redirectUri: string | null;
576
+ }
577
+ /** What a live reset token is for. */
578
+ interface PasswordResetPreview {
579
+ email: string;
580
+ expiresAt: string;
581
+ redirectUri: string | null;
582
+ }
583
+ /** The password is changed. Following `redirectUri` is up to you. */
584
+ interface PasswordResetCompleted {
585
+ redirectUri: string | null;
586
+ }
587
+ /** Returned when an invite is created or re-issued. `acceptUrl` is only ever
588
+ * readable here — the API keeps a hash of the token, not the token. */
589
+ interface TenantInviteIssued {
590
+ id: string;
591
+ tenantId: string;
592
+ email: string;
593
+ roles: string[];
594
+ acceptUrl: string;
595
+ expiresAt: string;
596
+ emailSent: boolean;
597
+ redirectUri: string | null;
598
+ }
599
+ type TenantInviteStatus = "pending" | "accepted" | "revoked" | "expired";
600
+ interface TenantInvite {
601
+ id: string;
602
+ tenantId: string;
603
+ email: string;
604
+ roles: string[];
605
+ status: TenantInviteStatus;
606
+ createdAt: string;
607
+ expiresAt: string;
608
+ emailSentAt: string | null;
609
+ acceptedAt: string | null;
610
+ acceptedByUserId: string | null;
611
+ revokedAt: string | null;
612
+ invitedByUserId: string | null;
613
+ redirectUri: string | null;
614
+ }
615
+ /** What an accept page shows before the invitee commits. */
616
+ interface TenantInvitePreview {
617
+ tenantId: string;
618
+ tenantName: string;
619
+ email: string;
620
+ roles: string[];
621
+ expiresAt: string;
622
+ /** True: accepting only needs the token. False: send a password (and a username when `usernameRequired`). */
623
+ accountExists: boolean;
624
+ usernameRequired: boolean;
625
+ /** Where the issuer asked to send the invitee after accepting, or `null`. */
626
+ redirectUri: string | null;
627
+ }
628
+ /**
629
+ * Redeem an invite. For an address that already has an account only `token`
630
+ * and the metadata are used; the rest is for creating the account.
631
+ */
632
+ interface AcceptTenantInviteInput {
633
+ token: string;
634
+ username?: string;
635
+ password?: string;
636
+ firstName?: string;
637
+ lastName?: string;
638
+ /**
639
+ * @deprecated Use `publicMetadata` / `privateMetadata`. Still sent and
640
+ * validated against the environment's user field schema for now.
641
+ */
642
+ customFields?: Record<string, unknown>;
643
+ /**
644
+ * Replaces the user's public metadata (readable by the user). Requires the
645
+ * client credentials (`clientId`/`clientSecret`) with `authyon:users:write`:
646
+ * when this or `privateMetadata` is set, `accept` calls
647
+ * `POST /env/tenant-invites/accept` instead of the public route.
648
+ */
649
+ publicMetadata?: Record<string, unknown>;
650
+ /** Replaces the user's private metadata (server-only). Same requirement as `publicMetadata`. */
651
+ privateMetadata?: Record<string, unknown>;
652
+ }
653
+ interface TenantInviteAccepted {
654
+ tenantId: string;
655
+ tenantName: string;
656
+ userId: string;
657
+ accountCreated: boolean;
658
+ /** Where the issuer asked to send the invitee, or `null`. Redirecting is up to the accept page. */
659
+ redirectUri: string | null;
660
+ }
661
+
662
+ type QueryParams = object;
663
+
664
+ type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
665
+ interface JsonRequestOptions {
666
+ method?: HttpMethod;
667
+ body?: unknown;
668
+ query?: QueryParams;
669
+ headers?: Record<string, string>;
670
+ }
671
+
672
+ type ManagementRequest = <T>(path: string, options?: JsonRequestOptions) => Promise<T>;
673
+
674
+ /** Customer-side operations on an approval (`/auth/authorizations`). */
675
+ interface SubjectApprovals {
676
+ /** GET /auth/authorizations/{id} — the pending payload, to show before asking for the code. */
677
+ get(id: string): Promise<Approval>;
678
+ /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving it. */
679
+ webauthnOptions(id: string): Promise<ApprovalWebAuthnOptions>;
680
+ /**
681
+ * POST /auth/authorizations/{id}/confirm — approves it.
682
+ *
683
+ * Pass the authenticator code or passkey assertion to verify the second
684
+ * factor inline (recommended). Without `input`, the session itself must
685
+ * have used a passkey or authenticator code within the last 5 minutes,
686
+ * otherwise the API answers `step_up_required`.
687
+ */
688
+ confirm(id: string, input?: ConfirmApprovalInput): Promise<Approval>;
689
+ /** POST /auth/authorizations/{id}/reject — the customer declines it. */
690
+ reject(id: string): Promise<Approval>;
691
+ }
692
+ /** The `security` namespace an end-user client exposes. */
693
+ interface SubjectSecurity {
694
+ /**
695
+ * GET /auth/me — which security methods the signed-in user has active
696
+ * (password, authenticator, email code, passkeys, recovery codes, SSO).
697
+ */
698
+ methods(): Promise<SecurityMethods>;
699
+ /** Approve or reject what your backend asked the customer to confirm. */
700
+ readonly approvals: SubjectApprovals;
701
+ }
702
+
703
+ /** End-user operations require a user token and the environment publishable key. */
704
+ declare class UserScopedClient {
705
+ #private;
706
+ /** @hidden */
707
+ constructor(request: ManagementRequest, token: AccessTokenSource);
708
+ /**
709
+ * The customer's side of `security.approvals`, for backends (BFF) that hold
710
+ * the customer's access token: `get`, `webauthnOptions`, `confirm`, `reject`.
711
+ */
712
+ readonly security: SubjectSecurity;
713
+ readonly tenants: {
714
+ members: {
715
+ list: (tenantId: string, options?: PaginationOptions) => Promise<TenantMemberPage>;
716
+ /** Adds an existing environment user by email; does not send an invitation email. */
717
+ invite: (tenantId: string, input: InviteTenantMemberInput) => Promise<TenantMember>;
718
+ remove: (tenantId: string, userId: string) => Promise<void>;
719
+ };
720
+ /**
721
+ * Invites by e-mail or by link, acting as the user. Requires the
722
+ * `tenants:members:invite` permission on the tenant.
723
+ */
724
+ invites: {
725
+ list: (tenantId: string) => Promise<TenantInvite[]>;
726
+ /** Always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
727
+ create: (tenantId: string, input: TenantInviteInput) => Promise<TenantInviteIssued>;
728
+ /** New link (the previous one stops working), mailed unless `sendEmail` is `false`. */
729
+ resend: (tenantId: string, inviteId: string, input?: {
730
+ sendEmail?: boolean;
731
+ }) => Promise<TenantInviteIssued>;
732
+ revoke: (tenantId: string, inviteId: string) => Promise<void>;
733
+ };
734
+ };
735
+ }
736
+
737
+ /** `security.approvals.create()` — something awaiting the customer's approval. */
738
+ interface CreateApprovalInput {
739
+ /** Environment user who must approve. */
740
+ subjectId: string;
741
+ /** Any JSON object (up to 16 KiB) describing what is being approved. Default `{}`. */
742
+ payload?: ApprovalPayload;
743
+ /** Restrict approval to a session in this tenant. */
744
+ tenantId?: string;
745
+ /** Lifetime in seconds, clamped to 60–600. Default 300. */
746
+ expiresInSeconds?: number;
747
+ /**
748
+ * Optional. Sent as the `Idempotency-Key` header (max 128 chars): retrying
749
+ * with the same key and payload returns the same approval; the same key
750
+ * with a different payload fails with `idempotency_conflict`.
751
+ */
752
+ idempotencyKey?: string;
753
+ }
754
+ /** `security.approvals.consume()` — single-use redemption result. */
755
+ interface ConsumedApproval {
756
+ id: string;
757
+ status: "consumed";
758
+ consumedAt: string;
759
+ /** The approved payload — execute exactly this. */
760
+ payload: ApprovalPayload;
761
+ payloadHash: string;
762
+ assurance: ApprovalAssurance | null;
763
+ }
764
+ /** `security.otp.check()` result. */
765
+ type OtpCheckResult = {
766
+ valid: true;
767
+ userId: string;
768
+ /** Always `"otp"` (authenticator app). */
769
+ method: string;
770
+ verifiedAt: string;
771
+ } | {
772
+ valid: false;
773
+ /**
774
+ * Wrong codes left before the first consequence: the sign-out (3 in a
775
+ * row) or the 15-minute lock (5). `0` when the user was just signed out.
776
+ */
777
+ attemptsRemaining: number;
778
+ /**
779
+ * True when this was the 3rd wrong code in a row (counted across login
780
+ * 2FA, `security.otp.check` and `security.approvals.confirm`): every
781
+ * session of the user was ended and they must sign in again.
782
+ */
783
+ sessionsRevoked?: boolean;
784
+ };
785
+
786
+ interface ClientRequestContext {
787
+ /** Real end-user IP, resolved only from infrastructure trusted by the application. */
788
+ clientIp?: string;
789
+ }
790
+ /** Rejects header injection and values that are not a single IPv4 or IPv6 address. */
791
+ declare function normalizeClientIp(value: string): string;
792
+
793
+ type SafeJwtAlgorithm = "RS256" | "PS256" | "ES256" | "EdDSA";
794
+ interface AuthyonJwtClaims extends JWTPayload {
795
+ sub: string;
796
+ iss: string;
797
+ aud: string | string[];
798
+ exp: number;
799
+ iat: number;
800
+ email?: string;
801
+ username?: string;
802
+ roles?: string[];
803
+ permissions?: string[];
804
+ scope?: string;
805
+ }
806
+ interface VerifiedAccessToken {
807
+ claims: AuthyonJwtClaims;
808
+ protectedHeader: JWSHeaderParameters;
809
+ }
810
+ interface JwksTokenVerifierOptions {
811
+ /** Exact trusted issuer from Authyon OpenID discovery. */
812
+ issuer: string;
813
+ /** Audience assigned to the API consuming this token. */
814
+ audience: string | string[];
815
+ /** Trusted HTTPS JWKS endpoint. Never derive this value from the token header. */
816
+ jwksUri?: string;
817
+ /** Static trusted keys for pinned or offline verification. */
818
+ jwks?: JSONWebKeySet;
819
+ algorithms?: readonly SafeJwtAlgorithm[];
820
+ acceptedTokenTypes?: readonly string[];
821
+ clockToleranceSeconds?: number;
822
+ maxTokenAgeSeconds?: number;
823
+ jwksTimeoutMs?: number;
824
+ jwksCacheMs?: number;
825
+ jwksCooldownMs?: number;
826
+ }
827
+ interface AuthyonJwksDiscoveryOptions extends Omit<JwksTokenVerifierOptions, "issuer" | "jwksUri" | "jwks"> {
828
+ /** Optional pin; discovery fails if Authyon advertises a different issuer. */
829
+ issuer?: string;
830
+ /** Override the client environment key used by the discovery endpoint. */
831
+ publishableKey?: string;
832
+ }
833
+ type TokenVerificationErrorCode = "token.invalid" | "token.expired" | "token.not_active" | "token.invalid_claims" | "token.invalid_signature" | "token.key_unavailable";
834
+ declare class TokenVerificationError extends Error {
835
+ readonly code: TokenVerificationErrorCode;
836
+ constructor(code: TokenVerificationErrorCode, options?: {
837
+ cause?: unknown;
838
+ });
839
+ }
840
+ /** Secure, cached JWT signature and claims verifier backed by a trusted remote JWKS. */
841
+ declare class JwksTokenVerifier {
842
+ private readonly options;
843
+ private readonly verifyKey;
844
+ private readonly algorithms;
845
+ private readonly acceptedTokenTypes;
846
+ constructor(options: JwksTokenVerifierOptions);
847
+ verifyAccessToken(token: string): Promise<VerifiedAccessToken>;
848
+ }
849
+
850
+ /**
851
+ * Server-side Authyon client: environment/tenant administration (OAuth
852
+ * client-credentials) plus access-token verification (publishable key).
853
+ * Never import this in browser code — client secrets must stay on your
854
+ * server.
855
+ */
856
+ declare class AuthyonServerClient {
857
+ #private;
858
+ private readonly envKey?;
859
+ private readonly clientId?;
860
+ private readonly clientIp?;
861
+ private readonly transport;
862
+ private readonly http;
863
+ private readonly environmentTokenProvider;
864
+ constructor(options?: AuthyonServerClientOptions);
865
+ private request;
866
+ /** Mints (and caches) an environment access token from `clientId`/`clientSecret`. */
867
+ private getEnvironmentAccessToken;
868
+ readonly discovery: {
869
+ /** GET /.well-known/jwks.json — the environment's public signing keys. */
870
+ jwks: (publishableKey?: string) => Promise<JsonWebKeySet>;
871
+ /** GET /.well-known/openid-configuration — OIDC discovery document. */
872
+ openidConfiguration: (publishableKey?: string) => Promise<OpenIdConfiguration>;
873
+ };
874
+ /** Discovers Authyon's trusted issuer/JWKS and creates a cached local access-token verifier. */
875
+ createJwksTokenVerifier(options: AuthyonJwksDiscoveryOptions): Promise<JwksTokenVerifier>;
876
+ /** POST /auth/introspect — lightweight token introspection (RFC 7662). */
877
+ introspect(token: string, context?: ClientRequestContext): Promise<IntrospectResult>;
878
+ /** POST /auth/validate — recommended: cross-checks DB state, catches revocation immediately. */
879
+ validate(token: string, context?: ClientRequestContext): Promise<ValidateResult>;
880
+ readonly environmentAuth: {
881
+ /** POST /env/oauth/token — exchanges environment client credentials for an access token. */
882
+ token: (credentials: ClientCredentials) => Promise<TokenResult>;
883
+ };
884
+ readonly tenantAuth: {
885
+ /** POST /tenant/oauth/token — exchanges a tenant's client credentials for a scoped access token. */
886
+ token: (credentials: ClientCredentials) => Promise<TokenResult>;
887
+ /** POST /tenant/auth/validate — validates an already-minted tenant-client bearer token. */
888
+ validate: (accessToken: string, context?: ClientRequestContext) => Promise<TenantClientValidationResult>;
889
+ };
890
+ /**
891
+ * Scopes a client to a single tenant's OAuth credentials — mints and
892
+ * caches its access token independently of the environment plane. Use
893
+ * this for the `TenantManagement` endpoints (`/tenant/...`), which act on
894
+ * "the token's tenant" rather than one you pass by id.
895
+ */
896
+ tenant(credentials: ClientCredentials): TenantScopedClient;
897
+ /** Uses an end-user token; the configured environment key selects the environment. */
898
+ user(token: AccessTokenSource): UserScopedClient;
899
+ readonly environment: {
900
+ users: {
901
+ /** GET /env/users — paginated list of users in the environment. */
902
+ list: (params?: {
903
+ search?: string;
904
+ } & PaginationOptions) => Promise<Paged<EnvironmentUser>>;
905
+ /** POST /env/users — create a user in the environment; returns only the new id. */
906
+ create: (input: CreateUserInput) => Promise<{
907
+ id: string;
908
+ }>;
909
+ /** GET /env/users/{userId} — fetch an environment user by id. */
910
+ get: (userId: string) => Promise<EnvironmentUser>;
911
+ /** POST /env/users/{userId}/roles — grant a role to an environment user. */
912
+ assignRole: (userId: string, role: string) => Promise<void>;
913
+ /** DELETE /env/users/{userId}/roles/{role} — revoke a role from an environment user. */
914
+ removeRole: (userId: string, role: string) => Promise<void>;
915
+ /** POST /env/users/{userId}/permissions — grant a direct permission to an environment user. */
916
+ grantPermission: (userId: string, permission: string) => Promise<void>;
917
+ /** DELETE /env/users/{userId}/permissions/{permission} — revoke a direct permission. */
918
+ revokePermission: (userId: string, permission: string) => Promise<void>;
919
+ /** POST /env/users/{userId}/unlock — clears an environment user's lockout. */
920
+ unlock: (userId: string, reason?: string) => Promise<void>;
921
+ /** POST /env/users/{userId}/password — sets a new password for the user. */
922
+ setPassword: (userId: string, newPassword: string, reason?: string) => Promise<void>;
923
+ /**
924
+ * POST /env/password-resets — issues a password-reset token for the
925
+ * account with this address and returns it, so your application can
926
+ * deliver it in its own e-mail instead of Authyon's. Needs the
927
+ * `authyon:users:password` scope. Unlike the public forgot-password
928
+ * request, an unknown address rejects with `user.not_found` (404).
929
+ * A previous live token for the same account stops working.
930
+ */
931
+ issuePasswordReset: (input: IssuePasswordResetInput) => Promise<PasswordResetIssued>;
932
+ /**
933
+ * POST /auth/password-reset/validate — for a backend hosting the reset
934
+ * page: checks a token without spending it. Public, needs only the
935
+ * `envKey`. Rejects with `user.password_reset.invalid` (401) when the
936
+ * token is unknown, used or expired.
937
+ */
938
+ validatePasswordReset: (token: string) => Promise<PasswordResetPreview>;
939
+ /**
940
+ * POST /auth/password-reset/confirm — redeems the token and sets the new
941
+ * password (every session of the account is signed out). Public, needs
942
+ * only the `envKey`. Resolves with the `redirectUri` the reset was issued
943
+ * with, or `null`.
944
+ */
945
+ confirmPasswordReset: (token: string, newPassword: string) => Promise<PasswordResetCompleted>;
946
+ /** POST /env/users/{userId}/sessions/revoke-all — revokes every session the user has. */
947
+ revokeSessions: (userId: string, reason?: string) => Promise<void>;
948
+ /** DELETE /env/users/{userId}/sessions/{sessionId} — revokes a single session. */
949
+ revokeSession: (userId: string, sessionId: string, reason?: string) => Promise<void>;
950
+ /** POST /env/users/{userId}/disable — bans the user indefinitely; revokes live sessions. */
951
+ disable: (userId: string, reason?: string) => Promise<void>;
952
+ /** POST /env/users/{userId}/enable — lifts a ban. */
953
+ enable: (userId: string, reason?: string) => Promise<void>;
954
+ /** POST /env/users/{userId}/suspend — blocks the user temporarily; clears itself after `durationMinutes`. */
955
+ suspend: (userId: string, durationMinutes: number, reason?: string) => Promise<void>;
956
+ /** POST /env/users/{userId}/unsuspend — lifts a suspension early. */
957
+ unsuspend: (userId: string, reason?: string) => Promise<void>;
958
+ /** POST /env/users/{userId}/tenants — adds an environment user to a tenant. */
959
+ assignTenant: (userId: string, tenantId: string, roles?: string[]) => Promise<void>;
960
+ /** DELETE /env/users/{userId}/tenants/{tenantId} — removes an environment user from a tenant. */
961
+ removeTenant: (userId: string, tenantId: string) => Promise<void>;
962
+ };
963
+ tenants: {
964
+ credentials: {
965
+ /** GET /env/tenants/{tenantId}/credentials. Returns metadata only, including revoked credentials. */
966
+ list: (tenantId: string) => Promise<TenantCredentialSummary[]>;
967
+ /** Paginated searchable listing. Prefer this over loading every credential. */
968
+ listPage: (tenantId: string, options?: CredentialListOptions) => Promise<Paged<TenantCredentialSummary>>;
969
+ get: (tenantId: string, credentialId: string) => Promise<CredentialDetail>;
970
+ /** Explicit scopes/permissions; only issuance returns the client secret. */
971
+ create: (tenantId: string, input: CreateTenantCredentialInput | CreateCredentialInput) => Promise<TenantCredentialIssued>;
972
+ /** Returns a new secret once while keeping the same client id. */
973
+ rotate: (tenantId: string, credentialId: string) => Promise<TenantCredentialIssued>;
974
+ updatePermissions: (tenantId: string, credentialId: string, input: CredentialPermissionsInput) => Promise<void>;
975
+ updateScopes: (tenantId: string, credentialId: string, scopes: readonly string[]) => Promise<void>;
976
+ revoke: (tenantId: string, credentialId: string) => Promise<void>;
977
+ };
978
+ /**
979
+ * GET /env/tenants — one page of the environment's tenants.
980
+ *
981
+ * `search` matches, case-insensitively and anywhere in the value, the
982
+ * name, the slug, the description and the raw text of both metadata
983
+ * documents — so a tenant filed with `{"cnpj":"00.000.000/0001-00"}`
984
+ * is found by the number, and `cnpj` alone finds every tenant carrying
985
+ * that key. `take` defaults to 25 and is capped at 100.
986
+ *
987
+ * Against an Authyon API older than 2026-10-21 this route ignored
988
+ * skip/take/search and answered with a bare array.
989
+ */
990
+ list: (params?: {
991
+ search?: string;
992
+ } & PaginationOptions) => Promise<Paged<Organization>>;
993
+ /** POST /env/tenants — create a tenant in the environment. */
994
+ create: (input: CreateOrganizationInput) => Promise<Organization>;
995
+ /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
996
+ get: (tenantId: string) => Promise<Organization>;
997
+ /** PUT /env/tenants/{tenantId} — update a tenant. */
998
+ update: (tenantId: string, input: UpdateOrganizationInput) => Promise<Organization>;
999
+ /** PUT /env/tenants/{tenantId}/metadata - replace public and private metadata. */
1000
+ updateMetadata: (tenantId: string, input: Pick<CreateOrganizationInput, "publicMetadata" | "privateMetadata">) => Promise<void>;
1001
+ /** POST /env/tenants/{tenantId}/disable — disable without removing tenant data. */
1002
+ disable: (tenantId: string) => Promise<void>;
1003
+ /** DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant. */
1004
+ delete: (tenantId: string) => Promise<void>;
1005
+ members: {
1006
+ /**
1007
+ * GET /env/tenants/{tenantId}/members — a tenant's members as full
1008
+ * user records, with the same shape `environment.users.list()` items
1009
+ * have, plus `tenantRoles` and `tenantPermissions` scoped to this
1010
+ * tenant.
1011
+ *
1012
+ * Paged like every other list: the `Paged<T>` envelope carries
1013
+ * `total` and `hasNext`, `take` defaults to 50 and is capped at 100.
1014
+ * Up to the Authyon API of 2026-10-21 this one route answered with a
1015
+ * bare array, so a caller had to page until a short page came back;
1016
+ * against such an API `data` is undefined and the array is the body
1017
+ * itself.
1018
+ */
1019
+ list: (tenantId: string, params?: PaginationOptions) => Promise<Paged<EnvironmentUser>>;
1020
+ /** POST /env/tenants/{tenantId}/members — add a member to a tenant. */
1021
+ add: (tenantId: string, userId: string, roles?: string[]) => Promise<void>;
1022
+ /** DELETE /env/tenants/{tenantId}/members/{userId} — remove a member from a tenant. */
1023
+ remove: (tenantId: string, userId: string) => Promise<void>;
1024
+ /** POST /env/tenants/{tenantId}/members/{userId}/roles — grant a tenant role to a member. */
1025
+ assignRole: (tenantId: string, userId: string, role: string) => Promise<void>;
1026
+ /** DELETE .../members/{userId}/roles/{role} — revoke a tenant role from a member. */
1027
+ removeRole: (tenantId: string, userId: string, role: string) => Promise<void>;
1028
+ /** POST .../members/{userId}/permissions — grant a permission to a tenant member. */
1029
+ grantPermission: (tenantId: string, userId: string, permission: string) => Promise<void>;
1030
+ /** DELETE .../members/{userId}/permissions/{permission} — revoke a permission from a tenant member. */
1031
+ revokePermission: (tenantId: string, userId: string, permission: string) => Promise<void>;
1032
+ };
1033
+ /**
1034
+ * Invites by e-mail or by link — for addresses that may not have an
1035
+ * account yet; accepting creates it. Managing them needs the
1036
+ * credential's `authyon:users:write` scope (listing, `authyon:tenants:read`).
1037
+ */
1038
+ invites: {
1039
+ /** GET /env/tenants/{tenantId}/invites — every invite with its status, newest first. */
1040
+ list: (tenantId: string) => Promise<TenantInvite[]>;
1041
+ /**
1042
+ * POST /env/tenants/{tenantId}/invites — invite an address. Always
1043
+ * returns `acceptUrl`; with `sendEmail: false` Authyon does not mail
1044
+ * it and you deliver the link yourself. Valid 7 days, single use, and
1045
+ * not readable again later.
1046
+ */
1047
+ create: (tenantId: string, input: TenantInviteInput) => Promise<TenantInviteIssued>;
1048
+ /** POST .../invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
1049
+ resend: (tenantId: string, inviteId: string, input?: {
1050
+ sendEmail?: boolean;
1051
+ }) => Promise<TenantInviteIssued>;
1052
+ /** DELETE /env/tenants/{tenantId}/invites/{inviteId} — revoke a pending invite. */
1053
+ revoke: (tenantId: string, inviteId: string) => Promise<void>;
1054
+ /**
1055
+ * POST /auth/tenant-invites/preview — for a backend hosting the accept
1056
+ * page. Public: needs only `envKey`, the token is the credential.
1057
+ */
1058
+ preview: (token: string) => Promise<TenantInvitePreview>;
1059
+ /**
1060
+ * Joins the tenant; for an address with no account, also creates it
1061
+ * (password required) with the e-mail already confirmed. Does not
1062
+ * sign the user in.
1063
+ *
1064
+ * Without metadata: POST /auth/tenant-invites/accept — public, needs
1065
+ * only `envKey`. With `publicMetadata`/`privateMetadata`: POST
1066
+ * /env/tenant-invites/accept with the environment credential
1067
+ * (`authyon:users:write`), since only your backend may set them.
1068
+ */
1069
+ accept: (input: AcceptTenantInviteInput) => Promise<TenantInviteAccepted>;
1070
+ };
1071
+ roles: {
1072
+ /** GET /env/tenants/{tenantId}/roles — list a tenant's roles. */
1073
+ list: (tenantId: string) => Promise<Role[]>;
1074
+ /** POST /env/tenants/{tenantId}/roles — create a tenant role. */
1075
+ create: (tenantId: string, input: RoleInput) => Promise<Role>;
1076
+ /** GET /env/tenants/{tenantId}/roles/{roleId} — fetch a tenant role by id. */
1077
+ get: (tenantId: string, roleId: string) => Promise<Role>;
1078
+ /** PUT /env/tenants/{tenantId}/roles/{roleId} — update a tenant role. */
1079
+ update: (tenantId: string, roleId: string, input: RoleInput) => Promise<Role>;
1080
+ /** DELETE /env/tenants/{tenantId}/roles/{roleId} — delete a tenant role. */
1081
+ delete: (tenantId: string, roleId: string) => Promise<void>;
1082
+ };
1083
+ };
1084
+ roles: {
1085
+ /** GET /env/roles — environment-level roles, grouped into custom and system-defined. */
1086
+ list: () => Promise<RoleList>;
1087
+ /** POST /env/roles — create an environment-level role. */
1088
+ create: (input: RoleInput) => Promise<Role>;
1089
+ /** PUT /env/roles/{roleId} — update an environment-level role. */
1090
+ update: (roleId: string, input: RoleInput) => Promise<Role>;
1091
+ /** DELETE /env/roles/{roleId} — delete an environment-level role. */
1092
+ delete: (roleId: string) => Promise<void>;
1093
+ };
1094
+ permissions: {
1095
+ /** GET /env/permissions — environment-level permissions, grouped by the role they're attached to. */
1096
+ list: () => Promise<PermissionsByRole>;
1097
+ /** POST /env/permissions — create an environment-level permission. */
1098
+ create: (input: CreatePermissionInput) => Promise<Permission>;
1099
+ /** PUT /env/permissions/{permissionId} — update an environment-level permission. */
1100
+ update: (permissionId: string, description?: string) => Promise<Permission>;
1101
+ /** DELETE /env/permissions/{permissionId} — delete an environment-level permission. */
1102
+ delete: (permissionId: string) => Promise<void>;
1103
+ /** GET /permissions/reserved — reserved permission names you can't redefine. */
1104
+ reserved: () => Promise<ReservedPermissions>;
1105
+ };
1106
+ audit: {
1107
+ /** GET /env/audit — paginated list of the environment's audit events. */
1108
+ list: (params?: PaginationOptions) => Promise<Paged<AuditEvent>>;
1109
+ /** GET /env/audit/login-activity — paginated login activity in the environment. */
1110
+ loginActivity: (params?: PaginationOptions) => Promise<Paged<LoginActivity>>;
1111
+ };
1112
+ };
1113
+ readonly security: {
1114
+ otp: {
1115
+ /**
1116
+ * POST /env/users/{userId}/otp/verify — checks the user's authenticator
1117
+ * app (TOTP) code. A wrong code returns `{ valid: false }` instead of
1118
+ * throwing. Each code is accepted once; 3 wrong codes in a row sign the
1119
+ * user out everywhere (`sessionsRevoked: true`); 5 lock the check for 15
1120
+ * minutes (`rate_limited`). More than 50 wrong codes in 10 minutes from the
1121
+ * same credential pause it (`credential_throttled`). Needs `authyon:otp:verify`.
1122
+ */
1123
+ check: (userId: string, code: string) => Promise<OtpCheckResult>;
1124
+ };
1125
+ /**
1126
+ * The customer approves a payload with their authenticator code or
1127
+ * passkey, once.
1128
+ *
1129
+ * 1. `create()` the approval with the payload and the customer.
1130
+ * 2. The customer confirms it (`@authyon/auth` → `security.approvals.confirm`).
1131
+ * 3. `consume()` it right before executing, and execute the returned payload.
1132
+ */
1133
+ approvals: {
1134
+ /** POST /env/authorizations — registers a payload awaiting the customer's approval. */
1135
+ create: (input: CreateApprovalInput) => Promise<Approval>;
1136
+ /** GET /env/authorizations/{id} — current status and, once approved, the assurance evidence. */
1137
+ get: (id: string) => Promise<Approval>;
1138
+ /**
1139
+ * POST /env/authorizations/{id}/consume — redeems an approved approval
1140
+ * exactly once and returns the approved payload. Pass `payload` to have
1141
+ * the API check it matches (`payload_mismatch` otherwise).
1142
+ */
1143
+ consume: (id: string, payload?: ApprovalPayload) => Promise<ConsumedApproval>;
1144
+ };
1145
+ };
1146
+ readonly permissions: {
1147
+ /** POST /users/{userId}/permissions — grant a permission directly to a user. */
1148
+ grant: (userId: string, permission: string) => Promise<void>;
1149
+ /** DELETE /users/{userId}/permissions/{permission} — revoke a permission from a user. */
1150
+ revoke: (userId: string, permission: string) => Promise<void>;
1151
+ };
1152
+ /** @internal used by {@link TenantScopedClient} to share the base URL/fetch/error handling. */
1153
+ _requestAsTenant<T>(accessToken: string, path: string, options?: {
1154
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
1155
+ body?: unknown;
1156
+ query?: object;
1157
+ headers?: Record<string, string>;
1158
+ }): Promise<T>;
1159
+ }
1160
+ /**
1161
+ * Client scoped to a single tenant's OAuth credentials — every call acts on
1162
+ * "the token's tenant" (`TenantManagement` endpoints), so there's no
1163
+ * `tenantId` parameter to pass.
1164
+ */
1165
+ declare class TenantScopedClient {
1166
+ private readonly server;
1167
+ private readonly tokenProvider;
1168
+ constructor(server: AuthyonServerClient, credentials: ClientCredentials);
1169
+ private getAccessToken;
1170
+ private request;
1171
+ /** POST /tenant/auth/validate — validates this tenant client's current bearer token. */
1172
+ validate(context?: ClientRequestContext): Promise<TenantClientValidationResult>;
1173
+ /** Invites to the token's tenant, by e-mail or by link. */
1174
+ readonly invites: {
1175
+ /** GET /tenant/invites — every invite with its status, newest first. */
1176
+ list: () => Promise<TenantInvite[]>;
1177
+ /** POST /tenant/invites — always returns `acceptUrl`; `sendEmail: false` skips the e-mail. */
1178
+ create: (input: TenantInviteInput) => Promise<TenantInviteIssued>;
1179
+ /** POST /tenant/invites/{inviteId}/resend — new link (the previous one stops working), mailed unless `sendEmail` is `false`. */
1180
+ resend: (inviteId: string, input?: {
1181
+ sendEmail?: boolean;
1182
+ }) => Promise<TenantInviteIssued>;
1183
+ /** DELETE /tenant/invites/{inviteId} — revoke a pending invite. */
1184
+ revoke: (inviteId: string) => Promise<void>;
1185
+ };
1186
+ readonly members: {
1187
+ /**
1188
+ * GET /tenant/members — members of the token's tenant.
1189
+ *
1190
+ * Same handler as `/env/tenants/{id}/members` (the tenant comes from the
1191
+ * token instead of the path), so the same `Paged<T>` envelope of full
1192
+ * user records, `take` defaulting to 50 and capped at 100 — as opposed
1193
+ * to `/auth/tenants/{id}/members`'s lightweight member shape.
1194
+ */
1195
+ list: (params?: PaginationOptions) => Promise<Paged<EnvironmentUser>>;
1196
+ /** POST /tenant/members — add a member to the token's tenant. */
1197
+ add: (userId: string, roles?: string[]) => Promise<void>;
1198
+ /** DELETE /tenant/members/{userId} — remove a member from the token's tenant. */
1199
+ remove: (userId: string) => Promise<void>;
1200
+ /** POST /tenant/members/{userId}/roles — grant a role to a member of the tenant. */
1201
+ assignRole: (userId: string, role: string) => Promise<void>;
1202
+ /** DELETE /tenant/members/{userId}/roles/{role} — revoke a role from a member of the tenant. */
1203
+ removeRole: (userId: string, role: string) => Promise<void>;
1204
+ /** POST /tenant/members/{userId}/permissions — grant a permission to a member of the tenant. */
1205
+ grantPermission: (userId: string, permission: string) => Promise<void>;
1206
+ /** DELETE .../permissions/{permission} — revoke a permission from a member of the tenant. */
1207
+ revokePermission: (userId: string, permission: string) => Promise<void>;
1208
+ };
1209
+ readonly roles: {
1210
+ /**
1211
+ * GET /tenant/roles — roles in the token's tenant, grouped into custom
1212
+ * and system-defined.
1213
+ *
1214
+ * ⚠️ Inferred, not confirmed live (the test environment had no tenants
1215
+ * to exchange a scoped token for) — assumed to share `/env/roles`'
1216
+ * grouped shape, since both operate on the same underlying role model.
1217
+ */
1218
+ list: () => Promise<RoleList>;
1219
+ /** POST /tenant/roles — create a role in the tenant. */
1220
+ create: (input: RoleInput) => Promise<Role>;
1221
+ /** GET /tenant/roles/{roleId} — fetch a tenant role by id. */
1222
+ get: (roleId: string) => Promise<Role>;
1223
+ /** PUT /tenant/roles/{roleId} — update a role in the tenant. */
1224
+ update: (roleId: string, input: RoleInput) => Promise<Role>;
1225
+ /** DELETE /tenant/roles/{roleId} — delete a role in the tenant. */
1226
+ delete: (roleId: string) => Promise<void>;
1227
+ };
1228
+ }
1229
+ /** Convenience factory: `const authyon = createClient({ clientId, clientSecret })`. */
1230
+ declare function createClient(options?: AuthyonServerClientOptions): AuthyonServerClient;
1231
+
1232
+ export { type RoleGrant as $, AuthyonServerClient as A, type HttpLogEvent as B, type ClientCredentials as C, type HttpLogger as D, type EnvironmentUser as E, FetchHttpAdapter as F, type InviteTenantMemberInput as G, type HttpAdapter as H, type IntrospectResult as I, type IssuePasswordResetInput as J, type JsonWebKeySet as K, JwksTokenVerifier as L, type JwksTokenVerifierOptions as M, LoggingHttpAdapter as N, type LoginActivity as O, type OpenIdConfiguration as P, type Organization as Q, type OtpCheckResult as R, type Paged as S, type PaginationOptions as T, type PasswordResetCompleted as U, type PasswordResetIssued as V, type PasswordResetPreview as W, type Permission as X, type PermissionsByRole as Y, type ReservedPermissions as Z, type Role as _, type HttpLoggerOptions as a, type RoleInput as a0, type RoleList as a1, type RolePermissions as a2, type SafeJwtAlgorithm as a3, type SecurityMethods as a4, type SubjectApprovals as a5, type SubjectSecurity as a6, type TenantClientValidationResult as a7, type TenantCredentialIssued as a8, type TenantCredentialSummary as a9, type TenantInvite as aa, type TenantInviteAccepted as ab, type TenantInviteInput as ac, type TenantInviteIssued as ad, type TenantInvitePreview as ae, type TenantInviteStatus as af, type TenantMember as ag, type TenantMemberPage as ah, type TenantMembership as ai, TenantScopedClient as aj, type TokenResult as ak, TokenVerificationError as al, type TokenVerificationErrorCode as am, type UpdateOrganizationInput as an, type User as ao, UserScopedClient as ap, type ValidateResult as aq, type VerifiedAccessToken as ar, createClient as as, normalizeClientIp as at, type AcceptTenantInviteInput as b, type AccessTokenSource as c, type Approval as d, type ApprovalAssurance as e, type ApprovalPayload as f, type ApprovalStatus as g, type ApprovalWebAuthnOptions as h, type AuditEvent as i, type AuthyonJwksDiscoveryOptions as j, type AuthyonJwtClaims as k, type AuthyonServerClientOptions as l, type ClientRequestContext as m, type ConfirmApprovalInput as n, type ConsumedApproval as o, type CreateApprovalInput as p, type CreateCredentialInput as q, type CreateOrganizationInput as r, type CreatePermissionInput as s, type CreateTenantCredentialInput as t, type CreateUserInput as u, type CredentialCreator as v, type CredentialDetail as w, type CredentialListOptions as x, type CredentialPermissionsInput as y, type HttpAdapterRequest as z };