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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -359,6 +359,39 @@ completa. A concessão OAuth continua recebendo apenas `clientId`/`clientSecret`
359
359
  Todas as operações usam os endpoints externos `/env` com a credencial de
360
360
  ambiente configurada no cliente. O SDK não repete mutações automaticamente.
361
361
 
362
+ ## Filtros do tenant
363
+
364
+ `search` é um substring só, ORado entre nome, slug, descrição e os dois metadata.
365
+ Quando mais de uma condição precisa valer — `kind IN (...) AND cnpj IN (...)` — use
366
+ `filter`, que roda dentro da consulta e por isso continua paginando:
367
+
368
+ ```ts
369
+ import { tenantFilter } from "@authyon/server";
370
+
371
+ const page = await authyon.environment.tenants.list({
372
+ filter: [
373
+ tenantFilter.in("public.kind", ["reseller", "partner"]),
374
+ tenantFilter.in("custom.cnpj", ["00000000000100", "11111111000199"]),
375
+ ],
376
+ take: 100,
377
+ });
378
+
379
+ page.total; // quantos casam com o filtro, não quantos existem no ambiente
380
+ ```
381
+
382
+ Cada entrada é uma condição; várias são ANDadas entre si e com o `search`, e a
383
+ vírgula dentro de um `in` é o OR. Os escopos são `public` (publicMetadata),
384
+ `private` (privateMetadata) e `custom` (customFields — este o `search` nunca
385
+ cobriu). Operadores: `eq`, `in`, `like` (ILIKE, com os metacaracteres escapados)
386
+ e `exists`. Caminho aninhado vale até três níveis: `private.billing.plan`.
387
+
388
+ O construtor valida antes de sair: escopo desconhecido, chave com espaço, mais de
389
+ 25 valores num `in` ou vírgula dentro de um valor levantam `RangeError` em vez de
390
+ virarem `400 tenant.filter.invalid`. No máximo 10 filtros por requisição.
391
+
392
+ Precisa da API Authyon de 2026-10-22 ou mais nova; contra uma anterior o `filter`
393
+ é ignorado, o que aparece como página larga demais e não como erro.
394
+
362
395
  ## Membros do tenant
363
396
 
