@happyvertical/smrt-users 0.55.18 → 0.55.19

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.
Files changed (39) hide show
  1. package/README.md +47 -0
  2. package/agents/oauth-authorization.md +124 -0
  3. package/agents/retention.md +18 -0
  4. package/dist/chunks/{TerminalAuthService-DjGsRtqb.js → TerminalAuthService-DWPeKl3k.js} +2 -2
  5. package/dist/chunks/TerminalAuthService-DWPeKl3k.js.map +1 -0
  6. package/dist/collections/OAuthAuthorizationCollection.d.ts +31 -0
  7. package/dist/collections/OAuthAuthorizationCollection.d.ts.map +1 -0
  8. package/dist/collections/index.d.ts +1 -0
  9. package/dist/collections/index.d.ts.map +1 -1
  10. package/dist/index.d.ts +4 -4
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +832 -33
  13. package/dist/index.js.map +1 -1
  14. package/dist/manifest.json +4590 -2529
  15. package/dist/models/OAuthAuthorization.d.ts +70 -0
  16. package/dist/models/OAuthAuthorization.d.ts.map +1 -0
  17. package/dist/models/index.d.ts +1 -0
  18. package/dist/models/index.d.ts.map +1 -1
  19. package/dist/retention.d.ts +3 -1
  20. package/dist/retention.d.ts.map +1 -1
  21. package/dist/services/OAuthAuthorizationService.d.ts +52 -0
  22. package/dist/services/OAuthAuthorizationService.d.ts.map +1 -0
  23. package/dist/services/OAuthAuthorizationStorage.d.ts +39 -0
  24. package/dist/services/OAuthAuthorizationStorage.d.ts.map +1 -0
  25. package/dist/services/index.d.ts +2 -0
  26. package/dist/services/index.d.ts.map +1 -1
  27. package/dist/services/oauth-retention.d.ts +14 -0
  28. package/dist/services/oauth-retention.d.ts.map +1 -0
  29. package/dist/services/oauth-transaction.d.ts +4 -0
  30. package/dist/services/oauth-transaction.d.ts.map +1 -0
  31. package/dist/smrt-knowledge.json +925 -48
  32. package/dist/sveltekit/index.d.ts +1 -0
  33. package/dist/sveltekit/index.d.ts.map +1 -1
  34. package/dist/sveltekit/oauth-handlers.d.ts +25 -0
  35. package/dist/sveltekit/oauth-handlers.d.ts.map +1 -0
  36. package/dist/sveltekit.js +93 -25
  37. package/dist/sveltekit.js.map +1 -1
  38. package/package.json +13 -12
  39. package/dist/chunks/TerminalAuthService-DjGsRtqb.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,27 +1,29 @@
1
- import { $ as DEFAULT_LOGIN_LOCKOUT_FACTOR, $t as UsersLoginAttemptCollection, A as readMobileBearerToken, At as deriveOperationPermissionCollectionName, B as DEFAULT_PIN_MANAGE_PERMISSION, Bt as UsersPasswordCredentialCollection, C as hasOperationPermission, Ct as applyTenantHierarchyUpdates, D as withSessionPermissionContext, Dt as DEFAULT_ROLE_PERMISSION_PATTERNS, E as withPrincipalPermissionContext, Et as recordTenantHierarchyChanges, F as encodeOidcTransaction, Ft as RolePermission, G as PIN_LOGIN_KIND, Gt as GroupRoleCollection, H as DeviceCredentialForbiddenError, Ht as MembershipOverrideCollection, I as getUsersOidcConfig, It as RoleCollection, J as ensurePinPermissionsRegistered, Jt as GroupMember, K as PIN_PERMISSION_DEFINITIONS, Kt as GroupRole, L as resolveOidcProviderConfig, Lt as UsersPinCredentialCollection, M as OidcLoginError, Mt as normalizeOperationPermissionAction, N as OidcLoginService, Nt as registerPermissionDefinitions, O as MobileAuthError, Ot as RolePermissionCollection, P as decodeOidcTransaction, Pt as syncPermissionCatalog, Q as DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, Qt as UsersLoginAuditEvent, Rt as UsersPinCredential, S as checkOperationPermission, St as TenantHierarchyError, T as getRequestScopedDatabase, Tt as planTenantHierarchy, U as DeviceCredentialPolicyError, Ut as MembershipOverride, V as DeviceCredentialError, Vt as UsersPasswordCredential, W as DeviceCredentialService, Wt as MembershipCollection, X as PermissionResolver, Xt as Group, Y as SessionService, Yt as GroupCollection, Z as DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, Zt as UsersLoginAuditEventCollection, _ as PasswordCredentialService, _t as TenantPermissionOverrideCollection, a as TerminalAuthError, an as isValidEmail, at as LoginRateLimitError, b as OperationPermissionError, bt as Tenant, c as DEFAULT_PASSWORD_DENYLIST, cn as SESSION_DATA_KEYS, ct as DEFAULT_ANCESTOR_READ_MAX_DEPTH, d as DEFAULT_PASSWORD_MIN_LENGTH, dn as Role, dt as normalizeAncestorReadPolicy, en as UsersLoginAttempt, et as DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, f as PASSWORD_LOGIN_KIND, fn as Permission, ft as OidcProvisioningError, g as PasswordCredentialForbiddenError, gt as backfillUserEmailKeys, h as PasswordCredentialError, ht as UserEmailKeyBackfillError, i as TERMINAL_APPROVE_LOGIN_KIND, in as User, it as LoginAttemptLimiter, j as validateMobileRedirectUri, jt as deriveOperationPermissionSlug, k as MobileAuthService, kt as PermissionCatalogService, l as DEFAULT_PASSWORD_MANAGE_PERMISSION, ln as Session, lt as getConfiguredAncestorReadPolicy, m as PASSWORD_PERMISSION_DEFINITIONS, n as DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, nn as SessionCollection, nt as DurableLoginAuditSink, o as TerminalAuthRateLimitError, on as normalizeEmail, ot as withoutListBounds, p as PASSWORD_MAX_LENGTH_CEILING, pn as Membership, pt as UserCollection, q as PinVerifier, qt as GroupMemberCollection, r as DEFAULT_CLI_SESSION_TTL_SECONDS, rn as UsersCliAuthRequest, rt as InvalidCredentialsError, s as TerminalAuthService, sn as DEFAULT_SESSION_TTL, st as ANCESTOR_READ_ACTION, t as DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, tn as UsersCliAuthRequestCollection, tt as DEFAULT_LOGIN_MAX_ATTEMPTS, u as DEFAULT_PASSWORD_MAX_LENGTH, un as generateSessionId, ut as isAncestorReadableSlug, v as PasswordPolicyError, vt as TenantPermissionOverride, w as getCurrentSessionPermissionContext, wt as assertTenantTableName, x as assertOperationPermission, xt as MAX_TENANT_HIERARCHY_DEPTH, y as ensurePasswordPermissionsRegistered, yt as TenantCollection, z as DEFAULT_DEVICE_PERSON_IDLE_SECONDS, zt as PermissionCollection } from "./chunks/TerminalAuthService-DjGsRtqb.js";
1
+ import { $ as DEFAULT_LOGIN_LOCKOUT_FACTOR, $t as UsersLoginAttemptCollection, A as readMobileBearerToken, At as deriveOperationPermissionCollectionName, B as DEFAULT_PIN_MANAGE_PERMISSION, Bt as UsersPasswordCredentialCollection, C as hasOperationPermission, Ct as applyTenantHierarchyUpdates, D as withSessionPermissionContext, Dt as DEFAULT_ROLE_PERMISSION_PATTERNS, E as withPrincipalPermissionContext, Et as recordTenantHierarchyChanges, F as encodeOidcTransaction, Ft as RolePermission, G as PIN_LOGIN_KIND, Gt as GroupRoleCollection, H as DeviceCredentialForbiddenError, Ht as MembershipOverrideCollection, I as getUsersOidcConfig, It as RoleCollection, J as ensurePinPermissionsRegistered, Jt as GroupMember, K as PIN_PERMISSION_DEFINITIONS, Kt as GroupRole, L as resolveOidcProviderConfig, Lt as UsersPinCredentialCollection, M as OidcLoginError, Mt as normalizeOperationPermissionAction, N as OidcLoginService, Nt as registerPermissionDefinitions, O as MobileAuthError, Ot as RolePermissionCollection, P as decodeOidcTransaction, Pt as syncPermissionCatalog, Q as DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, Qt as UsersLoginAuditEvent, Rt as UsersPinCredential, S as checkOperationPermission, St as TenantHierarchyError, T as getRequestScopedDatabase, Tt as planTenantHierarchy, U as DeviceCredentialPolicyError, Ut as MembershipOverride, V as DeviceCredentialError, Vt as UsersPasswordCredential, W as DeviceCredentialService, Wt as MembershipCollection, X as PermissionResolver, Xt as Group, Y as SessionService, Yt as GroupCollection, Z as DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, Zt as UsersLoginAuditEventCollection, _ as PasswordCredentialService, _t as TenantPermissionOverrideCollection, a as TerminalAuthError, an as isValidEmail, at as LoginRateLimitError, b as OperationPermissionError, bt as Tenant, c as DEFAULT_PASSWORD_DENYLIST, cn as SESSION_DATA_KEYS, ct as DEFAULT_ANCESTOR_READ_MAX_DEPTH, d as DEFAULT_PASSWORD_MIN_LENGTH, dn as Role, dt as normalizeAncestorReadPolicy, en as UsersLoginAttempt, et as DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, f as PASSWORD_LOGIN_KIND, fn as Permission, ft as OidcProvisioningError, g as PasswordCredentialForbiddenError, gt as backfillUserEmailKeys, h as PasswordCredentialError, ht as UserEmailKeyBackfillError, i as TERMINAL_APPROVE_LOGIN_KIND, in as User, it as LoginAttemptLimiter, j as validateMobileRedirectUri, jt as deriveOperationPermissionSlug, k as MobileAuthService, kt as PermissionCatalogService, l as DEFAULT_PASSWORD_MANAGE_PERMISSION, ln as Session, lt as getConfiguredAncestorReadPolicy, m as PASSWORD_PERMISSION_DEFINITIONS, n as DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, nn as SessionCollection, nt as DurableLoginAuditSink, o as TerminalAuthRateLimitError, on as normalizeEmail, ot as withoutListBounds, p as PASSWORD_MAX_LENGTH_CEILING, pn as Membership, pt as UserCollection, q as PinVerifier, qt as GroupMemberCollection, r as DEFAULT_CLI_SESSION_TTL_SECONDS, rn as UsersCliAuthRequest, rt as InvalidCredentialsError, s as TerminalAuthService, sn as DEFAULT_SESSION_TTL, st as ANCESTOR_READ_ACTION, t as DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, tn as UsersCliAuthRequestCollection, tt as DEFAULT_LOGIN_MAX_ATTEMPTS, u as DEFAULT_PASSWORD_MAX_LENGTH, un as generateSessionId, ut as isAncestorReadableSlug, v as PasswordPolicyError, vt as TenantPermissionOverride, w as getCurrentSessionPermissionContext, wt as assertTenantTableName, x as assertOperationPermission, xt as MAX_TENANT_HIERARCHY_DEPTH, y as ensurePasswordPermissionsRegistered, yt as TenantCollection, z as DEFAULT_DEVICE_PERSON_IDLE_SECONDS, zt as PermissionCollection } from "./chunks/TerminalAuthService-DWPeKl3k.js";
2
2
  import { a as MembershipStatus, c as TenantPermissionEffect, i as DEFAULT_TENANT_POLICY, l as TenantStatus, n as DEFAULT_ROLES, o as OverrideEffect, r as DEFAULT_ROLE_SLUGS, s as SessionStatus, t as AccessRequestStatus, u as UserStatus } from "./chunks/types-DFqeph0R.js";
