@authyon/auth 0.2.0-beta.20 → 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.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-BTcayvkM.cjs';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PasswordResetCompleted, W as PasswordResetPreview, X as PasswordResetRequestOptions, Y as PermissionGroup, Z as RegisterInput, _ as Role, $ as SecurityMethods, a0 as Session, a1 as SessionControllerOptions, a2 as SessionInfo, a3 as SessionSnapshot, a4 as SessionSnapshotListener, a5 as SessionStatus, a6 as SsoProvider, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TwoFactorChallenge, aa as TwoFactorMethod, ab as TwoFactorStatus, ac as User, ad as ValidateResult, ae as VerifyTwoFactorInput, af as WebAuthnAssertion, ag as WebAuthnCeremonyStart, ah as WebAuthnCredential, ai as createAuthyonAbility, aj as createAuthyonRules, ak as createClient, al as hasPermission, am as hasPermissionGroup } from './ability-BTcayvkM.cjs';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DjEMCVjx.cjs';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PasswordResetCompleted, W as PasswordResetPreview, X as PasswordResetRequestOptions, Y as PermissionGroup, Z as RegisterInput, _ as Role, $ as SecurityMethods, a0 as Session, a1 as SessionControllerOptions, a2 as SessionInfo, a3 as SessionSnapshot, a4 as SessionSnapshotListener, a5 as SessionStatus, a6 as SsoProvider, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TwoFactorChallenge, aa as TwoFactorMethod, ab as TwoFactorStatus, ac as User, ad as ValidateResult, ae as VerifyTwoFactorInput, af as WebAuthnAssertion, ag as WebAuthnCeremonyStart, ah as WebAuthnCredential, ai as createAuthyonAbility, aj as createAuthyonRules, ak as createClient, al as hasPermission, am as hasPermissionGroup } from './ability-DjEMCVjx.cjs';
3
3
 