364
397
  ```ts
@@ -1,4 +1,4 @@
1
- import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.js';
1
+ import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
2
2
 
3
3
  type AbilitySubject = string | Record<string, unknown>;
4
4
  type AbilityConditions = Record<string, unknown>;
@@ -1,4 +1,4 @@
1
- import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.cjs';
1
+ import { L as JwksTokenVerifier, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.cjs';
2
2
 
3
3
  type AbilitySubject = string | Record<string, unknown>;
4
4
  type AbilityConditions = Record<string, unknown>;
@@ -171,6 +171,43 @@ interface IntrospectResult {
171
171
  token_type?: string;
172
172
  }
173
173
 
174
+ /**
175
+ * Builders for the tenant list's structured filters.
176
+ *
177
+ * The wire form of one filter is `<scope>.<key>:<op>[:<value>]`, repeated once
178
+ * per condition: `?filter=public.kind:in:reseller,partner&filter=custom.cnpj:eq:000`.
179
+ * Repeating the parameter ANDs the conditions and the comma inside `in` is the
180
+ * OR, which is the whole reason to filter server-side — the conditions are part
181
+ * of the SQL statement, so `total`, `pages` and `hasNext` describe the filtered
182
+ * set. A filter applied to a page after it arrives cannot do that.
183
+ *
184
+ * Scopes map to the three JSON documents a tenant carries: `public` →
185
+ * `publicMetadata`, `private` → `privateMetadata`, `custom` → `customFields`
186
+ * (the one the free-text `search` never covered).
187
+ *
188
+ * The rules below mirror the server's parser, so a typo raises `RangeError`
189
+ * here instead of coming back as a 400 `tenant.filter.invalid`.
190
+ */
191
+ /** One `filter` parameter, ready to send. */
192
+ type TenantFilterExpression = string;
193
+ /** Values the filters accept; numbers and booleans are compared as text, the
194
+ * way `jsonb ->> key` returns them. */
195
+ type TenantFilterValue = string | number | boolean;
196
+ declare const TENANT_FILTER_MAX_VALUES = 25;
197
+ declare const TENANT_FILTER_MAX_VALUE_LENGTH = 200;
198
+ declare const TENANT_FILTER_MAX_DEPTH = 3;
199
+ declare const tenantFilter: {
200
+ /** `public.kind:eq:reseller` — the key equals this value. */
201
+ eq(path: string, value: TenantFilterValue): TenantFilterExpression;
202
+ /** `public.kind:in:reseller,partner` — the key equals any of these (SQL IN). */
203
+ in(path: string, values: readonly TenantFilterValue[]): TenantFilterExpression;
204
+ /** `public.notes:like:nacional` — the key contains this text, case-insensitive.
205
+ * The server escapes the LIKE metacharacters, so `100%` means `100%`. */
206
+ like(path: string, text: string): TenantFilterExpression;
207
+ /** `custom.cnpj:exists` — the key is present, whatever its value. */
208
+ exists(path: string): TenantFilterExpression;
209
+ };
210
+
174
211
  /** GET/POST /env/tenants — confirmed against the live API. */
175
212
  interface Organization {
176
213
  id: string;
@@ -190,6 +227,16 @@ interface Organization {
190
227
  /** JSON-encoded metadata available only through administrative APIs. */
191
228
  privateMetadata?: string;
192
229
  }
230
+ /**
231
+ * What `environment.tenants.list()` accepts. `search` is the free-text half
232
+ * (one substring, ORed across name, slug, description and both metadata
233
+ * documents); `filter` is the structured half, ANDed, one entry per condition
234
+ * — see `tenantFilter` for the builders and the wire format.
235
+ */
236
+ interface TenantListOptions extends PaginationOptions {
237
+ search?: string;
238
+ filter?: TenantFilterExpression[];
239
+ }
193
240
  /** One of a user's tenant memberships, as embedded in `EnvironmentUser.tenantMemberships`. */
194
241
  interface TenantMembership {
195
242
  tenantId: string;
@@ -984,12 +1031,29 @@ declare class AuthyonServerClient {
984
1031
  * is found by the number, and `cnpj` alone finds every tenant carrying
985
1032
  * that key. `take` defaults to 25 and is capped at 100.
986
1033
  *
1034
+ * `filter` is the structured half, and the one to reach for when more
1035
+ * than one condition has to hold: each entry is a condition on a JSON
1036
+ * document, they are ANDed with each other and with `search`, and they
1037
+ * run inside the statement — so the envelope keeps describing the
1038
+ * filtered set and you can page through it. Build them with
1039
+ * `tenantFilter`:
1040
+ *
1041
+ * ```ts
1042
+ * const page = await authyon.environment.tenants.list({
1043
+ * filter: [
1044
+ * tenantFilter.in("public.kind", ["reseller", "partner"]),
1045
+ * tenantFilter.in("custom.cnpj", [a, b]),
1046
+ * ],
1047
+ * take: 100,
1048
+ * });
1049
+ * ```
1050
+ *
987
1051
  * Against an Authyon API older than 2026-10-21 this route ignored
988
- * skip/take/search and answered with a bare array.
1052
+ * 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.
989
1055
  */
990
- list: (params?: {
991
- search?: string;
992
- } & PaginationOptions) => Promise<Paged<Organization>>;
1056
+ list: (params?: TenantListOptions) => Promise<Paged<Organization>>;
993
1057
  /** POST /env/tenants — create a tenant in the environment. */
994
1058
  create: (input: CreateOrganizationInput) => Promise<Organization>;
995
1059
  /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
@@ -1229,4 +1293,4 @@ declare class TenantScopedClient {
1229
1293
  /** Convenience factory: `const authyon = createClient({ clientId, clientSecret })`. */
1230
1294
  declare function createClient(options?: AuthyonServerClientOptions): AuthyonServerClient;
1231
1295
 
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 };
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 };
@@ -171,6 +171,43 @@ interface IntrospectResult {
171
171
  token_type?: string;
172
172
  }
173
173
 
174
+ /**
175
+ * Builders for the tenant list's structured filters.
176
+ *
177
+ * The wire form of one filter is `<scope>.<key>:<op>[:<value>]`, repeated once
178
+ * per condition: `?filter=public.kind:in:reseller,partner&filter=custom.cnpj:eq:000`.
179
+ * Repeating the parameter ANDs the conditions and the comma inside `in` is the
180
+ * OR, which is the whole reason to filter server-side — the conditions are part
181
+ * of the SQL statement, so `total`, `pages` and `hasNext` describe the filtered
182
+ * set. A filter applied to a page after it arrives cannot do that.
183
+ *
184
+ * Scopes map to the three JSON documents a tenant carries: `public` →
185
+ * `publicMetadata`, `private` → `privateMetadata`, `custom` → `customFields`
186
+ * (the one the free-text `search` never covered).
187
+ *
188
+ * The rules below mirror the server's parser, so a typo raises `RangeError`
189
+ * here instead of coming back as a 400 `tenant.filter.invalid`.
190
+ */
191
+ /** One `filter` parameter, ready to send. */
192
+ type TenantFilterExpression = string;
193
+ /** Values the filters accept; numbers and booleans are compared as text, the
194
+ * way `jsonb ->> key` returns them. */
195
+ type TenantFilterValue = string | number | boolean;
196
+ declare const TENANT_FILTER_MAX_VALUES = 25;
197
+ declare const TENANT_FILTER_MAX_VALUE_LENGTH = 200;
198
+ declare const TENANT_FILTER_MAX_DEPTH = 3;
199
+ declare const tenantFilter: {
200
+ /** `public.kind:eq:reseller` — the key equals this value. */
201
+ eq(path: string, value: TenantFilterValue): TenantFilterExpression;
202
+ /** `public.kind:in:reseller,partner` — the key equals any of these (SQL IN). */
203
+ in(path: string, values: readonly TenantFilterValue[]): TenantFilterExpression;
204
+ /** `public.notes:like:nacional` — the key contains this text, case-insensitive.
205
+ * The server escapes the LIKE metacharacters, so `100%` means `100%`. */
206
+ like(path: string, text: string): TenantFilterExpression;
207
+ /** `custom.cnpj:exists` — the key is present, whatever its value. */
208
+ exists(path: string): TenantFilterExpression;
209
+ };
210
+
174
211
  /** GET/POST /env/tenants — confirmed against the live API. */
175
212
  interface Organization {
176
213
  id: string;
@@ -190,6 +227,16 @@ interface Organization {
190
227
  /** JSON-encoded metadata available only through administrative APIs. */
191
228
  privateMetadata?: string;
192
229
  }
230
+ /**
231
+ * What `environment.tenants.list()` accepts. `search` is the free-text half
232
+ * (one substring, ORed across name, slug, description and both metadata
233
+ * documents); `filter` is the structured half, ANDed, one entry per condition
234
+ * — see `tenantFilter` for the builders and the wire format.
235
+ */
236
+ interface TenantListOptions extends PaginationOptions {
237
+ search?: string;
238
+ filter?: TenantFilterExpression[];
239
+ }
193
240
  /** One of a user's tenant memberships, as embedded in `EnvironmentUser.tenantMemberships`. */
194
241
  interface TenantMembership {
195
242
  tenantId: string;
@@ -984,12 +1031,29 @@ declare class AuthyonServerClient {
984
1031
  * is found by the number, and `cnpj` alone finds every tenant carrying
985
1032
  * that key. `take` defaults to 25 and is capped at 100.
986
1033
  *
1034
+ * `filter` is the structured half, and the one to reach for when more
1035
+ * than one condition has to hold: each entry is a condition on a JSON
1036
+ * document, they are ANDed with each other and with `search`, and they
1037
+ * run inside the statement — so the envelope keeps describing the
1038
+ * filtered set and you can page through it. Build them with
1039
+ * `tenantFilter`:
1040
+ *
1041
+ * ```ts
1042
+ * const page = await authyon.environment.tenants.list({
1043
+ * filter: [
1044
+ * tenantFilter.in("public.kind", ["reseller", "partner"]),
1045
+ * tenantFilter.in("custom.cnpj", [a, b]),
1046
+ * ],
1047
+ * take: 100,
1048
+ * });
1049
+ * ```
1050
+ *
987
1051
  * Against an Authyon API older than 2026-10-21 this route ignored
988
- * skip/take/search and answered with a bare array.
1052
+ * 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.
989
1055
  */
990
- list: (params?: {
991
- search?: string;
992
- } & PaginationOptions) => Promise<Paged<Organization>>;
1056
+ list: (params?: TenantListOptions) => Promise<Paged<Organization>>;
993
1057
  /** POST /env/tenants — create a tenant in the environment. */
994
1058
  create: (input: CreateOrganizationInput) => Promise<Organization>;
995
1059
  /** GET /env/tenants/{tenantId} — fetch a tenant by id. */
@@ -1229,4 +1293,4 @@ declare class TenantScopedClient {
1229
1293
  /** Convenience factory: `const authyon = createClient({ clientId, clientSecret })`. */
1230
1294
  declare function createClient(options?: AuthyonServerClientOptions): AuthyonServerClient;
1231
1295
 
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 };
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 };
package/dist/bff.cjs CHANGED
@@ -746,7 +746,14 @@ function appendQuery(path, params) {
746
746
  if (!params) return path;
747
747
  const query = new URLSearchParams();
748
748
  for (const [key, value2] of Object.entries(params)) {
749
- if (value2 !== void 0) query.set(key, String(value2));
749
+ if (value2 === void 0) continue;
750
+ if (Array.isArray(value2)) {
751
+ for (const item of value2) {
752
+ if (item !== void 0) query.append(key, String(item));
753
+ }
754
+ continue;
755
+ }
756
+ query.set(key, String(value2));
750
757
  }
751
758
  const value = query.toString();
752
759
  return value ? `${path}${path.includes("?") ? "&" : "?"}${value}` : path;
package/dist/bff.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.cjs';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.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-UA7HdjtD.js';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
2
2
  import 'jose';
3
3
 
4
4
  interface BffLoginInput {
package/dist/bff.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  DEFAULT_BASE_URL,
4
4
  JsonHttpClient,
5
5
  createSharedTransport
6
- } from "./chunk-TDJNBD3Z.js";
6
+ } from "./chunk-SUL2HLRR.js";
7
7
  import "./chunk-77J4NURK.js";
8
8
 
9
9
  // src/bff/contracts.ts
@@ -298,7 +298,14 @@ function appendQuery(path, params) {
298
298
  if (!params) return path;
299
299
  const query = new URLSearchParams();
300
300
  for (const [key, value2] of Object.entries(params)) {
301
- if (value2 !== void 0) query.set(key, String(value2));
301
+ if (value2 === void 0) continue;
302
+ if (Array.isArray(value2)) {
303
+ for (const item of value2) {
304
+ if (item !== void 0) query.append(key, String(item));
305
+ }
306
+ continue;
307
+ }
308
+ query.set(key, String(value2));
302
309
  }
303
310
  const value = query.toString();
304
311
  return value ? `${path}${path.includes("?") ? "&" : "?"}${value}` : path;
package/dist/index.cjs CHANGED
@@ -37,6 +37,9 @@ __export(index_exports, {
37
37
  FetchHttpAdapter: () => FetchHttpAdapter,
38
38
  JwksTokenVerifier: () => JwksTokenVerifier,
39
39
  LoggingHttpAdapter: () => LoggingHttpAdapter,
40
+ TENANT_FILTER_MAX_DEPTH: () => TENANT_FILTER_MAX_DEPTH,
41
+ TENANT_FILTER_MAX_VALUES: () => TENANT_FILTER_MAX_VALUES,
42
+ TENANT_FILTER_MAX_VALUE_LENGTH: () => TENANT_FILTER_MAX_VALUE_LENGTH,
40
43
  TenantScopedClient: () => TenantScopedClient,
41
44
  TokenVerificationError: () => TokenVerificationError,
42
45
  UserScopedClient: () => UserScopedClient,
@@ -49,7 +52,8 @@ __export(index_exports, {
49
52
  createExpressAuthorizationMiddleware: () => createExpressAuthorizationMiddleware,
50
53
  hasPermission: () => hasPermission,
51
54
  hasPermissionGroup: () => hasPermissionGroup,
52
- normalizeClientIp: () => normalizeClientIp
55
+ normalizeClientIp: () => normalizeClientIp,
56
+ tenantFilter: () => tenantFilter
53
57
  });
54
58
  module.exports = __toCommonJS(index_exports);
55
59
 
@@ -436,7 +440,14 @@ function appendQuery(path2, params) {
436
440
  if (!params) return path2;
437
441
  const query = new URLSearchParams();
438
442
  for (const [key, value2] of Object.entries(params)) {
439
- if (value2 !== void 0) query.set(key, String(value2));
443
+ if (value2 === void 0) continue;
444
+ if (Array.isArray(value2)) {
445
+ for (const item of value2) {
446
+ if (item !== void 0) query.append(key, String(item));
447
+ }
448
+ continue;
449
+ }
450
+ query.set(key, String(value2));
440
451
  }
441
452
  const value = query.toString();
442
453
  return value ? `${path2}${path2.includes("?") ? "&" : "?"}${value}` : path2;
@@ -1016,8 +1027,27 @@ var AuthyonServerClient = class {
1016
1027
  * is found by the number, and `cnpj` alone finds every tenant carrying
1017
1028
  * that key. `take` defaults to 25 and is capped at 100.
1018
1029
  *
1030
+ * `filter` is the structured half, and the one to reach for when more
1031
+ * than one condition has to hold: each entry is a condition on a JSON
1032
+ * document, they are ANDed with each other and with `search`, and they
1033
+ * run inside the statement — so the envelope keeps describing the
1034
+ * filtered set and you can page through it. Build them with
1035
+ * `tenantFilter`:
1036
+ *
1037
+ * ```ts
1038
+ * const page = await authyon.environment.tenants.list({
1039
+ * filter: [
1040
+ * tenantFilter.in("public.kind", ["reseller", "partner"]),
1041
+ * tenantFilter.in("custom.cnpj", [a, b]),
1042
+ * ],
1043
+ * take: 100,
1044
+ * });
1045
+ * ```
1046
+ *
1019
1047
  * Against an Authyon API older than 2026-10-21 this route ignored
1020
- * skip/take/search and answered with a bare array.
1048
+ * skip/take/search and answered with a bare array; one older than
1049
+ * 2026-10-22 ignores `filter`, which reads as a page that is too wide
1050
+ * rather than an error.
1021
1051
  */
1022
1052
  list: (params = {}) => this.request("/env/tenants", { envBearer: true, query: params }),
1023
1053
  /** POST /env/tenants — create a tenant in the environment. */
@@ -1539,6 +1569,86 @@ var AuthyonServerClientBuilder = class {
1539
1569
  };
1540
1570
  _options = new WeakMap();
1541
1571
 
1572
+ // src/client/tenantFilters.ts
1573
+ var TENANT_FILTER_MAX_VALUES = 25;
1574
+ var TENANT_FILTER_MAX_VALUE_LENGTH = 200;
1575
+ var TENANT_FILTER_MAX_DEPTH = 3;
1576
+ var SCOPES = ["public", "private", "custom"];
1577
+ var KEY_SEGMENT = /^[A-Za-z0-9_-]{1,64}$/;
1578
+ function assertPath(path2) {
1579
+ if (typeof path2 !== "string" || path2.length === 0) {
1580
+ throw new RangeError("Authyon: a filter path is required, e.g. public.kind.");
1581
+ }
1582
+ const [scope, ...keys] = path2.split(".");
1583
+ if (!SCOPES.includes(scope)) {
1584
+ throw new RangeError(
1585
+ `Authyon: unknown filter scope "${scope}" \u2014 use ${SCOPES.join(", ")} (e.g. public.kind).`
1586
+ );
1587
+ }
1588
+ if (keys.length === 0) {
1589
+ throw new RangeError(`Authyon: filter path "${path2}" needs a key after the scope.`);
1590
+ }
1591
+ if (keys.length > TENANT_FILTER_MAX_DEPTH) {
1592
+ throw new RangeError(
1593
+ `Authyon: filter path "${path2}" goes deeper than ${TENANT_FILTER_MAX_DEPTH} levels.`
1594
+ );
1595
+ }
1596
+ for (const key of keys) {
1597
+ if (!KEY_SEGMENT.test(key)) {
1598
+ throw new RangeError(
1599
+ `Authyon: invalid filter key "${key}" \u2014 letters, digits, "_" and "-", up to 64 characters.`
1600
+ );
1601
+ }
1602
+ }
1603
+ return path2;
1604
+ }
1605
+ function assertValue(value, forIn) {
1606
+ if (value === void 0 || value === null) {
1607
+ throw new RangeError("Authyon: a filter value is required.");
1608
+ }
1609
+ const text = String(value);
1610
+ if (text.length === 0) {
1611
+ throw new RangeError("Authyon: a filter value may not be empty.");
1612
+ }
1613
+ if (text.length > TENANT_FILTER_MAX_VALUE_LENGTH) {
1614
+ throw new RangeError(
1615
+ `Authyon: a filter value may hold at most ${TENANT_FILTER_MAX_VALUE_LENGTH} characters.`
1616
+ );
1617
+ }
1618
+ if (text.includes(",")) {
1619
+ throw new RangeError(
1620
+ forIn ? "Authyon: an `in` value may not contain a comma \u2014 pass separate values instead." : "Authyon: a filter value may not contain a comma."
1621
+ );
1622
+ }
1623
+ return text;
1624
+ }
1625
+ var tenantFilter = {
1626
+ /** `public.kind:eq:reseller` — the key equals this value. */
1627
+ eq(path2, value) {
1628
+ return `${assertPath(path2)}:eq:${assertValue(value, false)}`;
1629
+ },
1630
+ /** `public.kind:in:reseller,partner` — the key equals any of these (SQL IN). */
1631
+ in(path2, values) {
1632
+ if (!Array.isArray(values) || values.length === 0) {
1633
+ throw new RangeError("Authyon: `in` needs at least one value.");
1634
+ }
1635
+ if (values.length > TENANT_FILTER_MAX_VALUES) {
1636
+ throw new RangeError(`Authyon: \`in\` takes at most ${TENANT_FILTER_MAX_VALUES} values.`);
1637
+ }
1638
+ const unique = [...new Set(values.map((value) => assertValue(value, true)))];
1639
+ return `${assertPath(path2)}:in:${unique.join(",")}`;
1640
+ },
1641
+ /** `public.notes:like:nacional` — the key contains this text, case-insensitive.
1642
+ * The server escapes the LIKE metacharacters, so `100%` means `100%`. */
1643
+ like(path2, text) {
1644
+ return `${assertPath(path2)}:like:${assertValue(text, false)}`;
1645
+ },
1646
+ /** `custom.cnpj:exists` — the key is present, whatever its value. */
1647
+ exists(path2) {
1648
+ return `${assertPath(path2)}:exists`;
1649
+ }
1650
+ };
1651
+
1542
1652
  // ../../internal/core/authorization/ability.ts