3
3
  import { ObjectRegistry, SmrtCollection, SmrtObject, SmrtRecipe, bumpChangeFeed, ensureChangeFeedTable, field, findManifestEntryByQualifiedName, foreignKey, isEmbeddedDatabase, isUniqueViolationError, registerRetentionTask, smrt, unregisterRetentionTask, withEmbeddedWriteTransaction } from "@happyvertical/smrt-core";
4
4
  import { PROFILE_EMAIL_KEY_BACKFILL_NAME, Person, ProfileCollection, ProfileTypeCollection, normalizeIdentityEmail } from "@happyvertical/smrt-profiles";
5
5
  import { createHash, randomUUID } from "node:crypto";
6
+ import { setTimeout } from "node:timers/promises";
6
7
  import { createLogger } from "@happyvertical/logger";
7
8
  import { TenantScoped, tenantId, withSystemContext } from "@happyvertical/smrt-tenancy";
8
9
  import { BackfillTracker } from "@happyvertical/smrt-core/migrations";
10
+ import { OAuthServerError } from "@happyvertical/auth/server";
9
11
  //#region src/models/ResourceGrant.ts
10
- var __defProp$4 = Object.defineProperty;
11
- var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
12
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {
12
+ var __defProp$5 = Object.defineProperty;
13
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
14
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
13
15
  enumerable: true,
14
16
  configurable: true,
15
17
  writable: true,
16
18
  value
17
19
  }) : obj[key] = value;