4
4
  declare const ErrorCodes: {
5
5
  readonly Unknown: "unknown";
@@ -99,4 +99,54 @@ declare function createMemoryStorage(): TokenStorage;
99
99
  declare function createLocalStorage(key?: string): TokenStorage;
100
100
  declare function createDefaultStorage(): TokenStorage;
101
101
 
102
- export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
102
+ /**
103
+ * The permission values the tenant surface checks, as constants.
104
+ *
105
+ * They are strings on the wire and nothing forces you through here — the point
106
+ * is that a rename shows up as a type error instead of as a 403 nobody can
107
+ * explain. `tenants:settings:manage` is exactly that case: it used to be
108
+ * written `tenants:manage`, a two-segment value the API could not even store,
109
+ * so the endpoint requiring it refused every caller.
110
+ */
111
+ declare const TenantPermissions: {
112
+ /** Rename the tenant and change its settings. */
113
+ readonly SettingsManage: "tenants:settings:manage";
114
+ /** Invite an address to the tenant. */
115
+ readonly MembersInvite: "tenants:members:invite";
116
+ /** Remove a member from the tenant. */
117
+ readonly MembersRemove: "tenants:members:remove";
118
+ };
119
+ /**
120
+ * What lets a member of one tenant reach the tenants beneath it.
121
+ *
122
+ * A separate domain, not a suffix on `tenants:…`, and the reason is worth
123
+ * knowing before you grant one: permissions match per segment, so naming these
124
+ * `tenants:tree:manage` would have handed every role already holding
125
+ * `tenants:*:*` power over the whole subtree the day the hierarchy shipped — a
126
+ * widening that appears in no diff. `subtenants:…` is only covered by `*:*:*`,
127
+ * which is explicit superuser.
128
+ *
129
+ * Reaching down is opt-in at every level: holding `tenants:settings:manage` on
130
+ * a parent grants nothing below it, and each of these is granted at the node
131
+ * the caller belongs to, never at the target.
132
+ */
133
+ declare const SubtenantPermissions: {
134
+ /** Read any tenant below one you belong to. */
135
+ readonly TreeRead: "subtenants:tree:read";
136
+ /** Rename a tenant below yours, and add or remove its members. */
137
+ readonly TreeManage: "subtenants:tree:manage";
138
+ /** Create a tenant underneath one you belong to. */
139
+ readonly TreeCreate: "subtenants:tree:create";
140
+ /**
141
+ * Make a tenant below yours the ACTIVE tenant of the session — acting inside
142
+ * it rather than on it from outside. Deliberately not the same permission as
143
+ * {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
144
+ * the management endpoints and operating as that sub-tenant are different
145
+ * powers, and granting the first should not hand over the second.
146
+ */
147
+ readonly TreeSwitch: "subtenants:tree:switch";
148
+ };
149
+ type TenantPermission = (typeof TenantPermissions)[keyof typeof TenantPermissions];
150
+ type SubtenantPermission = (typeof SubtenantPermissions)[keyof typeof SubtenantPermissions];
151
+
152
+ export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, type SubtenantPermission, SubtenantPermissions, type TenantPermission, TenantPermissions, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-BTcayvkM.js';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PasswordResetCompleted, W as PasswordResetPreview, X as PasswordResetRequestOptions, Y as PermissionGroup, Z as RegisterInput, _ as Role, $ as SecurityMethods, a0 as Session, a1 as SessionControllerOptions, a2 as SessionInfo, a3 as SessionSnapshot, a4 as SessionSnapshotListener, a5 as SessionStatus, a6 as SsoProvider, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TwoFactorChallenge, aa as TwoFactorMethod, ab as TwoFactorStatus, ac as User, ad as ValidateResult, ae as VerifyTwoFactorInput, af as WebAuthnAssertion, ag as WebAuthnCeremonyStart, ah as WebAuthnCredential, ai as createAuthyonAbility, aj as createAuthyonRules, ak as createClient, al as hasPermission, am as hasPermissionGroup } from './ability-BTcayvkM.js';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DjEMCVjx.js';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PasswordResetCompleted, W as PasswordResetPreview, X as PasswordResetRequestOptions, Y as PermissionGroup, Z as RegisterInput, _ as Role, $ as SecurityMethods, a0 as Session, a1 as SessionControllerOptions, a2 as SessionInfo, a3 as SessionSnapshot, a4 as SessionSnapshotListener, a5 as SessionStatus, a6 as SsoProvider, a7 as SubjectApprovals, a8 as SubjectSecurity, a9 as TwoFactorChallenge, aa as TwoFactorMethod, ab as TwoFactorStatus, ac as User, ad as ValidateResult, ae as VerifyTwoFactorInput, af as WebAuthnAssertion, ag as WebAuthnCeremonyStart, ah as WebAuthnCredential, ai as createAuthyonAbility, aj as createAuthyonRules, ak as createClient, al as hasPermission, am as hasPermissionGroup } from './ability-DjEMCVjx.js';
3
3
 