1543
1653
  var AuthyonAbility = class {
1544
1654
  constructor(rules = [], detectSubjectType = defaultSubjectType) {
@@ -1857,6 +1967,9 @@ function unauthenticated() {
1857
1967
  FetchHttpAdapter,
1858
1968
  JwksTokenVerifier,
1859
1969
  LoggingHttpAdapter,
1970
+ TENANT_FILTER_MAX_DEPTH,
1971
+ TENANT_FILTER_MAX_VALUES,
1972
+ TENANT_FILTER_MAX_VALUE_LENGTH,
1860
1973
  TenantScopedClient,
1861
1974
  TokenVerificationError,
1862
1975
  UserScopedClient,
@@ -1869,5 +1982,6 @@ function unauthenticated() {
1869
1982
  createExpressAuthorizationMiddleware,
1870
1983
  hasPermission,
1871
1984
  hasPermissionGroup,
1872
- normalizeClientIp
1985
+ normalizeClientIp,
1986
+ tenantFilter
1873
1987
  });
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.cjs';
2
- export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as IssuePasswordResetInput, K as JsonWebKeySet, L as JwksTokenVerifier, M as JwksTokenVerifierOptions, N as LoggingHttpAdapter, O as LoginActivity, P as OpenIdConfiguration, Q as Organization, R as OtpCheckResult, S as Paged, T as PaginationOptions, U as PasswordResetCompleted, V as PasswordResetIssued, W as PasswordResetPreview, X as Permission, Y as PermissionsByRole, Z as ReservedPermissions, _ as Role, $ as RoleGrant, a0 as RoleInput, a1 as RoleList, a2 as RolePermissions, a3 as SafeJwtAlgorithm, a4 as SecurityMethods, a5 as SubjectApprovals, a6 as SubjectSecurity, a7 as TenantClientValidationResult, a8 as TenantCredentialIssued, a9 as TenantCredentialSummary, aa as TenantInvite, ab as TenantInviteAccepted, ac as TenantInviteInput, ad as TenantInviteIssued, ae as TenantInvitePreview, af as TenantInviteStatus, ag as TenantMember, ah as TenantMemberPage, ai as TenantMembership, aj as TenantScopedClient, ak as TokenResult, al as TokenVerificationError, am as TokenVerificationErrorCode, an as UpdateOrganizationInput, ao as User, ap as UserScopedClient, aq as ValidateResult, ar as VerifiedAccessToken, as as createClient, at as normalizeClientIp } from './authyonServerClient-UA7HdjtD.cjs';
3
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-DcA5oKZT.cjs';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.cjs';
2
+ export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as IssuePasswordResetInput, K as JsonWebKeySet, L as JwksTokenVerifier, M as JwksTokenVerifierOptions, N as LoggingHttpAdapter, O as LoginActivity, P as OpenIdConfiguration, Q as Organization, R as OtpCheckResult, S as Paged, T as PaginationOptions, U as PasswordResetCompleted, V as PasswordResetIssued, W as PasswordResetPreview, X as Permission, Y as PermissionsByRole, Z as ReservedPermissions, _ as Role, $ as RoleGrant, a0 as RoleInput, a1 as RoleList, a2 as RolePermissions, a3 as SafeJwtAlgorithm, a4 as SecurityMethods, a5 as SubjectApprovals, a6 as SubjectSecurity, a7 as TENANT_FILTER_MAX_DEPTH, a8 as TENANT_FILTER_MAX_VALUES, a9 as TENANT_FILTER_MAX_VALUE_LENGTH, aa as TenantClientValidationResult, ab as TenantCredentialIssued, ac as TenantCredentialSummary, ad as TenantFilterExpression, ae as TenantFilterValue, af as TenantInvite, ag as TenantInviteAccepted, ah as TenantInviteInput, ai as TenantInviteIssued, aj as TenantInvitePreview, ak as TenantInviteStatus, al as TenantListOptions, am as TenantMember, an as TenantMemberPage, ao as TenantMembership, ap as TenantScopedClient, aq as TokenResult, ar as TokenVerificationError, as as TokenVerificationErrorCode, at as UpdateOrganizationInput, au as User, av as UserScopedClient, aw as ValidateResult, ax as VerifiedAccessToken, ay as createClient, az as normalizeClientIp, aA as tenantFilter } from './authyonServerClient-COrfN4o_.cjs';
3
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-Soblu-A5.cjs';
4
4
  import 'jose';
