@authyon/server 0.2.0-beta.21 → 0.2.0-beta.22

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.
@@ -1,4 +1,4 @@
1
- import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.cjs';
1
+ import { J as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.cjs';
2
2
 
3
3
  type AbilitySubject = string | Record<string, unknown>;
4
4
  type AbilityConditions = Record<string, unknown>;
@@ -54,11 +54,25 @@ declare class AuthyonAbilityBuilder {
54
54
  }
55
55
  /** Creates an ability from Authyon permissions, OAuth scope and optional role rules. */
56
56
  declare function createAuthyonAbility(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AuthyonAbility;
57
- /** Checks an Authyon permission string using the same wildcard rules as an ability. */
57
+ /**
58
+ * Whether a source holds an Authyon permission, by Authyon's own rules: the
59
+ * values are compared segment by segment, `*` stands for any one segment, and
60
+ * two values of different lengths never match — except an all-wildcard grant,
61
+ * which is everything. OAuth scopes count as permissions.
62
+ *
63
+ * Not the same question as {@link AuthyonAbility.can}. An ability is CASL, so
64
+ * the action `manage` there means "every action on this subject", which is a
65
+ * useful thing to author by hand and a wrong thing to infer from a permission:
66
+ * `subtenants:tree:manage` and `subtenants:tree:switch` are deliberately
67
+ * separate grants on the API side — administering a sub-tenant from above and
68
+ * operating as it are different powers — and reading the first as the second
69
+ * would have this answer yes to a call the API then refuses. Ask this one
70
+ * about anything Authyon will be enforcing.
71
+ */
58
72
  declare function hasPermission(source: AuthyonPermissionSource | readonly string[], requiredPermission: string): boolean;
59
73
  /**
60
- * Checks a permission group using Authyon's standard permission and wildcard rules.
61
- * Empty or omitted groups do not add authorization requirements.
74
+ * Checks a permission group with {@link hasPermission}, so the same rules as
75
+ * the API. Empty or omitted groups do not add authorization requirements.
62
76
  */
63
77
  declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly string[], group: PermissionGroup): boolean;
64
78
  /** Converts Authyon's `subject:action` permission strings to authorization rules. */
@@ -1,4 +1,4 @@
1
- import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
1
+ import { J as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.js';
2
2
 
3
3
  type AbilitySubject = string | Record<string, unknown>;
4
4
  type AbilityConditions = Record<string, unknown>;
@@ -54,11 +54,25 @@ declare class AuthyonAbilityBuilder {
54
54
  }
55
55
  /** Creates an ability from Authyon permissions, OAuth scope and optional role rules. */
56
56
  declare function createAuthyonAbility(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AuthyonAbility;
57
- /** Checks an Authyon permission string using the same wildcard rules as an ability. */
57
+ /**
58
+ * Whether a source holds an Authyon permission, by Authyon's own rules: the
59
+ * values are compared segment by segment, `*` stands for any one segment, and
60
+ * two values of different lengths never match — except an all-wildcard grant,
61
+ * which is everything. OAuth scopes count as permissions.
62
+ *
63
+ * Not the same question as {@link AuthyonAbility.can}. An ability is CASL, so
64
+ * the action `manage` there means "every action on this subject", which is a
65
+ * useful thing to author by hand and a wrong thing to infer from a permission:
66
+ * `subtenants:tree:manage` and `subtenants:tree:switch` are deliberately
67
+ * separate grants on the API side — administering a sub-tenant from above and
68
+ * operating as it are different powers — and reading the first as the second
69
+ * would have this answer yes to a call the API then refuses. Ask this one
70
+ * about anything Authyon will be enforcing.
71
+ */
58
72
  declare function hasPermission(source: AuthyonPermissionSource | readonly string[], requiredPermission: string): boolean;
59
73
  /**
60
- * Checks a permission group using Authyon's standard permission and wildcard rules.
61
- * Empty or omitted groups do not add authorization requirements.
74
+ * Checks a permission group with {@link hasPermission}, so the same rules as
75
+ * the API. Empty or omitted groups do not add authorization requirements.
62
76
  */
63
77
  declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly string[], group: PermissionGroup): boolean;
64
78
  /** Converts Authyon's `subject:action` permission strings to authorization rules. */
@@ -226,6 +226,35 @@ interface Organization {
226
226
  publicMetadata?: string;
227
227
  /** JSON-encoded metadata available only through administrative APIs. */
228
228
  privateMetadata?: string;
229
+ /**
230
+ * The tenant this one sits under, or `null` for a root tenant. With `depth`
231
+ * it is what lets a flat page be rendered as the tree it describes.
232
+ *
233
+ * Absent on an API older than 2026-10-31, where every tenant was a root.
234
+ */
235
+ parentTenantId?: string | null;
236
+ /** Distance from the root: `0` for a root tenant. */
237
+ depth?: number;
238
+ /**
239
+ * Direct sub-tenants. A tree view expands only where this is above zero,
240
+ * instead of fetching every node to find out it has no children.
241
+ */
242
+ childCount?: number;
243
+ /** Custom roles defined inside the tenant. Only `get()` returns it. */
244
+ roleCount?: number;
245
+ /**
246
+ * The chain above this tenant, root first, excluding itself — a breadcrumb
247
+ * without a request per level. Empty for a root tenant, and only `get()`
248
+ * returns it.
249
+ */
250
+ ancestors?: TenantAncestor[];
251
+ }
252
+ /** One step of the chain above a tenant, as `Organization.ancestors` carries it. */
253
+ interface TenantAncestor {
254
+ id: string;
255
+ name: string;
256
+ slug: string;
257
+ isDisabled: boolean;
229
258
  }
230
259
  /**
231
260
  * What `environment.tenants.list()` accepts. `search` is the free-text half
@@ -236,6 +265,16 @@ interface Organization {
236
265
  interface TenantListOptions extends PaginationOptions {
237
266
  search?: string;
238
267
  filter?: TenantFilterExpression[];
268
+ /**
269
+ * Narrows the page to one level of the tree: a tenant id lists that tenant's
270
+ * direct sub-tenants, and `null` lists the roots. Omitted lists the
271
+ * environment's tenants regardless of depth — the behaviour from before the
272
+ * hierarchy existed, and still the right one for a flat picker.
273
+ *
274
+ * `search` and `filter` keep applying inside the level, so the envelope goes
275
+ * on describing what you asked for.
276
+ */
277
+ parentId?: string | null;
239
278
  }
240
279
  /** One of a user's tenant memberships, as embedded in `EnvironmentUser.tenantMemberships`. */
241
280
  interface TenantMembership {
@@ -383,6 +422,17 @@ interface CreateOrganizationInput {
383
422
  customFields?: Record<string, unknown>;
384
423
  publicMetadata?: Record<string, unknown>;
385
424
  privateMetadata?: Record<string, unknown>;
425
+ /**
426
+ * Creates the tenant underneath an existing one in the same environment.
427
+ * Omitted creates a root tenant.
428
+ *
429
+ * The environment's `maxTenantDepth` has to allow the level — it is `1` by
430
+ * default, which means roots only and refuses this with
431
+ * `tenant.depth.not_allowed` until an operator raises it. The new node counts
432
+ * against the plan's tenant cap like any other, so nesting cannot be used to
433
+ * get around it.
434
+ */
435
+ parentTenantId?: string;
386
436
  }
387
437
  interface UpdateOrganizationInput {
388
438
  name: string;
@@ -418,6 +468,12 @@ interface AuditEvent {
418
468
  environmentId?: string;
419
469
  actorUserId?: string | null;
420
470
  actorType?: string;
471
+ /**
472
+ * The address the event is recorded against — the vouched one when a machine
473
+ * credential named it. Where that differs from the socket peer, the peer is
474
+ * kept inside `payloadJson` as `peerIp`: which backend made the call is its
475
+ * own question, and the answer is not the caller's to choose.
476
+ */
421
477
  actorIp?: string;
422
478
  userAgent?: string;
423
479
  tenantId?: string | null;
@@ -512,8 +568,17 @@ interface AuthyonServerClientOptions {
512
568
  clientId?: string;
513
569
  clientSecret?: string;
514
570
  /**
515
- * Originating end-user IP to forward on every API call as `X-Forwarded-For`.
516
- * Only set this from infrastructure you trust; the SDK rejects comma-separated
571
+ * The end user's address, forwarded on every API call as
572
+ * `X-Authyon-Client-Ip` (and `X-Forwarded-For`, for your own proxies).
573
+ *
574
+ * Worth setting: a call from your backend has no browser in it, so without
575
+ * this every audit row Authyon writes for your integration names the
576
+ * container gateway, which identifies nobody. The API believes the header
577
+ * from a machine credential and records the address beside the event, where
578
+ * the console's IP filter can find it. It only ever changes the trail — no
579
+ * IP-keyed gate reads a vouched address.
580
+ *
581
+ * Only set it from infrastructure you trust; the SDK rejects comma-separated
517
582
  * or whitespace-containing values to avoid forwarded-header injection.
518
583
  */
519
584
  clientIp?: string;
@@ -834,10 +899,58 @@ interface ClientRequestContext {
834
899
  /** Real end-user IP, resolved only from infrastructure trusted by the application. */
835
900
  clientIp?: string;
836
901
  }
902
+ /**
903
+ * The header Authyon reads the real caller address from. `X-Forwarded-For` is
904
+ * not it: the API rewrites the socket peer from the edge proxy's chain and then
905
+ * resolves the client address from this header alone, so an address sent only
906
+ * in XFF is dropped before anything reads it.
907
+ */
908
+ declare const CLIENT_IP_HEADER = "X-Authyon-Client-Ip";
837
909
  /** Rejects header injection and values that are not a single IPv4 or IPv6 address. */
838
910
  declare function normalizeClientIp(value: string): string;
839
911
 
840
912
  type SafeJwtAlgorithm = "RS256" | "PS256" | "ES256" | "EdDSA";
913
+ /**
914
+ * The active tenant, as the `tenant` claim carries it. Present only on a
915
+ * session scoped to one — a token minted before any tenant switch has no
916
+ * tenant and no claim.
917
+ *
918
+ * Snake_case because these are wire names, not SDK ones: the claim is signed,
919
+ * and renaming its fields on the way in would hide what was actually asserted.
920
+ */
921
+ interface AuthyonTenantClaim {
922
+ id: string;
923
+ slug: string;
924
+ name: string;
925
+ /** The tenant above this one, or `null` at a root. */
926
+ parent_id?: string | null;
927
+ /**
928
+ * The materialised chain from the root down to this tenant. Signed, so a
929
+ * consumer can answer "is that tenant under mine?" with a prefix comparison
930
+ * and no round trip — which is the whole reason it is in the token.
931
+ */
932
+ path?: string;
933
+ /** Distance from the root: `0` at a root tenant. */
934
+ depth?: number;
935
+ /**
936
+ * Version of `path`. A tenant that gets moved bumps it, which is what makes
937
+ * the signed path safe to trust: a token minted before the move no longer
938
+ * matches and the API refuses it with `tenant.path_stale`, instead of
939
+ * letting a stale prefix keep answering yes.
940
+ */
941
+ pv?: number;
942
+ roles?: string[];
943
+ /** Effective permissions AT this tenant. */
944
+ permissions?: string[];
945
+ /**
946
+ * Set only when the session descended into this tenant from an ancestor,
947
+ * naming the node the permissions came from — the user holds no membership
948
+ * here. Treat it as borrowed authority if that matters to you (a banner, a
949
+ * tighter trail, a refusal); ignore it and you have a session scoped to a
950
+ * tenant, which is what it is. Absent on any other session.
951
+ */
952
+ via?: string | null;
953
+ }
841
954
  interface AuthyonJwtClaims extends JWTPayload {
842
955
  sub: string;
843
956
  iss: string;
@@ -849,6 +962,8 @@ interface AuthyonJwtClaims extends JWTPayload {
849
962
  roles?: string[];
850
963
  permissions?: string[];
851
964
  scope?: string;
965
+ /** The active tenant and the grants held inside it. Absent until a switch. */
966
+ tenant?: AuthyonTenantClaim;
852
967
  }
853
968
  interface VerifiedAccessToken {
854
969
  claims: AuthyonJwtClaims;
@@ -1048,23 +1163,66 @@ declare class AuthyonServerClient {
1048
1163
  * });
1049
1164
  * ```
1050
1165
  *
1166
+ * `parentId` narrows the page to one level of the tree — `children()`
1167
+ * and `roots()` below are the same call with that one option set.
1168
+ *
1051
1169
  * Against an Authyon API older than 2026-10-21 this route ignored
1052
1170
  * skip/take/search and answered with a bare array; one older than
1053
- * 2026-10-22 ignores `filter`, which reads as a page that is too wide
1054
- * rather than an error.
1171
+ * 2026-10-22 ignores `filter` and one older than 2026-10-31 ignores
1172
+ * `parentId`, which read as a page that is too wide rather than an error.
1055
1173
  */
1056
1174
  list: (params?: TenantListOptions) => Promise<Paged<Organization>>;
1057
- /** POST /env/tenants — create a tenant in the environment. */
1175
+ /**
1176
+ * One page of a tenant's direct sub-tenants — `list()` with `parentId`.
1177
+ *
1178
+ * Only one level: a node's own children carry `childCount`, so a tree
1179
+ * view asks again where that is above zero instead of reading the whole
1180
+ * subtree to draw the first level of it.
1181
+ */
1182
+ children: (parentTenantId: string, params?: Omit<TenantListOptions, "parentId">) => Promise<Paged<Organization>>;
1183
+ /**
1184
+ * One page of the environment's root tenants — `list()` with no parent.
1185
+ *
1186
+ * This is the first level of the tree, and the difference from `list()`
1187
+ * is worth keeping straight: `list()` returns every tenant at every
1188
+ * depth, which is what a flat picker wants and what a tree view must not
1189
+ * start from.
1190
+ */
1191
+ roots: (params?: Omit<TenantListOptions, "parentId">) => Promise<Paged<Organization>>;
1192
+ /**
1193
+ * POST /env/tenants — create a tenant in the environment.
1194
+ *
1195
+ * `parentTenantId` nests it under an existing tenant. The environment's
1196
+ * `maxTenantDepth` has to allow the level — it ships as `1`, roots only,
1197
+ * so this answers `tenant.depth.not_allowed` until an operator raises it
1198
+ * in the console.
1199
+ */
1058
1200
  create: (input: CreateOrganizationInput) => Promise<Organization>;
1059
- /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
1201
+ /**
1202
+ * GET /env/tenants/{tenantId} — fetch a tenant by id.
1203
+ *
1204
+ * Returns `ancestors` as well, the chain above it root first, so a
1205
+ * breadcrumb costs this one call rather than one per level.
1206
+ */
1060
1207
  get: (tenantId: string) => Promise<Organization>;
1061
1208
  /** PUT /env/tenants/{tenantId} — update a tenant. */
1062
1209
  update: (tenantId: string, input: UpdateOrganizationInput) => Promise<Organization>;
1063
1210
  /** PUT /env/tenants/{tenantId}/metadata - replace public and private metadata. */
1064
1211
  updateMetadata: (tenantId: string, input: Pick<CreateOrganizationInput, "publicMetadata" | "privateMetadata">) => Promise<void>;
1065
- /** POST /env/tenants/{tenantId}/disable — disable without removing tenant data. */
1212
+ /**
1213
+ * POST /env/tenants/{tenantId}/disable — disable without removing tenant
1214
+ * data.
1215
+ *
1216
+ * Disables the branch below it too. A sub-tenant left live under a
1217
+ * disabled parent would go on authenticating its users, which is the one
1218
+ * thing switching a tenant off is there to stop — so check `childCount`
1219
+ * before calling this on a node with children.
1220
+ */
1066
1221
  disable: (tenantId: string) => Promise<void>;
1067
- /** DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant. */
1222
+ /**
1223
+ * DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant,
1224
+ * and the branch below it. Same handler as `disable()`.
1225
+ */
1068
1226
  delete: (tenantId: string) => Promise<void>;
1069
1227
  members: {
1070
1228
  /**
@@ -1293,4 +1451,4 @@ declare class TenantScopedClient {
1293
1451
  /** Convenience factory: `const authyon = createClient({ clientId, clientSecret })`. */
1294
1452
  declare function createClient(options?: AuthyonServerClientOptions): AuthyonServerClient;
1295
1453
 
1296
- 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, TENANT_FILTER_MAX_DEPTH as a7, TENANT_FILTER_MAX_VALUES as a8, TENANT_FILTER_MAX_VALUE_LENGTH as a9, tenantFilter as aA, type TenantClientValidationResult as aa, type TenantCredentialIssued as ab, type TenantCredentialSummary as ac, type TenantFilterExpression as ad, type TenantFilterValue as ae, type TenantInvite as af, type TenantInviteAccepted as ag, type TenantInviteInput as ah, type TenantInviteIssued as ai, type TenantInvitePreview as aj, type TenantInviteStatus as ak, type TenantListOptions as al, type TenantMember as am, type TenantMemberPage as an, type TenantMembership as ao, TenantScopedClient as ap, type TokenResult as aq, TokenVerificationError as ar, type TokenVerificationErrorCode as as, type UpdateOrganizationInput as at, type User as au, UserScopedClient as av, type ValidateResult as aw, type VerifiedAccessToken as ax, createClient as ay, normalizeClientIp as az, 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 };
1454
+ export { type ReservedPermissions as $, AuthyonServerClient as A, type CredentialPermissionsInput as B, CLIENT_IP_HEADER as C, type HttpAdapterRequest as D, type EnvironmentUser as E, FetchHttpAdapter as F, type HttpLogEvent as G, type HttpAdapter as H, type HttpLogger as I, JwksTokenVerifier as J, type IntrospectResult as K, type InviteTenantMemberInput as L, type IssuePasswordResetInput as M, type JsonWebKeySet as N, type JwksTokenVerifierOptions as O, LoggingHttpAdapter as P, type LoginActivity as Q, type OpenIdConfiguration as R, type Organization as S, type OtpCheckResult as T, type Paged as U, type PaginationOptions as V, type PasswordResetCompleted as W, type PasswordResetIssued as X, type PasswordResetPreview as Y, type Permission as Z, type PermissionsByRole as _, type HttpLoggerOptions as a, type Role as a0, type RoleGrant as a1, type RoleInput as a2, type RoleList as a3, type RolePermissions as a4, type SafeJwtAlgorithm as a5, type SecurityMethods as a6, type SubjectApprovals as a7, type SubjectSecurity as a8, TENANT_FILTER_MAX_DEPTH as a9, type VerifiedAccessToken as aA, createClient as aB, normalizeClientIp as aC, tenantFilter as aD, TENANT_FILTER_MAX_VALUES as aa, TENANT_FILTER_MAX_VALUE_LENGTH as ab, type TenantAncestor as ac, type TenantClientValidationResult as ad, type TenantCredentialIssued as ae, type TenantCredentialSummary as af, type TenantFilterExpression as ag, type TenantFilterValue as ah, type TenantInvite as ai, type TenantInviteAccepted as aj, type TenantInviteInput as ak, type TenantInviteIssued as al, type TenantInvitePreview as am, type TenantInviteStatus as an, type TenantListOptions as ao, type TenantMember as ap, type TenantMemberPage as aq, type TenantMembership as ar, TenantScopedClient as as, type TokenResult as at, TokenVerificationError as au, type TokenVerificationErrorCode as av, type UpdateOrganizationInput as aw, type User as ax, UserScopedClient as ay, type ValidateResult as az, 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 AuthyonTenantClaim as m, type ClientCredentials as n, type ClientRequestContext as o, type ConfirmApprovalInput as p, type ConsumedApproval as q, type CreateApprovalInput as r, type CreateCredentialInput as s, type CreateOrganizationInput as t, type CreatePermissionInput as u, type CreateTenantCredentialInput as v, type CreateUserInput as w, type CredentialCreator as x, type CredentialDetail as y, type CredentialListOptions as z };
@@ -226,6 +226,35 @@ interface Organization {
226
226
  publicMetadata?: string;
227
227
  /** JSON-encoded metadata available only through administrative APIs. */
228
228
  privateMetadata?: string;
229
+ /**
230
+ * The tenant this one sits under, or `null` for a root tenant. With `depth`
231
+ * it is what lets a flat page be rendered as the tree it describes.
232
+ *
233
+ * Absent on an API older than 2026-10-31, where every tenant was a root.
234
+ */
235
+ parentTenantId?: string | null;
236
+ /** Distance from the root: `0` for a root tenant. */
237
+ depth?: number;
238
+ /**
239
+ * Direct sub-tenants. A tree view expands only where this is above zero,
240
+ * instead of fetching every node to find out it has no children.
241
+ */
242
+ childCount?: number;
243
+ /** Custom roles defined inside the tenant. Only `get()` returns it. */
244
+ roleCount?: number;
245
+ /**
246
+ * The chain above this tenant, root first, excluding itself — a breadcrumb
247
+ * without a request per level. Empty for a root tenant, and only `get()`
248
+ * returns it.
249
+ */
250
+ ancestors?: TenantAncestor[];
251
+ }
252
+ /** One step of the chain above a tenant, as `Organization.ancestors` carries it. */
253
+ interface TenantAncestor {
254
+ id: string;
255
+ name: string;
256
+ slug: string;
257
+ isDisabled: boolean;
229
258
  }
230
259
  /**
231
260
  * What `environment.tenants.list()` accepts. `search` is the free-text half
@@ -236,6 +265,16 @@ interface Organization {
236
265
  interface TenantListOptions extends PaginationOptions {
237
266
  search?: string;
238
267
  filter?: TenantFilterExpression[];
268
+ /**
269
+ * Narrows the page to one level of the tree: a tenant id lists that tenant's
270
+ * direct sub-tenants, and `null` lists the roots. Omitted lists the
271
+ * environment's tenants regardless of depth — the behaviour from before the
272
+ * hierarchy existed, and still the right one for a flat picker.
273
+ *
274
+ * `search` and `filter` keep applying inside the level, so the envelope goes
275
+ * on describing what you asked for.
276
+ */
277
+ parentId?: string | null;
239
278
  }
240
279
  /** One of a user's tenant memberships, as embedded in `EnvironmentUser.tenantMemberships`. */
241
280
  interface TenantMembership {
@@ -383,6 +422,17 @@ interface CreateOrganizationInput {
383
422
  customFields?: Record<string, unknown>;
384
423
  publicMetadata?: Record<string, unknown>;
385
424
  privateMetadata?: Record<string, unknown>;
425
+ /**
426
+ * Creates the tenant underneath an existing one in the same environment.
427
+ * Omitted creates a root tenant.
428
+ *
429
+ * The environment's `maxTenantDepth` has to allow the level — it is `1` by
430
+ * default, which means roots only and refuses this with
431
+ * `tenant.depth.not_allowed` until an operator raises it. The new node counts
432
+ * against the plan's tenant cap like any other, so nesting cannot be used to
433
+ * get around it.
434
+ */
435
+ parentTenantId?: string;
386
436
  }
387
437
  interface UpdateOrganizationInput {
388
438
  name: string;
@@ -418,6 +468,12 @@ interface AuditEvent {
418
468
  environmentId?: string;
419
469
  actorUserId?: string | null;
420
470
  actorType?: string;
471
+ /**
472
+ * The address the event is recorded against — the vouched one when a machine
473
+ * credential named it. Where that differs from the socket peer, the peer is
474
+ * kept inside `payloadJson` as `peerIp`: which backend made the call is its
475
+ * own question, and the answer is not the caller's to choose.
476
+ */
421
477
  actorIp?: string;
422
478
  userAgent?: string;
423
479
  tenantId?: string | null;
@@ -512,8 +568,17 @@ interface AuthyonServerClientOptions {
512
568
  clientId?: string;
513
569
  clientSecret?: string;
514
570
  /**
515
- * Originating end-user IP to forward on every API call as `X-Forwarded-For`.
516
- * Only set this from infrastructure you trust; the SDK rejects comma-separated
571
+ * The end user's address, forwarded on every API call as
572
+ * `X-Authyon-Client-Ip` (and `X-Forwarded-For`, for your own proxies).
573
+ *
574
+ * Worth setting: a call from your backend has no browser in it, so without
575
+ * this every audit row Authyon writes for your integration names the
576
+ * container gateway, which identifies nobody. The API believes the header
577
+ * from a machine credential and records the address beside the event, where
578
+ * the console's IP filter can find it. It only ever changes the trail — no
579
+ * IP-keyed gate reads a vouched address.
580
+ *
581
+ * Only set it from infrastructure you trust; the SDK rejects comma-separated
517
582
  * or whitespace-containing values to avoid forwarded-header injection.
518
583
  */
519
584
  clientIp?: string;
@@ -834,10 +899,58 @@ interface ClientRequestContext {
834
899
  /** Real end-user IP, resolved only from infrastructure trusted by the application. */
835
900
  clientIp?: string;
836
901
  }
902
+ /**
903
+ * The header Authyon reads the real caller address from. `X-Forwarded-For` is
904
+ * not it: the API rewrites the socket peer from the edge proxy's chain and then
905
+ * resolves the client address from this header alone, so an address sent only
906
+ * in XFF is dropped before anything reads it.
907
+ */
908
+ declare const CLIENT_IP_HEADER = "X-Authyon-Client-Ip";
837
909
  /** Rejects header injection and values that are not a single IPv4 or IPv6 address. */
838
910
  declare function normalizeClientIp(value: string): string;
839
911
 
840
912
  type SafeJwtAlgorithm = "RS256" | "PS256" | "ES256" | "EdDSA";
913
+ /**
914
+ * The active tenant, as the `tenant` claim carries it. Present only on a
915
+ * session scoped to one — a token minted before any tenant switch has no
916
+ * tenant and no claim.
917
+ *
918
+ * Snake_case because these are wire names, not SDK ones: the claim is signed,
919
+ * and renaming its fields on the way in would hide what was actually asserted.
920
+ */
921
+ interface AuthyonTenantClaim {
922
+ id: string;
923
+ slug: string;
924
+ name: string;
925
+ /** The tenant above this one, or `null` at a root. */
926
+ parent_id?: string | null;
927
+ /**
928
+ * The materialised chain from the root down to this tenant. Signed, so a
929
+ * consumer can answer "is that tenant under mine?" with a prefix comparison
930
+ * and no round trip — which is the whole reason it is in the token.
931
+ */
932
+ path?: string;
933
+ /** Distance from the root: `0` at a root tenant. */
934
+ depth?: number;
935
+ /**
936
+ * Version of `path`. A tenant that gets moved bumps it, which is what makes
937
+ * the signed path safe to trust: a token minted before the move no longer
938
+ * matches and the API refuses it with `tenant.path_stale`, instead of
939
+ * letting a stale prefix keep answering yes.
940
+ */
941
+ pv?: number;
942
+ roles?: string[];
943
+ /** Effective permissions AT this tenant. */
944
+ permissions?: string[];
945
+ /**
946
+ * Set only when the session descended into this tenant from an ancestor,
947
+ * naming the node the permissions came from — the user holds no membership
948
+ * here. Treat it as borrowed authority if that matters to you (a banner, a
949
+ * tighter trail, a refusal); ignore it and you have a session scoped to a
950
+ * tenant, which is what it is. Absent on any other session.
951
+ */
952
+ via?: string | null;
953
+ }
841
954
  interface AuthyonJwtClaims extends JWTPayload {
842
955
  sub: string;
843
956
  iss: string;
@@ -849,6 +962,8 @@ interface AuthyonJwtClaims extends JWTPayload {
849
962
  roles?: string[];
850
963
  permissions?: string[];
851
964
  scope?: string;
965
+ /** The active tenant and the grants held inside it. Absent until a switch. */
966
+ tenant?: AuthyonTenantClaim;
852
967
  }
853
968
  interface VerifiedAccessToken {
854
969
  claims: AuthyonJwtClaims;
@@ -1048,23 +1163,66 @@ declare class AuthyonServerClient {
1048
1163
  * });
1049
1164
  * ```
1050
1165
  *
1166
+ * `parentId` narrows the page to one level of the tree — `children()`
1167
+ * and `roots()` below are the same call with that one option set.
1168
+ *
1051
1169
  * Against an Authyon API older than 2026-10-21 this route ignored
1052
1170
  * skip/take/search and answered with a bare array; one older than
1053
- * 2026-10-22 ignores `filter`, which reads as a page that is too wide
1054
- * rather than an error.
1171
+ * 2026-10-22 ignores `filter` and one older than 2026-10-31 ignores
1172
+ * `parentId`, which read as a page that is too wide rather than an error.
1055
1173
  */
1056
1174
  list: (params?: TenantListOptions) => Promise<Paged<Organization>>;
1057
- /** POST /env/tenants — create a tenant in the environment. */
1175
+ /**
1176
+ * One page of a tenant's direct sub-tenants — `list()` with `parentId`.
1177
+ *
1178
+ * Only one level: a node's own children carry `childCount`, so a tree
1179
+ * view asks again where that is above zero instead of reading the whole
1180
+ * subtree to draw the first level of it.
1181
+ */
1182
+ children: (parentTenantId: string, params?: Omit<TenantListOptions, "parentId">) => Promise<Paged<Organization>>;
1183
+ /**
1184
+ * One page of the environment's root tenants — `list()` with no parent.
1185
+ *
1186
+ * This is the first level of the tree, and the difference from `list()`
1187
+ * is worth keeping straight: `list()` returns every tenant at every
1188
+ * depth, which is what a flat picker wants and what a tree view must not
1189
+ * start from.
1190
+ */
1191
+ roots: (params?: Omit<TenantListOptions, "parentId">) => Promise<Paged<Organization>>;
1192
+ /**
1193
+ * POST /env/tenants — create a tenant in the environment.
1194
+ *
1195
+ * `parentTenantId` nests it under an existing tenant. The environment's
1196
+ * `maxTenantDepth` has to allow the level — it ships as `1`, roots only,
1197
+ * so this answers `tenant.depth.not_allowed` until an operator raises it
1198
+ * in the console.
1199
+ */
1058
1200
  create: (input: CreateOrganizationInput) => Promise<Organization>;
1059
- /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
1201
+ /**
1202
+ * GET /env/tenants/{tenantId} — fetch a tenant by id.
1203
+ *
1204
+ * Returns `ancestors` as well, the chain above it root first, so a
1205
+ * breadcrumb costs this one call rather than one per level.
1206
+ */
1060
1207
  get: (tenantId: string) => Promise<Organization>;
1061
1208
  /** PUT /env/tenants/{tenantId} — update a tenant. */
1062
1209
  update: (tenantId: string, input: UpdateOrganizationInput) => Promise<Organization>;
1063
1210
  /** PUT /env/tenants/{tenantId}/metadata - replace public and private metadata. */
1064
1211
  updateMetadata: (tenantId: string, input: Pick<CreateOrganizationInput, "publicMetadata" | "privateMetadata">) => Promise<void>;
1065
- /** POST /env/tenants/{tenantId}/disable — disable without removing tenant data. */
1212
+ /**
1213
+ * POST /env/tenants/{tenantId}/disable — disable without removing tenant
1214
+ * data.
1215
+ *
1216
+ * Disables the branch below it too. A sub-tenant left live under a
1217
+ * disabled parent would go on authenticating its users, which is the one
1218
+ * thing switching a tenant off is there to stop — so check `childCount`
1219
+ * before calling this on a node with children.
1220
+ */
1066
1221
  disable: (tenantId: string) => Promise<void>;
1067
- /** DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant. */
1222
+ /**
1223
+ * DELETE /env/tenants/{tenantId} — logically delete (disable) a tenant,
1224
+ * and the branch below it. Same handler as `disable()`.
1225
+ */
1068
1226
  delete: (tenantId: string) => Promise<void>;
1069
1227
  members: {
1070
1228
  /**
@@ -1293,4 +1451,4 @@ declare class TenantScopedClient {
1293
1451
  /** Convenience factory: `const authyon = createClient({ clientId, clientSecret })`. */
1294
1452
  declare function createClient(options?: AuthyonServerClientOptions): AuthyonServerClient;
1295
1453
 
1296
- 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, TENANT_FILTER_MAX_DEPTH as a7, TENANT_FILTER_MAX_VALUES as a8, TENANT_FILTER_MAX_VALUE_LENGTH as a9, tenantFilter as aA, type TenantClientValidationResult as aa, type TenantCredentialIssued as ab, type TenantCredentialSummary as ac, type TenantFilterExpression as ad, type TenantFilterValue as ae, type TenantInvite as af, type TenantInviteAccepted as ag, type TenantInviteInput as ah, type TenantInviteIssued as ai, type TenantInvitePreview as aj, type TenantInviteStatus as ak, type TenantListOptions as al, type TenantMember as am, type TenantMemberPage as an, type TenantMembership as ao, TenantScopedClient as ap, type TokenResult as aq, TokenVerificationError as ar, type TokenVerificationErrorCode as as, type UpdateOrganizationInput as at, type User as au, UserScopedClient as av, type ValidateResult as aw, type VerifiedAccessToken as ax, createClient as ay, normalizeClientIp as az, 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 };
1454
+ export { type ReservedPermissions as $, AuthyonServerClient as A, type CredentialPermissionsInput as B, CLIENT_IP_HEADER as C, type HttpAdapterRequest as D, type EnvironmentUser as E, FetchHttpAdapter as F, type HttpLogEvent as G, type HttpAdapter as H, type HttpLogger as I, JwksTokenVerifier as J, type IntrospectResult as K, type InviteTenantMemberInput as L, type IssuePasswordResetInput as M, type JsonWebKeySet as N, type JwksTokenVerifierOptions as O, LoggingHttpAdapter as P, type LoginActivity as Q, type OpenIdConfiguration as R, type Organization as S, type OtpCheckResult as T, type Paged as U, type PaginationOptions as V, type PasswordResetCompleted as W, type PasswordResetIssued as X, type PasswordResetPreview as Y, type Permission as Z, type PermissionsByRole as _, type HttpLoggerOptions as a, type Role as a0, type RoleGrant as a1, type RoleInput as a2, type RoleList as a3, type RolePermissions as a4, type SafeJwtAlgorithm as a5, type SecurityMethods as a6, type SubjectApprovals as a7, type SubjectSecurity as a8, TENANT_FILTER_MAX_DEPTH as a9, type VerifiedAccessToken as aA, createClient as aB, normalizeClientIp as aC, tenantFilter as aD, TENANT_FILTER_MAX_VALUES as aa, TENANT_FILTER_MAX_VALUE_LENGTH as ab, type TenantAncestor as ac, type TenantClientValidationResult as ad, type TenantCredentialIssued as ae, type TenantCredentialSummary as af, type TenantFilterExpression as ag, type TenantFilterValue as ah, type TenantInvite as ai, type TenantInviteAccepted as aj, type TenantInviteInput as ak, type TenantInviteIssued as al, type TenantInvitePreview as am, type TenantInviteStatus as an, type TenantListOptions as ao, type TenantMember as ap, type TenantMemberPage as aq, type TenantMembership as ar, TenantScopedClient as as, type TokenResult as at, TokenVerificationError as au, type TokenVerificationErrorCode as av, type UpdateOrganizationInput as aw, type User as ax, UserScopedClient as ay, type ValidateResult as az, 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 AuthyonTenantClaim as m, type ClientCredentials as n, type ClientRequestContext as o, type ConfirmApprovalInput as p, type ConsumedApproval as q, type CreateApprovalInput as r, type CreateCredentialInput as s, type CreateOrganizationInput as t, type CreatePermissionInput as u, type CreateTenantCredentialInput as v, type CreateUserInput as w, type CredentialCreator as x, type CredentialDetail as y, type CredentialListOptions as z };
package/dist/bff.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.cjs';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.cjs';
2
2
  import 'jose';
3
3
 
4
4
  interface BffLoginInput {
package/dist/bff.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-CW46xIRD.js';
2
2
  import 'jose';
3
3
 
4
4
  interface BffLoginInput {