4
4
  declare const ErrorCodes: {
5
5
  readonly Unknown: "unknown";
@@ -99,4 +99,54 @@ declare function createMemoryStorage(): TokenStorage;
99
99
  declare function createLocalStorage(key?: string): TokenStorage;
100
100
  declare function createDefaultStorage(): TokenStorage;
101
101
 
102
- export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
102
+ /**
103
+ * The permission values the tenant surface checks, as constants.
104
+ *
105
+ * They are strings on the wire and nothing forces you through here — the point
106
+ * is that a rename shows up as a type error instead of as a 403 nobody can
107
+ * explain. `tenants:settings:manage` is exactly that case: it used to be
108
+ * written `tenants:manage`, a two-segment value the API could not even store,
109
+ * so the endpoint requiring it refused every caller.
110
+ */
111
+ declare const TenantPermissions: {
112
+ /** Rename the tenant and change its settings. */
113
+ readonly SettingsManage: "tenants:settings:manage";
114
+ /** Invite an address to the tenant. */
115
+ readonly MembersInvite: "tenants:members:invite";
116
+ /** Remove a member from the tenant. */
117
+ readonly MembersRemove: "tenants:members:remove";
118
+ };
119
+ /**
120
+ * What lets a member of one tenant reach the tenants beneath it.
121
+ *
122
+ * A separate domain, not a suffix on `tenants:…`, and the reason is worth
123
+ * knowing before you grant one: permissions match per segment, so naming these
124
+ * `tenants:tree:manage` would have handed every role already holding
125
+ * `tenants:*:*` power over the whole subtree the day the hierarchy shipped — a
126
+ * widening that appears in no diff. `subtenants:…` is only covered by `*:*:*`,
127
+ * which is explicit superuser.
128
+ *
129
+ * Reaching down is opt-in at every level: holding `tenants:settings:manage` on
130
+ * a parent grants nothing below it, and each of these is granted at the node
131
+ * the caller belongs to, never at the target.
132
+ */
133
+ declare const SubtenantPermissions: {
134
+ /** Read any tenant below one you belong to. */
135
+ readonly TreeRead: "subtenants:tree:read";
136
+ /** Rename a tenant below yours, and add or remove its members. */
137
+ readonly TreeManage: "subtenants:tree:manage";
138
+ /** Create a tenant underneath one you belong to. */
139
+ readonly TreeCreate: "subtenants:tree:create";
140
+ /**
141
+ * Make a tenant below yours the ACTIVE tenant of the session — acting inside
142
+ * it rather than on it from outside. Deliberately not the same permission as
143
+ * {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
144
+ * the management endpoints and operating as that sub-tenant are different
145
+ * powers, and granting the first should not hand over the second.
146
+ */
147
+ readonly TreeSwitch: "subtenants:tree:switch";
148
+ };
149
+ type TenantPermission = (typeof TenantPermissions)[keyof typeof TenantPermissions];
150
+ type SubtenantPermission = (typeof SubtenantPermissions)[keyof typeof SubtenantPermissions];
151
+
152
+ export { AuthyonClient, AuthyonClientBuilder, AuthyonError, type AuthyonErrorAction, type AuthyonErrorBody, type AuthyonErrorCategory, type AuthyonErrorInterpretation, ErrorCodes, HttpAdapter, HttpLoggerOptions, type KnownErrorCode, type SubtenantPermission, SubtenantPermissions, type TenantPermission, TenantPermissions, TokenStorage, createDefaultStorage, createLocalStorage, createMemoryStorage };
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  createAuthyonRules,
7
7
  hasPermission,
8
8
  hasPermissionGroup
9
- } from "./chunk-3XJY6BCI.js";
9
+ } from "./chunk-IX6U6A72.js";
10
10
 
11
11
  // ../../internal/core/security/approvals.ts