5
5
 
6
6
  declare const ErrorCodes: {
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.js';
2
- export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as IssuePasswordResetInput, K as JsonWebKeySet, L as JwksTokenVerifier, M as JwksTokenVerifierOptions, N as LoggingHttpAdapter, O as LoginActivity, P as OpenIdConfiguration, Q as Organization, R as OtpCheckResult, S as Paged, T as PaginationOptions, U as PasswordResetCompleted, V as PasswordResetIssued, W as PasswordResetPreview, X as Permission, Y as PermissionsByRole, Z as ReservedPermissions, _ as Role, $ as RoleGrant, a0 as RoleInput, a1 as RoleList, a2 as RolePermissions, a3 as SafeJwtAlgorithm, a4 as SecurityMethods, a5 as SubjectApprovals, a6 as SubjectSecurity, a7 as TenantClientValidationResult, a8 as TenantCredentialIssued, a9 as TenantCredentialSummary, aa as TenantInvite, ab as TenantInviteAccepted, ac as TenantInviteInput, ad as TenantInviteIssued, ae as TenantInvitePreview, af as TenantInviteStatus, ag as TenantMember, ah as TenantMemberPage, ai as TenantMembership, aj as TenantScopedClient, ak as TokenResult, al as TokenVerificationError, am as TokenVerificationErrorCode, an as UpdateOrganizationInput, ao as User, ap as UserScopedClient, aq as ValidateResult, ar as VerifiedAccessToken, as as createClient, at as normalizeClientIp } from './authyonServerClient-UA7HdjtD.js';
3
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-DfFCoDQ6.js';
1
+ import { H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
2
+ export { b as AcceptTenantInviteInput, c as AccessTokenSource, d as Approval, e as ApprovalAssurance, f as ApprovalPayload, g as ApprovalStatus, h as ApprovalWebAuthnOptions, i as AuditEvent, j as AuthyonJwksDiscoveryOptions, k as AuthyonJwtClaims, l as AuthyonServerClientOptions, C as ClientCredentials, m as ClientRequestContext, n as ConfirmApprovalInput, o as ConsumedApproval, p as CreateApprovalInput, q as CreateCredentialInput, r as CreateOrganizationInput, s as CreatePermissionInput, t as CreateTenantCredentialInput, u as CreateUserInput, v as CredentialCreator, w as CredentialDetail, x as CredentialListOptions, y as CredentialPermissionsInput, E as EnvironmentUser, F as FetchHttpAdapter, z as HttpAdapterRequest, B as HttpLogEvent, D as HttpLogger, I as IntrospectResult, G as InviteTenantMemberInput, J as IssuePasswordResetInput, K as JsonWebKeySet, L as JwksTokenVerifier, M as JwksTokenVerifierOptions, N as LoggingHttpAdapter, O as LoginActivity, P as OpenIdConfiguration, Q as Organization, R as OtpCheckResult, S as Paged, T as PaginationOptions, U as PasswordResetCompleted, V as PasswordResetIssued, W as PasswordResetPreview, X as Permission, Y as PermissionsByRole, Z as ReservedPermissions, _ as Role, $ as RoleGrant, a0 as RoleInput, a1 as RoleList, a2 as RolePermissions, a3 as SafeJwtAlgorithm, a4 as SecurityMethods, a5 as SubjectApprovals, a6 as SubjectSecurity, a7 as TENANT_FILTER_MAX_DEPTH, a8 as TENANT_FILTER_MAX_VALUES, a9 as TENANT_FILTER_MAX_VALUE_LENGTH, aa as TenantClientValidationResult, ab as TenantCredentialIssued, ac as TenantCredentialSummary, ad as TenantFilterExpression, ae as TenantFilterValue, af as TenantInvite, ag as TenantInviteAccepted, ah as TenantInviteInput, ai as TenantInviteIssued, aj as TenantInvitePreview, ak as TenantInviteStatus, al as TenantListOptions, am as TenantMember, an as TenantMemberPage, ao as TenantMembership, ap as TenantScopedClient, aq as TokenResult, ar as TokenVerificationError, as as TokenVerificationErrorCode, at as UpdateOrganizationInput, au as User, av as UserScopedClient, aw as ValidateResult, ax as VerifiedAccessToken, ay as createClient, az as normalizeClientIp, aA as tenantFilter } from './authyonServerClient-COrfN4o_.js';
3
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRequirement, f as AbilityRule, A as AbilitySubject, g as AuthorizationContext, a as AuthorizationError, h as AuthorizationOptions, i as AuthyonAbility, j as AuthyonAbilityBuilder, k as AuthyonAbilityOptions, l as AuthyonPermissionSource, E as ExpressAuthorizationMiddlewareOptions, m as ExpressNext, n as ExpressRequestLike, o as ExpressResponseLike, P as PermissionGroup, R as RequestAuthorizationOptions, p as authorizeRequest, q as authorizeToken, r as createAuthorizationErrorResponse, s as createAuthyonAbility, t as createAuthyonRules, u as createExpressAuthorizationMiddleware, v as hasPermission, w as hasPermissionGroup } from './authorization-D8tznR96.js';
4
4
  import 'jose';