18
- var __decorateClass$4 = (decorators, target, key, kind) => {
19
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
20
+ var __decorateClass$5 = (decorators, target, key, kind) => {
21
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
20
22
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
21
- if (kind && result) __defProp$4(target, key, result);
23
+ if (kind && result) __defProp$5(target, key, result);
22
24
  return result;
23
25
  };
24
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
26
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
25
27
  var ResourceGrant = class extends SmrtObject {
26
28
  tenantId;
27
29
  userId;
@@ -48,32 +50,32 @@ var ResourceGrant = class extends SmrtObject {
48
50
  return !this.revokedAt;
49
51
  }
50
52
  };
51
- __publicField$4(ResourceGrant, "__smrtPackage__", "@happyvertical/smrt-users");
52
- __decorateClass$4([foreignKey("Tenant", { required: true })], ResourceGrant.prototype, "tenantId", 2);
53
- __decorateClass$4([field({ description: "The person receiving this record-specific access rule." }), foreignKey("User", { required: true })], ResourceGrant.prototype, "userId", 2);
54
- __decorateClass$4([field({
53
+ __publicField$5(ResourceGrant, "__smrtPackage__", "@happyvertical/smrt-users");
54
+ __decorateClass$5([foreignKey("Tenant", { required: true })], ResourceGrant.prototype, "tenantId", 2);
55
+ __decorateClass$5([field({ description: "The person receiving this record-specific access rule." }), foreignKey("User", { required: true })], ResourceGrant.prototype, "userId", 2);
56
+ __decorateClass$5([field({
55
57
  description: "The kind of record this access rule applies to.",
56
58
  type: "text"
57
59
  })], ResourceGrant.prototype, "resourceType", 2);
58
- __decorateClass$4([field({
60
+ __decorateClass$5([field({
59
61
  description: "The specific record covered by this access rule.",
60
62
  type: "text"
61
63
  })], ResourceGrant.prototype, "resourceId", 2);
62
- __decorateClass$4([field({
64
+ __decorateClass$5([field({
63
65
  description: "The action this rule allows or denies for the record.",
64
66
  type: "text"
65
67
  })], ResourceGrant.prototype, "permission", 2);
66
- __decorateClass$4([field({
68
+ __decorateClass$5([field({
67
69
  description: "Whether this rule grants access or denies it. Denies take precedence.",
68
70
  type: "text"
69
71
  })], ResourceGrant.prototype, "effect", 2);
70
- __decorateClass$4([field({ description: "Whether the recipient may pass this grant on to another person." })], ResourceGrant.prototype, "canDelegate", 2);
71
- __decorateClass$4([field({ description: "The earlier grant from which this access was delegated." }), foreignKey("ResourceGrant")], ResourceGrant.prototype, "parentGrantId", 2);
72
- __decorateClass$4([field({
72
+ __decorateClass$5([field({ description: "Whether the recipient may pass this grant on to another person." })], ResourceGrant.prototype, "canDelegate", 2);
73
+ __decorateClass$5([field({ description: "The earlier grant from which this access was delegated." }), foreignKey("ResourceGrant")], ResourceGrant.prototype, "parentGrantId", 2);
74
+ __decorateClass$5([field({
73
75
  description: "When this access rule was revoked, if it has ended.",
74
76
  type: "text"
75
77
  })], ResourceGrant.prototype, "revokedAt", 2);
76
- ResourceGrant = __decorateClass$4([smrt({
78
+ ResourceGrant = __decorateClass$5([smrt({
77
79
  tenantScoped: true,
78
80
  api: { include: [] },
79
81
  mcp: { include: [] },
@@ -179,21 +181,21 @@ var UsersRolesAndPermissionsRecipe = class extends SmrtRecipe {
179
181
  };
180
182
  //#endregion
181
183
  //#region src/models/MagicLinkToken.ts
182
- var __defProp$3 = Object.defineProperty;
183
- var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
184
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
184
+ var __defProp$4 = Object.defineProperty;
185
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
186
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {
185
187
  enumerable: true,
186
188
  configurable: true,
187
189
  writable: true,
188
190
  value
189
191
  }) : obj[key] = value;
190
- var __decorateClass$3 = (decorators, target, key, kind) => {
191
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
192
+ var __decorateClass$4 = (decorators, target, key, kind) => {
193
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
192
194
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
193
- if (kind && result) __defProp$3(target, key, result);
195
+ if (kind && result) __defProp$4(target, key, result);
194
196
  return result;
195
197
  };
196
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
198
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
197
199
  var DEFAULT_TOKEN_EXPIRY_SECONDS = 600;
198
200
  var UsersMagicLinkToken = class extends SmrtObject {
199
201
  nonce = "";
@@ -218,16 +220,16 @@ var UsersMagicLinkToken = class extends SmrtObject {
218
220
  return !this.used && !this.isExpired();
219
221
  }
220
222
  };
221
- __publicField$3(UsersMagicLinkToken, "__smrtPackage__", "@happyvertical/smrt-users");
222
- __decorateClass$3([field({
223
+ __publicField$4(UsersMagicLinkToken, "__smrtPackage__", "@happyvertical/smrt-users");
224
+ __decorateClass$4([field({
223
225
  required: true,
224
226
  unique: true
225
227
  })], UsersMagicLinkToken.prototype, "nonce", 2);
226
- __decorateClass$3([field({
228
+ __decorateClass$4([field({
227
229
  type: "datetime",
228
230
  indexed: true
229
231
  })], UsersMagicLinkToken.prototype, "expiresAt", 2);
230
- UsersMagicLinkToken = __decorateClass$3([smrt({
232
+ UsersMagicLinkToken = __decorateClass$4([smrt({
231
233
  tableName: "users_magic_link_tokens",
232
234
  sensitive: true,
233
235
  api: { include: [] },
@@ -279,6 +281,395 @@ var UsersMagicLinkTokenCollection = class extends SmrtCollection {
279
281
  }
280
282
  };
281
283
  //#endregion
284
+ //#region src/models/OAuthAuthorization.ts
285
+ var __defProp$3 = Object.defineProperty;
286
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
287
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
288
+ enumerable: true,
289
+ configurable: true,
290
+ writable: true,
291
+ value
292
+ }) : obj[key] = value;
293
+ var __decorateClass$3 = (decorators, target, key, kind) => {
294
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
295
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
296
+ if (kind && result) __defProp$3(target, key, result);
297
+ return result;
298
+ };
299
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
300
+ function stringArray(value) {
301
+ if (Array.isArray(value) && value.every((item) => typeof item === "string")) return [...value];
302
+ if (typeof value !== "string") return [];
303
+ try {
304
+ const parsed = JSON.parse(value);
305
+ return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : [];
306
+ } catch {
307
+ return [];
308
+ }
309
+ }
310
+ function tokenClaims(value) {
311
+ if (value && typeof value === "object" && !Array.isArray(value)) return Object.fromEntries(Object.entries(value).filter(([, item]) => typeof item === "string" || typeof item === "number" || typeof item === "boolean"));
312
+ if (typeof value !== "string") return {};
313
+ try {
314
+ return tokenClaims(JSON.parse(value));
315
+ } catch {
316
+ return {};
317
+ }
318
+ }
319
+ var UsersOAuthClient = class extends SmrtObject {
320
+ clientId = "";
321
+ redirectUris = "[]";
322
+ allowedScopes = "[]";
323
+ tokenEndpointAuthMethod = "none";
324
+ secretHash = null;
325
+ allowedResources = "null";
326
+ createdAt = /* @__PURE__ */ new Date();
327
+ getRedirectUris() {
328
+ return stringArray(this.redirectUris);
329
+ }
330
+ getAllowedScopes() {
331
+ return stringArray(this.allowedScopes);
332
+ }
333
+ getAllowedResources() {
334
+ return this.allowedResources === "null" ? void 0 : stringArray(this.allowedResources);
335
+ }
336
+ };
337
+ __publicField$3(UsersOAuthClient, "__smrtPackage__", "@happyvertical/smrt-users");
338
+ __decorateClass$3([field({
339
+ type: "text",
340
+ required: true,
341
+ unique: true
342
+ })], UsersOAuthClient.prototype, "clientId", 2);
343
+ __decorateClass$3([field({
344
+ nullable: true,
345
+ sensitive: true
346
+ })], UsersOAuthClient.prototype, "secretHash", 2);
347
+ __decorateClass$3([field({ type: "datetime" })], UsersOAuthClient.prototype, "createdAt", 2);
348
+ UsersOAuthClient = __decorateClass$3([smrt({
349
+ tableName: "users_oauth_clients",
350
+ sensitive: true,
351
+ api: { include: [] },
352
+ mcp: { include: [] },
353
+ cli: false
354
+ })], UsersOAuthClient);
355
+ var UsersOAuthAuthorizationCode = class extends SmrtObject {
356
+ authorizationId = null;
357
+ codeHash = "";
358
+ clientId = "";
359
+ subject = "";
360
+ tenantId = null;
361
+ claims = "{}";
362
+ redirectUri = "";
363
+ scopes = "[]";
364
+ resource = null;
365
+ codeChallenge = "";
366
+ expiresAt = /* @__PURE__ */ new Date();
367
+ consumedAt = null;
368
+ getScopes() {
369
+ return stringArray(this.scopes);
370
+ }
371
+ getClaims() {
372
+ return tokenClaims(this.claims);
373
+ }
374
+ };
375
+ __publicField$3(UsersOAuthAuthorizationCode, "__smrtPackage__", "@happyvertical/smrt-users");
376
+ __decorateClass$3([field({
377
+ nullable: true,
378
+ indexed: true
379
+ })], UsersOAuthAuthorizationCode.prototype, "authorizationId", 2);
380
+ __decorateClass$3([field({
381
+ type: "text",
382
+ required: true,
383
+ unique: true,
384
+ sensitive: true
385
+ })], UsersOAuthAuthorizationCode.prototype, "codeHash", 2);
386
+ __decorateClass$3([field({
387
+ type: "text",
388
+ indexed: true
389
+ })], UsersOAuthAuthorizationCode.prototype, "clientId", 2);
390
+ __decorateClass$3([field({
391
+ type: "text",
392
+ indexed: true
393
+ })], UsersOAuthAuthorizationCode.prototype, "subject", 2);
394
+ __decorateClass$3([field({
395
+ nullable: true,
396
+ indexed: true
397
+ })], UsersOAuthAuthorizationCode.prototype, "tenantId", 2);
398
+ __decorateClass$3([field({ nullable: true })], UsersOAuthAuthorizationCode.prototype, "resource", 2);
399
+ __decorateClass$3([field({
400
+ type: "datetime",
401
+ indexed: true
402
+ })], UsersOAuthAuthorizationCode.prototype, "expiresAt", 2);
403
+ __decorateClass$3([field({
404
+ type: "datetime",
405
+ nullable: true
406
+ })], UsersOAuthAuthorizationCode.prototype, "consumedAt", 2);
407
+ UsersOAuthAuthorizationCode = __decorateClass$3([smrt({
408
+ tableName: "users_oauth_authorization_codes",
409
+ sensitive: true,
410
+ api: { include: [] },
411
+ mcp: { include: [] },
412
+ cli: false
413
+ })], UsersOAuthAuthorizationCode);
414
+ var UsersOAuthRefreshGrant = class extends SmrtObject {
415
+ authorizationId = null;
416
+ tokenHash = "";
417
+ familyId = "";
418
+ clientId = "";
419
+ subject = "";
420
+ tenantId = null;
421
+ claims = "{}";
422
+ scopes = "[]";
423
+ resource = null;
424
+ expiresAt = /* @__PURE__ */ new Date();
425
+ consumedAt = null;
426
+ revokedAt = null;
427
+ getScopes() {
428
+ return stringArray(this.scopes);
429
+ }
430
+ getClaims() {
431
+ return tokenClaims(this.claims);
432
+ }
433
+ };
434
+ __publicField$3(UsersOAuthRefreshGrant, "__smrtPackage__", "@happyvertical/smrt-users");
435
+ __decorateClass$3([field({
436
+ nullable: true,
437
+ indexed: true
438
+ })], UsersOAuthRefreshGrant.prototype, "authorizationId", 2);
439
+ __decorateClass$3([field({
440
+ type: "text",
441
+ required: true,
442
+ unique: true,
443
+ sensitive: true
444
+ })], UsersOAuthRefreshGrant.prototype, "tokenHash", 2);
445
+ __decorateClass$3([field({
446
+ type: "text",
447
+ indexed: true
448
+ })], UsersOAuthRefreshGrant.prototype, "familyId", 2);
449
+ __decorateClass$3([field({
450
+ type: "text",
451
+ indexed: true
452
+ })], UsersOAuthRefreshGrant.prototype, "clientId", 2);
453
+ __decorateClass$3([field({
454
+ type: "text",
455
+ indexed: true
456
+ })], UsersOAuthRefreshGrant.prototype, "subject", 2);
457
+ __decorateClass$3([field({
458
+ nullable: true,
459
+ indexed: true
460
+ })], UsersOAuthRefreshGrant.prototype, "tenantId", 2);
461
+ __decorateClass$3([field({ nullable: true })], UsersOAuthRefreshGrant.prototype, "resource", 2);
462
+ __decorateClass$3([field({
463
+ type: "datetime",
464
+ indexed: true
465
+ })], UsersOAuthRefreshGrant.prototype, "expiresAt", 2);
466
+ __decorateClass$3([field({
467
+ type: "datetime",
468
+ nullable: true
469
+ })], UsersOAuthRefreshGrant.prototype, "consumedAt", 2);
470
+ __decorateClass$3([field({
471
+ type: "datetime",
472
+ nullable: true,
473
+ indexed: true
474
+ })], UsersOAuthRefreshGrant.prototype, "revokedAt", 2);
475
+ UsersOAuthRefreshGrant = __decorateClass$3([smrt({
476
+ tableName: "users_oauth_refresh_grants",
477
+ sensitive: true,
478
+ api: { include: [] },
479
+ mcp: { include: [] },
480
+ cli: false
481
+ })], UsersOAuthRefreshGrant);
482
+ var UsersOAuthAccessTokenRevocation = class extends SmrtObject {
483
+ jti = "";
484
+ expiresAt = /* @__PURE__ */ new Date();
485
+ };
486
+ __publicField$3(UsersOAuthAccessTokenRevocation, "__smrtPackage__", "@happyvertical/smrt-users");
487
+ __decorateClass$3([field({
488
+ type: "text",
489
+ required: true,
490
+ unique: true,
491
+ sensitive: true
492
+ })], UsersOAuthAccessTokenRevocation.prototype, "jti", 2);
493
+ __decorateClass$3([field({
494
+ type: "datetime",
495
+ indexed: true
496
+ })], UsersOAuthAccessTokenRevocation.prototype, "expiresAt", 2);
497
+ UsersOAuthAccessTokenRevocation = __decorateClass$3([smrt({
498
+ tableName: "users_oauth_access_token_revocations",
499
+ sensitive: true,
500
+ api: { include: [] },
501
+ mcp: { include: [] },
502
+ cli: false
503
+ })], UsersOAuthAccessTokenRevocation);
504
+ var UsersOAuthAuthorization = class extends SmrtObject {
505
+ subject = "";
506
+ sessionId = "";
507
+ clientId = "";
508
+ tenantId = null;
509
+ scopes = "[]";
510
+ permissionCeiling = "[]";
511
+ resource = null;
512
+ revokedAt = null;
513
+ getPermissionCeiling() {
514
+ return stringArray(this.permissionCeiling);
515
+ }
516
+ getScopes() {
517
+ return stringArray(this.scopes);
518
+ }
519
+ };
520
+ __publicField$3(UsersOAuthAuthorization, "__smrtPackage__", "@happyvertical/smrt-users");
521
+ __decorateClass$3([field({
522
+ type: "text",
523
+ indexed: true
524
+ })], UsersOAuthAuthorization.prototype, "subject", 2);
525
+ __decorateClass$3([field({
526
+ type: "text",
527
+ sensitive: true
528
+ })], UsersOAuthAuthorization.prototype, "sessionId", 2);
529
+ __decorateClass$3([field({
530
+ type: "text",
531
+ indexed: true
532
+ })], UsersOAuthAuthorization.prototype, "clientId", 2);
533
+ __decorateClass$3([field({ nullable: true })], UsersOAuthAuthorization.prototype, "tenantId", 2);
534
+ __decorateClass$3([field({ nullable: true })], UsersOAuthAuthorization.prototype, "resource", 2);
535
+ __decorateClass$3([field({
536
+ type: "datetime",
537
+ nullable: true
538
+ })], UsersOAuthAuthorization.prototype, "revokedAt", 2);
539
+ UsersOAuthAuthorization = __decorateClass$3([smrt({
540
+ tableName: "users_oauth_authorizations",
541
+ sensitive: true,
542
+ api: { include: [] },
543
+ mcp: { include: [] },
544
+ cli: false
545
+ })], UsersOAuthAuthorization);
546
+ var UsersOAuthRefreshFamily = class extends SmrtObject {
547
+ authorizationId = null;
548
+ revokedAt = null;
549
+ };
550
+ __publicField$3(UsersOAuthRefreshFamily, "__smrtPackage__", "@happyvertical/smrt-users");
551
+ __decorateClass$3([field({
552
+ nullable: true,
553
+ indexed: true
554
+ })], UsersOAuthRefreshFamily.prototype, "authorizationId", 2);
555
+ __decorateClass$3([field({
556
+ type: "datetime",
557
+ nullable: true
558
+ })], UsersOAuthRefreshFamily.prototype, "revokedAt", 2);
559
+ UsersOAuthRefreshFamily = __decorateClass$3([smrt({
560
+ tableName: "users_oauth_refresh_families",
561
+ sensitive: true,
562
+ api: { include: [] },
563
+ mcp: { include: [] },
564
+ cli: false
565
+ })], UsersOAuthRefreshFamily);
566
+ //#endregion
567
+ //#region src/collections/OAuthAuthorizationCollection.ts
568
+ var UsersOAuthClientCollection = class extends SmrtCollection {
569
+ static _itemClass = UsersOAuthClient;
570
+ findByClientId(clientId) {
571
+ return this.findOne({ where: { clientId } });
572
+ }
573
+ };
574
+ var UsersOAuthAuthorizationCodeCollection = class extends SmrtCollection {
575
+ static _itemClass = UsersOAuthAuthorizationCode;
576
+ async consume(id, codeHash, clientId, redirectUri, resource, now) {
577
+ return (await this.db.query(`UPDATE ${this.tableName} SET consumed_at = ?, updated_at = ? WHERE id = ? AND code_hash = ? AND client_id = ? AND redirect_uri = ? AND ${resource === null ? "resource IS NULL" : "resource = ?"} AND consumed_at IS NULL AND expires_at > ?`, now.toISOString(), now.toISOString(), id, codeHash, clientId, redirectUri, ...resource === null ? [] : [resource], now.toISOString())).rowCount === 1;
578
+ }
579
+ };
580
+ var UsersOAuthRefreshGrantCollection = class extends SmrtCollection {
581
+ static _itemClass = UsersOAuthRefreshGrant;
582
+ async consume(id, tokenHash, clientId, resource, now) {
583
+ return (await this.db.query(`UPDATE ${this.tableName} SET consumed_at = ?, updated_at = ? WHERE id = ? AND token_hash = ? AND client_id = ? AND ${resource === null ? "resource IS NULL" : "resource = ?"} AND consumed_at IS NULL AND revoked_at IS NULL AND expires_at > ?`, now.toISOString(), now.toISOString(), id, tokenHash, clientId, ...resource === null ? [] : [resource], now.toISOString())).rowCount === 1;
584
+ }
585
+ async revokeFamily(familyId, now) {
586
+ await this.db.query(`UPDATE ${this.tableName} SET revoked_at = ?, updated_at = ? WHERE family_id = ? AND revoked_at IS NULL`, now.toISOString(), now.toISOString(), familyId);
587
+ }
588
+ };
589
+ var UsersOAuthAccessTokenRevocationCollection = class extends SmrtCollection {
590
+ static _itemClass = UsersOAuthAccessTokenRevocation;
591
+ async findByJti(jti) {
592
+ const result = await this.db.query(`SELECT id FROM ${this.tableName} WHERE jti = ?`, jti);
593
+ return result.rows[0] ? this.get(String(result.rows[0].id)) : null;
594
+ }
595
+ };
596
+ var UsersOAuthAuthorizationCollection = class extends SmrtCollection {
597
+ static _itemClass = UsersOAuthAuthorization;
598
+ };
599
+ var UsersOAuthRefreshFamilyCollection = class extends SmrtCollection {
600
+ static _itemClass = UsersOAuthRefreshFamily;
601
+ async lock(id, now) {
602
+ return (await this.db.query(`UPDATE ${this.tableName} SET updated_at = ? WHERE id = ?`, now.toISOString(), id)).rowCount === 1;
603
+ }
604
+ async revoke(id, now) {
605
+ await this.db.query(`UPDATE ${this.tableName} SET revoked_at = ?, updated_at = ? WHERE id = ?`, now.toISOString(), now.toISOString(), id);
606
+ }
607
+ };
608
+ //#endregion
609
+ //#region src/services/oauth-transaction.ts
610
+ async function withOAuthTransaction(db, action) {
611
+ if (!db.transaction) throw new Error("OAuth persistence requires transaction support.");
612
+ for (let attempt = 0;; attempt++) try {
613
+ return await db.transaction(action);
614
+ } catch (error) {
615
+ let current = error;
616
+ let retryable = false;
617
+ let invalidated = false;
618
+ for (let depth = 0; depth < 4 && current && typeof current === "object"; depth++) {
619
+ const failure = current;
620
+ if ([
621
+ "SQLITE_BUSY",
622
+ "SQLITE_BUSY_SNAPSHOT",
623
+ "40001",
624
+ "40P01"
625
+ ].includes(String(failure.code))) retryable = true;
626
+ invalidated ||= failure.connectionInvalidated === true;
627
+ current = failure.cause;
628
+ }
629
+ if (attempt >= 6 || !retryable || invalidated) throw error;
630
+ await setTimeout(5 * 2 ** attempt);
631
+ }
632
+ }
633
+ //#endregion
634
+ //#region src/services/oauth-retention.ts
635
+ var OAUTH_REFRESH_REPLAY_RETENTION_MS = 720 * 60 * 60 * 1e3;
636
+ async function pruneOAuthCredentials(db, options = {}) {
637
+ const now = options.now ?? /* @__PURE__ */ new Date();
638
+ const cutoff = (/* @__PURE__ */ new Date(now.getTime() - OAUTH_REFRESH_REPLAY_RETENTION_MS)).toISOString();
639
+ const codes = await UsersOAuthAuthorizationCodeCollection.create({ db });
640
+ const revocations = await UsersOAuthAccessTokenRevocationCollection.create({ db });
641
+ const grants = await UsersOAuthRefreshGrantCollection.create({ db });
642
+ const families = await UsersOAuthRefreshFamilyCollection.create({ db });
643
+ let total = 0;
644
+ for (const table of [codes.tableName, revocations.tableName]) {
645
+ const prune = async (tx) => {
646
+ if (!options.dryRun) return (await tx.query(`DELETE FROM ${table} WHERE expires_at < ? RETURNING id`, now.toISOString())).rows.length;
647
+ const counted = await tx.query(`SELECT COUNT(*) AS total FROM ${table} WHERE expires_at < ?`, now.toISOString());
648
+ return Number(counted.rows[0]?.total ?? 0);
649
+ };
650
+ total += options.dryRun ? await prune(db) : await withOAuthTransaction(db, prune);
651
+ }
652
+ const candidates = await db.query(`SELECT id FROM ${families.tableName} f WHERE EXISTS (SELECT 1 FROM ${grants.tableName} g WHERE g.family_id = CAST(f.id AS TEXT) AND g.expires_at < ?) OR NOT EXISTS (SELECT 1 FROM ${grants.tableName} g WHERE g.family_id = CAST(f.id AS TEXT)) ORDER BY id`, cutoff);
653
+ for (const candidate of candidates.rows) {
654
+ const id = String(candidate.id);
655
+ const prune = async (tx) => {
656
+ if (!options.dryRun) {
657
+ if ((await tx.query(`UPDATE ${families.tableName} SET updated_at = ? WHERE id = ?`, now.toISOString(), id)).rowCount !== 1) return 0;
658
+ }
659
+ const counted = await tx.query(`SELECT COUNT(*) AS total FROM ${grants.tableName} WHERE family_id = ? AND expires_at < ?`, id, cutoff);
660
+ const retained = await tx.query(`SELECT COUNT(*) AS total FROM ${grants.tableName} WHERE family_id = ? AND expires_at >= ?`, id, cutoff);
661
+ const empty = Number(retained.rows[0]?.total ?? 0) === 0;
662
+ if (!options.dryRun) {
663
+ await tx.query(`DELETE FROM ${grants.tableName} WHERE family_id = ? AND expires_at < ?`, id, cutoff);
664
+ if (empty) await tx.query(`DELETE FROM ${families.tableName} WHERE id = ?`, id);
665
+ }
666
+ return Number(counted.rows[0]?.total ?? 0) + Number(empty);
667
+ };
668
+ total += options.dryRun ? await prune(db) : await withOAuthTransaction(db, prune);
669
+ }
670
+ return total;
671
+ }
672
+ //#endregion
282
673
  //#region src/retention.ts
283
674
  var SESSIONS_RETENTION_TASK = "users-sessions";
284
675
  var MAGIC_LINK_RETENTION_TASK = "users-magic-link-tokens";
@@ -286,7 +677,9 @@ var CLI_AUTH_RETENTION_TASK = "users-cli-auth-requests";
286
677
  var LOGIN_ATTEMPTS_RETENTION_TASK = "users-login-attempts";
287
678
  var LOGIN_AUDIT_RETENTION_TASK = "users-login-audit-events";
288
679
  var DEFAULT_LOGIN_AUDIT_RETENTION_DAYS = 90;
680
+ var OAUTH_CREDENTIALS_RETENTION_TASK = "users-oauth-credentials";
289
681
  var USER_RETENTION_TASKS = [
682
+ OAUTH_CREDENTIALS_RETENTION_TASK,
290
683
  SESSIONS_RETENTION_TASK,
291
684
  MAGIC_LINK_RETENTION_TASK,
292
685
  CLI_AUTH_RETENTION_TASK,
@@ -294,6 +687,14 @@ var USER_RETENTION_TASKS = [
294
687
  LOGIN_AUDIT_RETENTION_TASK
295
688
  ];
296
689
  function registerUserRetentionTasks() {
690
+ registerRetentionTask({
691
+ name: OAUTH_CREDENTIALS_RETENTION_TASK,
692
+ description: "Delete expired OAuth credentials after their replay window",
693
+ run: (db, context) => pruneOAuthCredentials(db, {
694
+ dryRun: context.dryRun,
695
+ now: context.now
696
+ })
697
+ });
297
698
  registerRetentionTask({
298
699
  name: SESSIONS_RETENTION_TASK,
299
700
  description: "Delete expired and revoked sessions",
@@ -1492,7 +1893,7 @@ var MagicLinkService = class MagicLinkService {
1492
1893
  * The caller is responsible for emailing the token to the user.
1493
1894
  */
1494
1895
  async generate(email) {
1495
- const { SignJWT } = await import("./chunks/TerminalAuthService-DjGsRtqb.js").then((n) => n.R);
1896
+ const { SignJWT } = await import("./chunks/TerminalAuthService-DWPeKl3k.js").then((n) => n.R);
1496
1897
  const key = await this.getSigningKey();
1497
1898
  const nonce = crypto.randomUUID();
1498
1899
  const normalizedEmail = normalizeEmail(email);
@@ -1521,7 +1922,7 @@ var MagicLinkService = class MagicLinkService {
1521
1922
  * @throws {MagicLinkError} If the token is invalid, expired, or already used
1522
1923
  */
1523
1924
  async verify(token) {
1524
- const { jwtVerify, errors } = await import("./chunks/TerminalAuthService-DjGsRtqb.js").then((n) => n.R);
1925
+ const { jwtVerify, errors } = await import("./chunks/TerminalAuthService-DWPeKl3k.js").then((n) => n.R);
1525
1926
  const key = await this.getSigningKey();
1526
1927
  let payload;
1527
1928
  try {
@@ -1555,6 +1956,404 @@ var MagicLinkService = class MagicLinkService {
1555
1956
  }
1556
1957
  };
1557
1958
  //#endregion
1959
+ //#region src/services/OAuthAuthorizationStorage.ts
1960
+ var SMRT_OAUTH_GRANT_CLAIM = "smrt_grant_id";
1961
+ function authorizationId(grant) {
1962
+ const id = grant.claims?.[SMRT_OAUTH_GRANT_CLAIM];
1963
+ return typeof id === "string" ? id : null;
1964
+ }
1965
+ function codeGrant(row) {
1966
+ return {
1967
+ id: row.id,
1968
+ codeHash: row.codeHash,
1969
+ clientId: row.clientId,
1970
+ subject: row.subject,
1971
+ ...row.tenantId ? { tenantId: row.tenantId } : {},
1972
+ claims: row.getClaims(),
1973
+ redirectUri: row.redirectUri,
1974
+ scopes: row.getScopes(),
1975
+ ...row.resource ? { resource: row.resource } : {},
1976
+ codeChallenge: row.codeChallenge,
1977
+ expiresAt: row.expiresAt
1978
+ };
1979
+ }
1980
+ function refreshGrant(row) {
1981
+ return {
1982
+ id: row.id,
1983
+ tokenHash: row.tokenHash,
1984
+ familyId: row.familyId,
1985
+ clientId: row.clientId,
1986
+ subject: row.subject,
1987
+ ...row.tenantId ? { tenantId: row.tenantId } : {},
1988
+ claims: row.getClaims(),
1989
+ scopes: row.getScopes(),
1990
+ ...row.resource ? { resource: row.resource } : {},
1991
+ expiresAt: row.expiresAt
1992
+ };
1993
+ }
1994
+ var SmrtOAuthAuthorizationStorage = class SmrtOAuthAuthorizationStorage {
1995
+ constructor(db, recoverDatabase) {
1996
+ this.db = db;
1997
+ this.recoverDatabase = recoverDatabase;
1998
+ }
1999
+ db;
2000
+ recoverDatabase;
2001
+ recovering = null;
2002
+ async execute(action) {
2003
+ for (let attempt = 0;; attempt++) {
2004
+ const previous = this.db;
2005
+ try {
2006
+ return await action();
2007
+ } catch (error) {
2008
+ let cause = error;
2009
+ let invalidated = false;
2010
+ for (let depth = 0; depth < 6 && cause && typeof cause === "object"; depth++) {
2011
+ const failure = cause;
2012
+ invalidated ||= failure.connectionInvalidated === true;
2013
+ cause = failure.cause;
2014
+ }
2015
+ const recover = this.recoverDatabase;
2016
+ if (!invalidated || !recover || attempt >= 6) throw error;
2017
+ if (this.db === previous) {
2018
+ this.recovering ??= (async () => {
2019
+ const db = await recover();
2020
+ if (!db.transaction) throw new Error("OAuth recovery requires transaction support.");
2021
+ this.db = db;
2022
+ })().finally(() => {
2023
+ this.recovering = null;
2024
+ });
2025
+ await this.recovering;
2026
+ }
2027
+ await setTimeout(5 * 2 ** attempt);
2028
+ }
2029
+ }
2030
+ }
2031
+ static async create(options) {
2032
+ const rows = await UsersOAuthClientCollection.create(options.recoverDatabase ? {
2033
+ ...options,
2034
+ db: await options.recoverDatabase()
2035
+ } : options);
2036
+ if (!rows.db.transaction) throw new Error("OAuth storage requires transaction support.");
2037
+ return new SmrtOAuthAuthorizationStorage(rows.db, options.recoverDatabase);
2038
+ }
2039
+ async lockAuthorization(db, id, now) {
2040
+ if (!id) return true;
2041
+ return (await db.query("UPDATE users_oauth_authorizations SET updated_at = ? WHERE id = ? AND revoked_at IS NULL", now.toISOString(), id)).rowCount === 1;
2042
+ }
2043
+ async revokeAuthorization(db, id, now) {
2044
+ if (!id) return;
2045
+ const time = now.toISOString();
2046
+ await db.query("UPDATE users_oauth_authorizations SET revoked_at = ?, updated_at = ? WHERE id = ?", time, time, id);
2047
+ await db.query("UPDATE users_oauth_authorization_codes SET consumed_at = ? WHERE authorization_id = ? AND consumed_at IS NULL", time, id);
2048
+ await db.query("UPDATE users_oauth_refresh_families SET revoked_at = ? WHERE authorization_id = ?", time, id);
2049
+ await db.query("UPDATE users_oauth_refresh_grants SET revoked_at = ? WHERE authorization_id = ?", time, id);
2050
+ }
2051
+ async getClient(clientId) {
2052
+ return this.execute(async () => {
2053
+ const client = await (await UsersOAuthClientCollection.create({ db: this.db })).findByClientId(clientId);
2054
+ return client ? {
2055
+ id: client.clientId,
2056
+ redirectUris: client.getRedirectUris(),
2057
+ allowedScopes: client.getAllowedScopes(),
2058
+ tokenEndpointAuthMethod: client.tokenEndpointAuthMethod,
2059
+ ...client.secretHash ? { secretHash: client.secretHash } : {},
2060
+ ...client.getAllowedResources() !== void 0 ? { allowedResources: client.getAllowedResources() } : {},
2061
+ createdAt: client.createdAt
2062
+ } : null;
2063
+ });
2064
+ }
2065
+ async registerClient(client) {
2066
+ return this.execute(async () => {
2067
+ await (await (await UsersOAuthClientCollection.create({ db: this.db })).create({
2068
+ clientId: client.id,
2069
+ redirectUris: JSON.stringify(client.redirectUris),
2070
+ allowedScopes: JSON.stringify(client.allowedScopes),
2071
+ tokenEndpointAuthMethod: client.tokenEndpointAuthMethod,
2072
+ secretHash: client.secretHash ?? null,
2073
+ allowedResources: JSON.stringify(client.allowedResources ?? null),
2074
+ createdAt: client.createdAt,
2075
+ _insertOnly: true
2076
+ })).save();
2077
+ });
2078
+ }
2079
+ async createAuthorizationCode(grant) {
2080
+ return this.execute(async () => {
2081
+ await withOAuthTransaction(this.db, async (db) => {
2082
+ if (!await this.lockAuthorization(db, authorizationId(grant), /* @__PURE__ */ new Date())) throw new Error("Authorization is revoked.");
2083
+ await (await (await UsersOAuthAuthorizationCodeCollection.create({ db })).create({
2084
+ id: grant.id,
2085
+ authorizationId: authorizationId(grant),
2086
+ codeHash: grant.codeHash,
2087
+ clientId: grant.clientId,
2088
+ subject: grant.subject,
2089
+ tenantId: grant.tenantId ?? null,
2090
+ claims: JSON.stringify(grant.claims ?? {}),
2091
+ redirectUri: grant.redirectUri,
2092
+ scopes: JSON.stringify(grant.scopes),
2093
+ resource: grant.resource ?? null,
2094
+ codeChallenge: grant.codeChallenge,
2095
+ expiresAt: grant.expiresAt,
2096
+ consumedAt: null,
2097
+ _insertOnly: true
2098
+ })).save();
2099
+ });
2100
+ });
2101
+ }
2102
+ async consumeAuthorizationCode(input) {
2103
+ return this.execute(async () => {
2104
+ const row = await (await UsersOAuthAuthorizationCodeCollection.create({ db: this.db })).get(input.id);
2105
+ if (!row || row.codeHash !== input.codeHash || row.clientId !== input.clientId || row.redirectUri !== input.redirectUri || (row.resource ?? void 0) !== input.resource) return { status: "invalid" };
2106
+ return withOAuthTransaction(this.db, async (db) => {
2107
+ if (!await this.lockAuthorization(db, row.authorizationId, input.now)) return { status: "invalid" };
2108
+ const rows = await UsersOAuthAuthorizationCodeCollection.create({ db });
2109
+ if (await rows.consume(input.id, input.codeHash, input.clientId, input.redirectUri, input.resource ?? null, input.now)) return {
2110
+ status: "consumed",
2111
+ grant: codeGrant(row)
2112
+ };
2113
+ const current = await rows.get(input.id);
2114
+ return { status: current?.consumedAt ? "replayed" : current && current.expiresAt <= input.now ? "expired" : "invalid" };
2115
+ });
2116
+ });
2117
+ }
2118
+ async createRefreshGrant(grant) {
2119
+ return this.execute(async () => {
2120
+ await withOAuthTransaction(this.db, async (db) => {
2121
+ if (!await this.lockAuthorization(db, authorizationId(grant), /* @__PURE__ */ new Date())) throw new Error("Authorization is revoked.");
2122
+ await (await (await UsersOAuthRefreshFamilyCollection.create({ db })).create({
2123
+ id: grant.familyId,
2124
+ authorizationId: authorizationId(grant),
2125
+ revokedAt: null,
2126
+ _insertOnly: true
2127
+ })).save();
2128
+ await this.saveRefresh(await UsersOAuthRefreshGrantCollection.create({ db }), grant);
2129
+ });
2130
+ });
2131
+ }
2132
+ async rotateRefreshGrant(input) {
2133
+ return this.execute(async () => {
2134
+ const initial = await (await UsersOAuthRefreshGrantCollection.create({ db: this.db })).get(input.id);
2135
+ if (!initial || initial.tokenHash !== input.tokenHash || initial.clientId !== input.clientId || (initial.resource ?? void 0) !== input.resource) return { status: "invalid" };
2136
+ return withOAuthTransaction(this.db, async (db) => {
2137
+ if (!await this.lockAuthorization(db, initial.authorizationId, input.now)) return { status: "revoked" };
2138
+ const families = await UsersOAuthRefreshFamilyCollection.create({ db });
2139
+ if (!await families.lock(initial.familyId, input.now)) return { status: "invalid" };
2140
+ const family = await families.get(initial.familyId);
2141
+ const rows = await UsersOAuthRefreshGrantCollection.create({ db });
2142
+ const row = await rows.get(input.id);
2143
+ if (!row) return { status: "invalid" };
2144
+ if (family?.revokedAt || row.revokedAt) return { status: "revoked" };
2145
+ if (row.consumedAt) {
2146
+ await families.revoke(row.familyId, input.now);
2147
+ await rows.revokeFamily(row.familyId, input.now);
2148
+ await this.revokeAuthorization(db, row.authorizationId, input.now);
2149
+ return { status: "replayed" };
2150
+ }
2151
+ if (row.expiresAt <= input.now) return { status: "expired" };
2152
+ if (!await rows.consume(input.id, input.tokenHash, input.clientId, input.resource ?? null, input.now)) return { status: "invalid" };
2153
+ const grant = refreshGrant(row);
2154
+ await this.saveRefresh(rows, {
2155
+ ...grant,
2156
+ ...input.replacement
2157
+ });
2158
+ return {
2159
+ status: "rotated",
2160
+ grant
2161
+ };
2162
+ });
2163
+ });
2164
+ }
2165
+ /** Persist a narrowed replacement before the SDK exposes it to a caller. */
2166
+ async narrowRefreshGrant(input) {
2167
+ return this.execute(async () => {
2168
+ const initial = await (await UsersOAuthRefreshGrantCollection.create({ db: this.db })).get(input.id);
2169
+ if (!initial || initial.tokenHash !== input.tokenHash) throw new Error("Invalid refresh grant.");
2170
+ await withOAuthTransaction(this.db, async (db) => {
2171
+ const now = /* @__PURE__ */ new Date();
2172
+ if (!await this.lockAuthorization(db, initial.authorizationId, now)) throw new Error("Authorization is revoked.");
2173
+ const families = await UsersOAuthRefreshFamilyCollection.create({ db });
2174
+ if (!await families.lock(initial.familyId, now)) throw new Error("Invalid refresh family.");
2175
+ const family = await families.get(initial.familyId);
2176
+ const row = await (await UsersOAuthRefreshGrantCollection.create({ db })).get(input.id);
2177
+ if (!row || row.tokenHash !== input.tokenHash || family?.revokedAt || row.revokedAt || row.consumedAt || row.expiresAt <= now || input.scopes.some((scope) => !row.getScopes().includes(scope))) throw new Error("Invalid refresh scope narrowing.");
2178
+ await db.query("UPDATE users_oauth_refresh_grants SET scopes = ?, claims = ?, updated_at = ? WHERE id = ?", JSON.stringify(input.scopes), JSON.stringify(input.claims ?? {}), now.toISOString(), input.id);
2179
+ });
2180
+ });
2181
+ }
2182
+ async revokeRefreshGrant(input) {
2183
+ return this.execute(async () => {
2184
+ const row = await (await UsersOAuthRefreshGrantCollection.create({ db: this.db })).get(input.id);
2185
+ if (!row || row.tokenHash !== input.tokenHash) return;
2186
+ await withOAuthTransaction(this.db, async (db) => {
2187
+ await this.lockAuthorization(db, row.authorizationId, input.now);
2188
+ const families = await UsersOAuthRefreshFamilyCollection.create({ db });
2189
+ await families.lock(row.familyId, input.now);
2190
+ await families.revoke(row.familyId, input.now);
2191
+ await this.revokeAuthorization(db, row.authorizationId, input.now);
2192
+ await (await UsersOAuthRefreshGrantCollection.create({ db })).revokeFamily(row.familyId, input.now);
2193
+ });
2194
+ });
2195
+ }
2196
+ async revokeAccessToken(input) {
2197
+ return this.execute(async () => {
2198
+ await withOAuthTransaction(this.db, async (db) => {
2199
+ await db.query("INSERT INTO users_oauth_access_token_revocations (id, slug, jti, expires_at) VALUES (?, ?, ?, ?) ON CONFLICT (jti) DO NOTHING", randomUUID(), randomUUID(), input.jti, input.expiresAt.toISOString());
2200
+ });
2201
+ });
2202
+ }
2203
+ async isAccessTokenRevoked(jti, now) {
2204
+ return this.execute(async () => {
2205
+ const row = await (await UsersOAuthAccessTokenRevocationCollection.create({ db: this.db })).findByJti(jti);
2206
+ return !!row && row.expiresAt > now;
2207
+ });
2208
+ }
2209
+ async saveRefresh(rows, grant) {
2210
+ await (await rows.create({
2211
+ id: grant.id,
2212
+ authorizationId: authorizationId(grant),
2213
+ tokenHash: grant.tokenHash,
2214
+ familyId: grant.familyId,
2215
+ clientId: grant.clientId,
2216
+ subject: grant.subject,
2217
+ tenantId: grant.tenantId ?? null,
2218
+ claims: JSON.stringify(grant.claims ?? {}),
2219
+ scopes: JSON.stringify(grant.scopes),
2220
+ resource: grant.resource ?? null,
2221
+ expiresAt: grant.expiresAt,
2222
+ consumedAt: null,
2223
+ revokedAt: null,
2224
+ _insertOnly: true
2225
+ })).save();
2226
+ }
2227
+ };
2228
+ //#endregion
2229
+ //#region src/services/OAuthAuthorizationService.ts
2230
+ var SmrtOAuthAuthorizationService = class SmrtOAuthAuthorizationService {
2231
+ constructor(options, sessions, grants) {
2232
+ this.options = options;
2233
+ this.sessions = sessions;
2234
+ this.grants = grants;
2235
+ }
2236
+ options;
2237
+ sessions;
2238
+ grants;
2239
+ static async create(options) {
2240
+ const sessions = await SessionService.create({
2241
+ ...options,
2242
+ autoExtend: false
2243
+ });
2244
+ return new SmrtOAuthAuthorizationService(options, sessions, await UsersOAuthAuthorizationCollection.create({ db: sessions.getDatabase() }));
2245
+ }
2246
+ /** Suitable for createAuthorizationServer({ identity: service.identity }). */
2247
+ identity = {
2248
+ refreshConsent: (context, grant) => this.revalidateConsent(context, grant),
2249
+ revalidateConsent: (context, grant) => this.revalidateConsent(context, grant)
2250
+ };
2251
+ async liveSession(sessionId) {
2252
+ const context = await this.sessions.loadSessionContext(sessionId);
2253
+ if (!context) return null;
2254
+ if (context.tenantId) {
2255
+ if (!context.tenantAuthorization?.membershipId) return null;
2256
+ if (!(await (await TenantCollection.create({ db: this.sessions.getDatabase() })).get(context.tenantId))?.isActive()) return null;
2257
+ }
2258
+ return context;
2259
+ }
2260
+ permits(context, scopes) {
2261
+ return scopes.every((scope) => Object.hasOwn(this.options.scopePermissions, scope) && this.options.scopePermissions[scope].every((permission) => context.permissions.includes(permission)));
2262
+ }
2263
+ /** Call only after an explicit user consent action; the session is loaded again. */
2264
+ async approve(server, request, sessionId) {
2265
+ const context = await this.liveSession(sessionId);
2266
+ if (!context || !this.permits(context, request.scopes)) throw new OAuthServerError("access_denied", "Authorization denied.", 403);
2267
+ const row = await this.grants.create({
2268
+ subject: context.user.id,
2269
+ sessionId,
2270
+ clientId: request.clientId,
2271
+ tenantId: context.tenantId,
2272
+ scopes: JSON.stringify(request.scopes),
2273
+ permissionCeiling: JSON.stringify(context.permissions),
2274
+ resource: request.resource ?? null,
2275
+ revokedAt: null,
2276
+ _insertOnly: true
2277
+ });
2278
+ await row.save();
2279
+ try {
2280
+ return await server.approve(request, {
2281
+ subject: context.user.id,
2282
+ ...context.tenantId ? { tenantId: context.tenantId } : {},
2283
+ claims: { [SMRT_OAUTH_GRANT_CLAIM]: row.id }
2284
+ });
2285
+ } catch (error) {
2286
+ await this.revokeOwned(context.user.id, row.id);
2287
+ throw error;
2288
+ }
2289
+ }
2290
+ async resolve(grantId, subject, tenantId, clientId, scopes, resource) {
2291
+ if (typeof grantId !== "string" || typeof subject !== "string" || typeof clientId !== "string") return null;
2292
+ const grant = await this.grants.get(grantId);
2293
+ if (!grant || grant.revokedAt || grant.subject !== subject || grant.clientId !== clientId || (grant.tenantId ?? void 0) !== (tenantId ?? void 0) || grant.resource && grant.resource !== resource || scopes.some((scope) => !grant.getScopes().includes(scope))) return null;
2294
+ const context = await this.liveSession(grant.sessionId);
2295
+ if (!context || context.user.id !== grant.subject || context.tenantId !== grant.tenantId || !this.permits(context, scopes) || scopes.some((scope) => this.options.scopePermissions[scope]?.some((permission) => !grant.getPermissionCeiling().includes(permission)))) return null;
2296
+ const current = await this.grants.get(grantId);
2297
+ if (!current || current.revokedAt) return null;
2298
+ const allowed = new Set(scopes.flatMap((scope) => this.options.scopePermissions[scope] ?? []));
2299
+ const permissions = context.permissions.filter((permission) => allowed.has(permission));
2300
+ return {
2301
+ ...context,
2302
+ permissions,
2303
+ permissionCeiling: permissions
2304
+ };
2305
+ }
2306
+ async revalidateConsent(context, grant) {
2307
+ return await this.resolve(context.claims?.["smrt_grant_id"], grant.subject, grant.tenantId, grant.clientId, grant.scopes, grant.resource) && context.subject === grant.subject && context.tenantId === grant.tenantId ? context : null;
2308
+ }
2309
+ /** Call after SDK signature/audience/revocation verification, never on decoded-only JWTs. */
2310
+ async validateAccessTokenClaims(payload) {
2311
+ if (typeof payload.scope !== "string") return null;
2312
+ return this.resolve(payload[SMRT_OAUTH_GRANT_CLAIM], payload.sub, payload.tenant_id, payload.client_id, payload.scope.split(" ").filter(Boolean), payload.aud);
2313
+ }
2314
+ /** Lists only the current authenticated user's consent decisions. */
2315
+ async listGrants(sessionId) {
2316
+ const context = await this.liveSession(sessionId);
2317
+ if (!context) throw new OAuthServerError("access_denied", "Sign in required.", 401);
2318
+ const result = await this.sessions.getDatabase().query("SELECT id FROM users_oauth_authorizations WHERE subject = ? ORDER BY created_at DESC", context.user.id);
2319
+ const grants = [];
2320
+ for (const row of result.rows) {
2321
+ const grant = await this.grants.get(String(row.id));
2322
+ if (grant) grants.push(this.summary(grant));
2323
+ }
2324
+ return grants;
2325
+ }
2326
+ /** Revocation is idempotent and confined to the authenticated subject. */
2327
+ async revokeGrant(sessionId, grantId) {
2328
+ const context = await this.liveSession(sessionId);
2329
+ if (!context) throw new OAuthServerError("access_denied", "Sign in required.", 401);
2330
+ return this.revokeOwned(context.user.id, grantId);
2331
+ }
2332
+ async revokeOwned(subject, grantId) {
2333
+ const db = this.sessions.getDatabase();
2334
+ if (!db.transaction) throw new Error("OAuth revocation requires transaction support.");
2335
+ return withOAuthTransaction(db, async (db2) => {
2336
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2337
+ if ((await db2.query("UPDATE users_oauth_authorizations SET revoked_at = ?, updated_at = ? WHERE id = ? AND subject = ?", now, now, grantId, subject)).rowCount !== 1) return false;
2338
+ await db2.query("UPDATE users_oauth_authorization_codes SET consumed_at = ? WHERE authorization_id = ? AND consumed_at IS NULL", now, grantId);
2339
+ await db2.query("UPDATE users_oauth_refresh_families SET revoked_at = ? WHERE authorization_id = ?", now, grantId);
2340
+ await db2.query("UPDATE users_oauth_refresh_grants SET revoked_at = ? WHERE authorization_id = ?", now, grantId);
2341
+ return true;
2342
+ });
2343
+ }
2344
+ summary(grant) {
2345
+ return {
2346
+ id: grant.id,
2347
+ clientId: grant.clientId,
2348
+ tenantId: grant.tenantId,
2349
+ scopes: grant.getScopes(),
2350
+ resource: grant.resource,
2351
+ createdAt: grant.created_at ?? null,
2352
+ revokedAt: grant.revokedAt
2353
+ };
2354
+ }
2355
+ };
2356
+ //#endregion
1558
2357
  //#region src/services/PostgresPermissionPolicies.ts
1559
2358
  function toSnakeCase(value) {
1560
2359
  return value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[-\s]+/g, "_").toLowerCase();
@@ -2119,6 +2918,6 @@ var TenantService = class TenantService {
2119
2918
  //#region src/index.ts
2120
2919
  registerUserRetentionTasks();
2121
2920
  //#endregion
2122
- export { ACCESS_REQUEST_CAPABILITIES, ANCESTOR_READ_ACTION, AccessRequest, AccessRequestCollection, AccessRequestError, AccessRequestService, AccessRequestStatus, CLI_AUTH_RETENTION_TASK, UsersCliAuthRequest as CliAuthRequest, UsersCliAuthRequest, UsersCliAuthRequestCollection as CliAuthRequestCollection, UsersCliAuthRequestCollection, DEFAULT_ANCESTOR_READ_MAX_DEPTH, DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, DEFAULT_CLI_SESSION_TTL_SECONDS, DEFAULT_DEVICE_PERSON_IDLE_SECONDS, DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, DEFAULT_LOGIN_AUDIT_RETENTION_DAYS, DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, DEFAULT_LOGIN_LOCKOUT_FACTOR, DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, DEFAULT_LOGIN_MAX_ATTEMPTS, DEFAULT_PASSWORD_DENYLIST, DEFAULT_PASSWORD_MANAGE_PERMISSION, DEFAULT_PASSWORD_MAX_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH, DEFAULT_PIN_MANAGE_PERMISSION, DEFAULT_ROLES, DEFAULT_ROLE_PERMISSION_PATTERNS, DEFAULT_ROLE_SLUGS, DEFAULT_SESSION_TTL, DEFAULT_TENANT_POLICY, DEFAULT_TOKEN_EXPIRY_SECONDS, DeviceCredentialError, DeviceCredentialForbiddenError, DeviceCredentialPolicyError, DeviceCredentialService, DurableLoginAuditSink, Group, GroupCollection, GroupMember, GroupMemberCollection, GroupRole, GroupRoleCollection, InvalidCredentialsError, LEGACY_USER_PROFILE_BACKFILL_NAME, LOGIN_ATTEMPTS_RETENTION_TASK, LOGIN_AUDIT_RETENTION_TASK, LegacyUserProfileBackfillError, LoginAttemptLimiter, LoginRateLimitError, MAGIC_LINK_RETENTION_TASK, MAX_RESOURCE_GRANT_DELEGATION_DEPTH, MAX_TENANT_HIERARCHY_DEPTH, MagicLinkError, MagicLinkService, UsersMagicLinkToken as MagicLinkToken, UsersMagicLinkToken, UsersMagicLinkTokenCollection as MagicLinkTokenCollection, UsersMagicLinkTokenCollection, Membership, MembershipCollection, MembershipOverride, MembershipOverrideCollection, MembershipStatus, MobileAuthError, MobileAuthService, OidcLoginError, OidcLoginService, OidcProvisioningError, OperationPermissionError, OverrideEffect, PASSWORD_LOGIN_KIND, PASSWORD_MAX_LENGTH_CEILING, PASSWORD_PERMISSION_DEFINITIONS, PIN_LOGIN_KIND, PIN_PERMISSION_DEFINITIONS, PasswordCredentialError, PasswordCredentialForbiddenError, PasswordCredentialService, PasswordPolicyError, Permission, PermissionCatalogService, PermissionCollection, PermissionResolver, PinVerifier, ResourceGrant, ResourceGrantCollection, ResourceGrantService, Role, RoleCollection, RolePermission, RolePermissionCollection, SESSIONS_RETENTION_TASK, SESSION_DATA_KEYS, Session, SessionCollection, SessionService, SessionStatus, TERMINAL_APPROVE_LOGIN_KIND, Tenant, TenantCollection, TenantHierarchyError, TenantHierarchyMaterializationError, TenantIntegration, TenantIntegrationCollection, TenantPermissionEffect, TenantPermissionOverride, TenantPermissionOverrideCollection, TenantService, TenantStatus, TerminalAuthError, TerminalAuthRateLimitError, TerminalAuthService, USER_RETENTION_TASKS, User, UserCollection, UserEmailKeyBackfillError, UserStatus, UsersCliAuthApproveLimit, UsersCliAuthApproveLimitCollection, UsersLoginAttempt, UsersLoginAttemptCollection, UsersLoginAuditEvent, UsersLoginAuditEventCollection, UsersPasswordCredential, UsersPasswordCredentialCollection, UsersPinCredential, UsersPinCredentialCollection, UsersRolesAndPermissionsRecipe, UsersSignInRecipe, applyPostgresPermissionPolicies, assertOperationPermission, backfillLegacyUserProfiles, backfillUserEmailKeys, checkOperationPermission, checkResourceOperationPermission, decodeOidcTransaction, deduplicateRolePermissions, deriveOperationPermissionCollectionName, deriveOperationPermissionSlug, encodeOidcTransaction, ensurePasswordPermissionsRegistered, ensurePinPermissionsRegistered, generatePostgresPermissionSql, generateSessionId, getConfiguredAncestorReadPolicy, getCurrentSessionPermissionContext, getRequestScopedDatabase, getUsersOidcConfig, hasOperationPermission, isAncestorReadableSlug, materializeTenantHierarchy, normalizeAncestorReadPolicy, normalizeOperationPermissionAction, planTenantHierarchy, readMobileBearerToken, registerPermissionDefinitions, registerUserRetentionTasks, resolveOidcProviderConfig, syncPermissionCatalog, unregisterUserRetentionTasks, validateMobileRedirectUri, withPrincipalPermissionContext, withSessionPermissionContext };
2921
+ export { ACCESS_REQUEST_CAPABILITIES, ANCESTOR_READ_ACTION, AccessRequest, AccessRequestCollection, AccessRequestError, AccessRequestService, AccessRequestStatus, CLI_AUTH_RETENTION_TASK, UsersCliAuthRequest as CliAuthRequest, UsersCliAuthRequest, UsersCliAuthRequestCollection as CliAuthRequestCollection, UsersCliAuthRequestCollection, DEFAULT_ANCESTOR_READ_MAX_DEPTH, DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, DEFAULT_CLI_SESSION_TTL_SECONDS, DEFAULT_DEVICE_PERSON_IDLE_SECONDS, DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, DEFAULT_LOGIN_AUDIT_RETENTION_DAYS, DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, DEFAULT_LOGIN_LOCKOUT_FACTOR, DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, DEFAULT_LOGIN_MAX_ATTEMPTS, DEFAULT_PASSWORD_DENYLIST, DEFAULT_PASSWORD_MANAGE_PERMISSION, DEFAULT_PASSWORD_MAX_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH, DEFAULT_PIN_MANAGE_PERMISSION, DEFAULT_ROLES, DEFAULT_ROLE_PERMISSION_PATTERNS, DEFAULT_ROLE_SLUGS, DEFAULT_SESSION_TTL, DEFAULT_TENANT_POLICY, DEFAULT_TOKEN_EXPIRY_SECONDS, DeviceCredentialError, DeviceCredentialForbiddenError, DeviceCredentialPolicyError, DeviceCredentialService, DurableLoginAuditSink, Group, GroupCollection, GroupMember, GroupMemberCollection, GroupRole, GroupRoleCollection, InvalidCredentialsError, LEGACY_USER_PROFILE_BACKFILL_NAME, LOGIN_ATTEMPTS_RETENTION_TASK, LOGIN_AUDIT_RETENTION_TASK, LegacyUserProfileBackfillError, LoginAttemptLimiter, LoginRateLimitError, MAGIC_LINK_RETENTION_TASK, MAX_RESOURCE_GRANT_DELEGATION_DEPTH, MAX_TENANT_HIERARCHY_DEPTH, MagicLinkError, MagicLinkService, UsersMagicLinkToken as MagicLinkToken, UsersMagicLinkToken, UsersMagicLinkTokenCollection as MagicLinkTokenCollection, UsersMagicLinkTokenCollection, Membership, MembershipCollection, MembershipOverride, MembershipOverrideCollection, MembershipStatus, MobileAuthError, MobileAuthService, OAUTH_CREDENTIALS_RETENTION_TASK, OidcLoginError, OidcLoginService, OidcProvisioningError, OperationPermissionError, OverrideEffect, PASSWORD_LOGIN_KIND, PASSWORD_MAX_LENGTH_CEILING, PASSWORD_PERMISSION_DEFINITIONS, PIN_LOGIN_KIND, PIN_PERMISSION_DEFINITIONS, PasswordCredentialError, PasswordCredentialForbiddenError, PasswordCredentialService, PasswordPolicyError, Permission, PermissionCatalogService, PermissionCollection, PermissionResolver, PinVerifier, ResourceGrant, ResourceGrantCollection, ResourceGrantService, Role, RoleCollection, RolePermission, RolePermissionCollection, SESSIONS_RETENTION_TASK, SESSION_DATA_KEYS, SMRT_OAUTH_GRANT_CLAIM, Session, SessionCollection, SessionService, SessionStatus, SmrtOAuthAuthorizationService, SmrtOAuthAuthorizationStorage, TERMINAL_APPROVE_LOGIN_KIND, Tenant, TenantCollection, TenantHierarchyError, TenantHierarchyMaterializationError, TenantIntegration, TenantIntegrationCollection, TenantPermissionEffect, TenantPermissionOverride, TenantPermissionOverrideCollection, TenantService, TenantStatus, TerminalAuthError, TerminalAuthRateLimitError, TerminalAuthService, USER_RETENTION_TASKS, User, UserCollection, UserEmailKeyBackfillError, UserStatus, UsersCliAuthApproveLimit, UsersCliAuthApproveLimitCollection, UsersLoginAttempt, UsersLoginAttemptCollection, UsersLoginAuditEvent, UsersLoginAuditEventCollection, UsersOAuthAccessTokenRevocation, UsersOAuthAccessTokenRevocationCollection, UsersOAuthAuthorization, UsersOAuthAuthorizationCode, UsersOAuthAuthorizationCodeCollection, UsersOAuthAuthorizationCollection, UsersOAuthClient, UsersOAuthClientCollection, UsersOAuthRefreshFamily, UsersOAuthRefreshFamilyCollection, UsersOAuthRefreshGrant, UsersOAuthRefreshGrantCollection, UsersPasswordCredential, UsersPasswordCredentialCollection, UsersPinCredential, UsersPinCredentialCollection, UsersRolesAndPermissionsRecipe, UsersSignInRecipe, applyPostgresPermissionPolicies, assertOperationPermission, backfillLegacyUserProfiles, backfillUserEmailKeys, checkOperationPermission, checkResourceOperationPermission, decodeOidcTransaction, deduplicateRolePermissions, deriveOperationPermissionCollectionName, deriveOperationPermissionSlug, encodeOidcTransaction, ensurePasswordPermissionsRegistered, ensurePinPermissionsRegistered, generatePostgresPermissionSql, generateSessionId, getConfiguredAncestorReadPolicy, getCurrentSessionPermissionContext, getRequestScopedDatabase, getUsersOidcConfig, hasOperationPermission, isAncestorReadableSlug, materializeTenantHierarchy, normalizeAncestorReadPolicy, normalizeOperationPermissionAction, planTenantHierarchy, readMobileBearerToken, registerPermissionDefinitions, registerUserRetentionTasks, resolveOidcProviderConfig, syncPermissionCatalog, unregisterUserRetentionTasks, validateMobileRedirectUri, withPrincipalPermissionContext, withSessionPermissionContext };
2123
2922
 
2124
2923
  //# sourceMappingURL=index.js.map