12
12
  function path(id, suffix = "") {
@@ -237,7 +237,14 @@ function appendQuery(path2, params) {
237
237
  if (!params) return path2;
238
238
  const query = new URLSearchParams();
239
239
  for (const [key, value2] of Object.entries(params)) {
240
- if (value2 !== void 0) query.set(key, String(value2));
240
+ if (value2 === void 0) continue;
241
+ if (Array.isArray(value2)) {
242
+ for (const item of value2) {
243
+ if (item !== void 0) query.append(key, String(item));
244
+ }
245
+ continue;
246
+ }
247
+ query.set(key, String(value2));
241
248
  }
242
249
  const value = query.toString();
243
250
  return value ? `${path2}${path2.includes("?") ? "&" : "?"}${value}` : path2;
@@ -435,9 +442,11 @@ var JsonHttpClient = class {
435
442
  };
436
443
 
437
444
  // ../../internal/core/http/clientIp.ts
445
+ var CLIENT_IP_HEADER = "X-Authyon-Client-Ip";
438
446
  function clientIpHeaders(context) {
439
447
  if (!context?.clientIp) return {};
440
- return { "X-Forwarded-For": normalizeClientIp(context.clientIp) };
448
+ const ip = normalizeClientIp(context.clientIp);
449
+ return { "X-Forwarded-For": ip, [CLIENT_IP_HEADER]: ip };
441
450
  }
442
451
  function normalizeClientIp(value) {
443
452
  let ip = value.trim();
@@ -566,26 +575,59 @@ var AuthyonClient = class {
566
575
  };
567
576
  // ── Organization ─────────────────────────────────────────────────────────
568
577
  this.organization = {
569
- /** GET /auth/tenants — filterable list of organization memberships. */
578
+ /**
579
+ * GET /auth/tenants — filterable list of organization memberships.
580
+ *
581
+ * Also lists the organizations below them that the user may switch into
582
+ * without being a member, marked `inherited` — only the ones that actually
583
+ * carry `subtenants:tree:switch`, so the switcher never offers an
584
+ * organization the switch would then refuse. `depth` indents the list into
585
+ * the tree it describes.
586
+ */
570
587
  list: (params = {}) => this.request(appendQuery("/auth/tenants", params), { bearer: true }),
571
588
  /**
572
589
  * POST /auth/tenants — creates an organization owned by the signed-in
573
590
  * user (only available when self-service organization creation is
574
591
  * enabled for the environment).
592
+ *
593
+ * `parentTenantId` nests it under one the user already belongs to, which
594
+ * needs `subtenants:tree:create` there. The creator lands as the effective
595
+ * owner either way, with `tenants:settings:manage`,
596
+ * `tenants:members:invite` and `tenants:members:remove` granted directly
597
+ * inside the new organization.
575
598
  */
576
599
  create: (params = {}) => this.request("/auth/tenants", { method: "POST", bearer: true, body: params }),
577
600
  /** GET /auth/tenants/{organizationId} — fetch one of the user's organizations by id. */
578
601
  get: (organizationId) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}`, { bearer: true }),
579
602
  /**
580
603
  * PATCH /auth/tenants/{organizationId} — renames the organization.
581
- * Requires the `tenants:manage` custom permission on it.
604
+ *
605
+ * Requires the `tenants:settings:manage` custom permission on it, or
606
+ * `subtenants:tree:manage` on an organization above it. The value was
607
+ * spelled `tenants:manage` before 2026-10-31 — two segments, which the API
608
+ * could not store, so the endpoint refused everyone who had been granted
609
+ * it.
582
610
  */
583
611
  rename: (organizationId, name) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}`, {
584
612
  method: "PATCH",
585
613
  bearer: true,
586
614
  body: { name }
587
615
  }),
588
- /** POST /auth/switch-tenant — issues a fresh token scoped to the new organization. */
616
+ /**
617
+ * POST /auth/switch-tenant — issues a fresh token scoped to the new
618
+ * organization.
619
+ *
620
+ * Membership is enough for one of the user's own organizations. Descending
621
+ * into one below it takes `subtenants:tree:switch` at the organization they
622
+ * belong to — deliberately not the same permission as administering a
623
+ * sub-organization from the outside, since operating AS it is the larger of
624
+ * the two powers. The grants then travel from the node the user belongs to,
625
+ * and the token says so in its `tenant.via`.
626
+ *
627
+ * Refusals: `tenant.outside_scope` (no path down to it),
628
+ * `tenant.ancestor_disabled`, and `tenant.path_stale` when the tree moved
629
+ * under a session — sign-in again rather than retrying.
630
+ */
589
631
  switch: (organizationSlug) => this.request("/auth/switch-tenant", {
590
632
  method: "POST",
591
633
  bearer: true,
@@ -899,7 +941,21 @@ var AuthyonClient = class {
899
941
  return this.http.parse(response);
900
942
  }
901
943
  // ── Auth flows ───────────────────────────────────────────────────────────
902
- /** POST /auth/register — creates a new user (rate-limited to 20/hour per IP). */
944
+ /**
945
+ * POST /auth/register — creates a new user (rate-limited to 20/hour per IP).
946
+ *
947
+ * An environment may close public sign-up, and then this route answers as
948
+ * though it were not mapped: **404 with no body**, so the error carries
949
+ * status 404 and the code `unknown`. The SDK does not relabel it, because a
950
+ * wrong `baseUrl` looks exactly the same from here and guessing would send
951
+ * you after the wrong bug — check the environment's setting in the console
952
+ * and the URL you configured. Accounts in a closed environment are created
953
+ * by your backend instead, through `environment.users.create()` in
954
+ * `@authyon/server`, which already needs the `users:write` scope.
955
+ *
956
+ * It gates creation only. Everyone who already has an account signs in as
957
+ * before, and magic link and social sign-up keep their own switches.
958
+ */
903
959
  async register(params) {
904
960
  return this.request("/auth/register", { method: "POST", body: params });
905
961
  }
@@ -1059,6 +1115,32 @@ var AuthyonClientBuilder = class {
1059
1115
  return new AuthyonClient({ ...this.options });
1060
1116
  }
1061
1117
  };
1118
+
1119
+ // ../../internal/core/authorization/tenantPermissions.ts
1120
+ var TenantPermissions = {
1121
+ /** Rename the tenant and change its settings. */
1122
+ SettingsManage: "tenants:settings:manage",
1123
+ /** Invite an address to the tenant. */
1124
+ MembersInvite: "tenants:members:invite",
1125
+ /** Remove a member from the tenant. */
1126
+ MembersRemove: "tenants:members:remove"
1127
+ };
1128
+ var SubtenantPermissions = {
1129
+ /** Read any tenant below one you belong to. */
1130
+ TreeRead: "subtenants:tree:read",
1131
+ /** Rename a tenant below yours, and add or remove its members. */
1132
+ TreeManage: "subtenants:tree:manage",
1133
+ /** Create a tenant underneath one you belong to. */
1134
+ TreeCreate: "subtenants:tree:create",
1135
+ /**
1136
+ * Make a tenant below yours the ACTIVE tenant of the session — acting inside
1137
+ * it rather than on it from outside. Deliberately not the same permission as
1138
+ * {@link SubtenantPermissions.TreeManage}: administering a sub-tenant through
1139
+ * the management endpoints and operating as that sub-tenant are different
1140
+ * powers, and granting the first should not hand over the second.
1141
+ */
1142
+ TreeSwitch: "subtenants:tree:switch"
1143
+ };
1062
1144
  export {
1063
1145
  AuthyonAbility,
1064
1146
  AuthyonAbilityBuilder,
@@ -1069,6 +1151,8 @@ export {
1069
1151
  ErrorCodes,
1070
1152
  FetchHttpAdapter,
1071
1153
  LoggingHttpAdapter,
1154
+ SubtenantPermissions,
1155
+ TenantPermissions,
1072
1156
  createAuthyonAbility,
1073
1157
  createAuthyonRules,
1074
1158
  createClient,
@@ -83,13 +83,23 @@ function createAuthyonRules(source = {}, options = {}) {
83
83
  ...source.permissions ?? [],
84
84
  ...source.scope?.split(/\s+/).filter(Boolean) ?? []
85
85
  ]);
86
- const rules = [...permissions].map(permissionToRule).filter(isAbilityRule);
86
+ const rules = [...permissions].map(grantToRule).filter(isAbilityRule);
87
87
  for (const role of /* @__PURE__ */ new Set([...source.roles ?? [], ...options.roles ?? []])) {
88
88
  rules.push(...(options.roleRules?.[role] ?? []).map(cloneRule));
89
89
  }
90
90
  rules.push(...(options.rules ?? []).map(cloneRule));
91
91
  return rules;
92
92
  }
93
+ function grantToRule(permission) {
94
+ const normalized = permission.trim();
95
+ if (normalized && isFullWildcard(normalized)) {
96
+ return { action: "manage", subject: "all" };
97
+ }
98
+ return permissionToRule(normalized);
99
+ }
100
+ function isFullWildcard(permission) {
101
+ return permission.split(":").every((segment) => segment === "*");
102
+ }
93
103
  function permissionToRule(permission) {
94
104
  const normalized = permission.trim();
95
105
  if (!normalized) return null;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { ac as User, a1 as SessionControllerOptions, A as AuthyonClient, a3 as SessionSnapshot, a0 as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-BTcayvkM.cjs';
4
- export { w as AuthyonSessionController, a4 as SessionSnapshotListener, a5 as SessionStatus } from '../ability-BTcayvkM.cjs';
3
+ import { ac as User, a1 as SessionControllerOptions, A as AuthyonClient, a3 as SessionSnapshot, a0 as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-DjEMCVjx.cjs';
4
+ export { w as AuthyonSessionController, a4 as SessionSnapshotListener, a5 as SessionStatus } from '../ability-DjEMCVjx.cjs';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { ac as User, a1 as SessionControllerOptions, A as AuthyonClient, a3 as SessionSnapshot, a0 as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-BTcayvkM.js';
4
- export { w as AuthyonSessionController, a4 as SessionSnapshotListener, a5 as SessionStatus } from '../ability-BTcayvkM.js';
3
+ import { ac as User, a1 as SessionControllerOptions, A as AuthyonClient, a3 as SessionSnapshot, a0 as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-DjEMCVjx.js';
4
+ export { w as AuthyonSessionController, a4 as SessionSnapshotListener, a5 as SessionStatus } from '../ability-DjEMCVjx.js';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AuthyonSessionController,
4
4
  createAuthyonAbility
5
- } from "../chunk-3XJY6BCI.js";
5
+ } from "../chunk-IX6U6A72.js";
6
6
 
7
7
  // src/react/index.tsx
8
8
  import {
package/package.json CHANGED
@@ -1,71 +1,71 @@
1
- {
2
- "name": "@authyon/auth",
3
- "version": "0.2.0-beta.20",
4
- "description": "Authyon SDK for browsers — auth, sessions, multi-tenant and 2FA for vanilla JS/TS.",
5
- "license": "MIT",
6
- "type": "module",
7
- "engines": {
8
- "node": ">=18"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/Synkestra/package-authyon.git",
13
- "directory": "packages/auth"
14
- },
15
- "homepage": "https://authyon.com/docs",
16
- "bugs": {
17
- "url": "https://github.com/Synkestra/package-authyon/issues"
18
- },
19
- "main": "./dist/index.cjs",
20
- "module": "./dist/index.js",
21
- "types": "./dist/index.d.ts",
22
- "exports": {
23
- ".": {
24
- "types": "./dist/index.d.ts",
25
- "import": "./dist/index.js",
26
- "require": "./dist/index.cjs",
27
- "default": "./dist/index.js"
28
- },
29
- "./react": {
30
- "types": "./dist/react/index.d.ts",
31
- "import": "./dist/react/index.js",
32
- "require": "./dist/react/index.cjs",
33
- "default": "./dist/react/index.js"
34
- }
35
- },
36
- "files": [
37
- "dist"
38
- ],
39
- "sideEffects": false,
40
- "publishConfig": {
41
- "access": "public",
42
- "provenance": true
43
- },
44
- "scripts": {
45
- "build": "tsup src/index.ts src/react/index.tsx --format esm,cjs --dts --clean",
46
- "typecheck": "tsc --noEmit",
47
- "prepack": "npm run build"
48
- },
49
- "keywords": [
50
- "authyon",
51
- "auth",
52
- "authentication",
53
- "jwt",
54
- "2fa",
55
- "multi-tenant"
56
- ],
57
- "devDependencies": {
58
- "@types/react": "^19.2.18",
59
- "react": "^19.2.8",
60
- "tsup": "^8.0.0",
61
- "typescript": "^5.5.0"
62
- },
63
- "peerDependencies": {
64
- "react": ">=18.2.0"
65
- },
66
- "peerDependenciesMeta": {
67
- "react": {
68
- "optional": true
69
- }
70
- }
71
- }
1
+ {
2
+ "name": "@authyon/auth",
3
+ "version": "0.2.0-beta.22",
4
+ "description": "Authyon SDK for browsers — auth, sessions, multi-tenant and 2FA for vanilla JS/TS.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=18"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/Synkestra/package-authyon.git",
13
+ "directory": "packages/auth"
14
+ },
15
+ "homepage": "https://authyon.com/docs",
16
+ "bugs": {
17
+ "url": "https://github.com/Synkestra/package-authyon/issues"
18
+ },
19
+ "main": "./dist/index.cjs",
20
+ "module": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.cjs",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "./react": {
30
+ "types": "./dist/react/index.d.ts",
31
+ "import": "./dist/react/index.js",
32
+ "require": "./dist/react/index.cjs",
33
+ "default": "./dist/react/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "sideEffects": false,
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true
43
+ },
44
+ "scripts": {
45
+ "build": "tsup src/index.ts src/react/index.tsx --format esm,cjs --dts --clean",
46
+ "typecheck": "tsc --noEmit",
47
+ "prepack": "npm run build"
48
+ },
49
+ "keywords": [
50
+ "authyon",
51
+ "auth",
52
+ "authentication",
53
+ "jwt",
54
+ "2fa",
55
+ "multi-tenant"
56
+ ],
57
+ "devDependencies": {
58
+ "@types/react": "^19.2.18",
59
+ "react": "^19.2.8",
60
+ "tsup": "^8.0.0",
61
+ "typescript": "^5.5.0"
62
+ },
63
+ "peerDependencies": {
64
+ "react": ">=18.2.0"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "react": {
68
+ "optional": true
69
+ }
70
+ }
71
+ }