5
5
 
6
6
  declare const ErrorCodes: {
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  JsonHttpClient,
8
8
  LoggingHttpAdapter,
9
9
  createSharedTransport
10
- } from "./chunk-TDJNBD3Z.js";
10
+ } from "./chunk-SUL2HLRR.js";
11
11
  import {
12
12
  AuthorizationError,
13
13
  AuthyonAbility,
@@ -493,8 +493,27 @@ var AuthyonServerClient = class {
493
493
  * is found by the number, and `cnpj` alone finds every tenant carrying
494
494
  * that key. `take` defaults to 25 and is capped at 100.
495
495
  *
496
+ * `filter` is the structured half, and the one to reach for when more
497
+ * than one condition has to hold: each entry is a condition on a JSON
498
+ * document, they are ANDed with each other and with `search`, and they
499
+ * run inside the statement — so the envelope keeps describing the
500
+ * filtered set and you can page through it. Build them with
501
+ * `tenantFilter`:
502
+ *
503
+ * ```ts
504
+ * const page = await authyon.environment.tenants.list({
505
+ * filter: [
506
+ * tenantFilter.in("public.kind", ["reseller", "partner"]),
507
+ * tenantFilter.in("custom.cnpj", [a, b]),
508
+ * ],
509
+ * take: 100,
510
+ * });
511
+ * ```
512
+ *
496
513
  * Against an Authyon API older than 2026-10-21 this route ignored
497
- * skip/take/search and answered with a bare array.
514
+ * skip/take/search and answered with a bare array; one older than
515
+ * 2026-10-22 ignores `filter`, which reads as a page that is too wide
516
+ * rather than an error.
498
517
  */
499
518
  list: (params = {}) => this.request("/env/tenants", { envBearer: true, query: params }),
500
519
  /** POST /env/tenants — create a tenant in the environment. */
@@ -1015,6 +1034,86 @@ var AuthyonServerClientBuilder = class {
1015
1034
  }
1016
1035
  };
1017
1036
  _options = new WeakMap();
1037
+
1038
+ // src/client/tenantFilters.ts
1039
+ var TENANT_FILTER_MAX_VALUES = 25;
1040
+ var TENANT_FILTER_MAX_VALUE_LENGTH = 200;
1041
+ var TENANT_FILTER_MAX_DEPTH = 3;
1042
+ var SCOPES = ["public", "private", "custom"];
1043
+ var KEY_SEGMENT = /^[A-Za-z0-9_-]{1,64}$/;
1044
+ function assertPath(path2) {
1045
+ if (typeof path2 !== "string" || path2.length === 0) {
1046
+ throw new RangeError("Authyon: a filter path is required, e.g. public.kind.");
1047
+ }
1048
+ const [scope, ...keys] = path2.split(".");
1049
+ if (!SCOPES.includes(scope)) {
1050
+ throw new RangeError(
1051
+ `Authyon: unknown filter scope "${scope}" \u2014 use ${SCOPES.join(", ")} (e.g. public.kind).`
1052
+ );
1053
+ }
1054
+ if (keys.length === 0) {
1055
+ throw new RangeError(`Authyon: filter path "${path2}" needs a key after the scope.`);
1056
+ }
1057
+ if (keys.length > TENANT_FILTER_MAX_DEPTH) {
1058
+ throw new RangeError(
1059
+ `Authyon: filter path "${path2}" goes deeper than ${TENANT_FILTER_MAX_DEPTH} levels.`
1060
+ );
1061
+ }
1062
+ for (const key of keys) {
1063
+ if (!KEY_SEGMENT.test(key)) {
1064
+ throw new RangeError(
1065
+ `Authyon: invalid filter key "${key}" \u2014 letters, digits, "_" and "-", up to 64 characters.`
1066
+ );
1067
+ }
1068
+ }
1069
+ return path2;
1070
+ }
1071
+ function assertValue(value, forIn) {
1072
+ if (value === void 0 || value === null) {
1073
+ throw new RangeError("Authyon: a filter value is required.");
1074
+ }
1075
+ const text = String(value);
1076
+ if (text.length === 0) {
1077
+ throw new RangeError("Authyon: a filter value may not be empty.");
1078
+ }
1079
+ if (text.length > TENANT_FILTER_MAX_VALUE_LENGTH) {
1080
+ throw new RangeError(
1081
+ `Authyon: a filter value may hold at most ${TENANT_FILTER_MAX_VALUE_LENGTH} characters.`
1082
+ );
1083
+ }
1084
+ if (text.includes(",")) {
1085
+ throw new RangeError(
1086
+ forIn ? "Authyon: an `in` value may not contain a comma \u2014 pass separate values instead." : "Authyon: a filter value may not contain a comma."
1087
+ );
1088
+ }
1089
+ return text;
1090
+ }
1091
+ var tenantFilter = {
1092
+ /** `public.kind:eq:reseller` — the key equals this value. */
1093
+ eq(path2, value) {
1094
+ return `${assertPath(path2)}:eq:${assertValue(value, false)}`;
1095
+ },
1096
+ /** `public.kind:in:reseller,partner` — the key equals any of these (SQL IN). */
1097
+ in(path2, values) {
1098
+ if (!Array.isArray(values) || values.length === 0) {
1099
+ throw new RangeError("Authyon: `in` needs at least one value.");
1100
+ }
1101
+ if (values.length > TENANT_FILTER_MAX_VALUES) {
1102
+ throw new RangeError(`Authyon: \`in\` takes at most ${TENANT_FILTER_MAX_VALUES} values.`);
1103
+ }
1104
+ const unique = [...new Set(values.map((value) => assertValue(value, true)))];
1105
+ return `${assertPath(path2)}:in:${unique.join(",")}`;
1106
+ },
1107
+ /** `public.notes:like:nacional` — the key contains this text, case-insensitive.
1108
+ * The server escapes the LIKE metacharacters, so `100%` means `100%`. */
1109
+ like(path2, text) {
1110
+ return `${assertPath(path2)}:like:${assertValue(text, false)}`;
1111
+ },
1112
+ /** `custom.cnpj:exists` — the key is present, whatever its value. */
1113
+ exists(path2) {
1114
+ return `${assertPath(path2)}:exists`;
1115
+ }
1116
+ };
1018
1117
  export {
1019
1118
  AuthorizationError,
1020
1119
  AuthyonAbility,
@@ -1026,6 +1125,9 @@ export {
1026
1125
  FetchHttpAdapter,
1027
1126
  JwksTokenVerifier,
1028
1127
  LoggingHttpAdapter,
1128
+ TENANT_FILTER_MAX_DEPTH,
1129
+ TENANT_FILTER_MAX_VALUES,
1130
+ TENANT_FILTER_MAX_VALUE_LENGTH,
1029
1131
  TenantScopedClient,
1030
1132
  TokenVerificationError,
1031
1133
  UserScopedClient,
@@ -1038,5 +1140,6 @@ export {
1038
1140
  createExpressAuthorizationMiddleware,
1039
1141
  hasPermission,
1040
1142
  hasPermissionGroup,
1041
- normalizeClientIp
1143
+ normalizeClientIp,
1144
+ tenantFilter
1042
1145
  };
package/dist/next.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-DcA5oKZT.cjs';
3
- import { A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.cjs';
2
+ import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-Soblu-A5.cjs';
3
+ import { A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.cjs';
4
4
  import 'jose';
5
5
 
6
6
  interface ServerPermissionGuardFallbackContext {
package/dist/next.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-DfFCoDQ6.js';
3
- import { A as AuthyonServerClient } from './authyonServerClient-UA7HdjtD.js';
2
+ import { R as RequestAuthorizationOptions, A as AbilitySubject, a as AuthorizationError } from './authorization-D8tznR96.js';
3
+ import { A as AuthyonServerClient } from './authyonServerClient-COrfN4o_.js';
4
4
  import 'jose';
5
5
 
6
6
  interface ServerPermissionGuardFallbackContext {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authyon/server",
3
- "version": "0.2.0-beta.20",
3
+ "version": "0.2.0-beta.21",
4
4
  "description": "Authyon SDK for backends — server-to-server organization/member management and access-token verification.",
5
5
  "license": "MIT",
6
6
  "type": "module",