@absolutejs/auth 0.57.8 → 0.58.0

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.js CHANGED
@@ -5853,6 +5853,7 @@ var DEFAULT_SMS_CODE_LENGTH = 6;
5853
5853
  var SMS_CODE_TTL_MINUTES = 5;
5854
5854
  var DEFAULT_SMS_CODE_TTL_MS = SMS_CODE_TTL_MINUTES * SECONDS_IN_A_MINUTE * MILLISECONDS_IN_A_SECOND;
5855
5855
  var DEFAULT_SMS_MAX_ATTEMPTS = 3;
5856
+ var DEFAULT_SMS_RESEND_COOLDOWN_MS = 30 * MILLISECONDS_IN_A_SECOND;
5856
5857
  var DEFAULT_TOTP_MAX_ATTEMPTS = 5;
5857
5858
 
5858
5859
  // src/mfa/secret.ts
@@ -5863,6 +5864,20 @@ var encryptTotpSecret = (secret, encryptionKey) => encryptionKey ? encryptSecret
5863
5864
  // src/mfa/sms.ts
5864
5865
  init_crypto();
5865
5866
  import { Elysia as Elysia17, t as t11 } from "elysia";
5867
+
5868
+ // src/verification/types.ts
5869
+ class VerificationProviderError extends Error {
5870
+ kind;
5871
+ provider;
5872
+ constructor(input) {
5873
+ super(input.message, { cause: input.cause });
5874
+ this.name = "VerificationProviderError";
5875
+ this.kind = input.kind;
5876
+ this.provider = input.provider;
5877
+ }
5878
+ }
5879
+
5880
+ // src/mfa/sms.ts
5866
5881
  var DECIMAL_RADIX2 = 10;
5867
5882
  var MASK_VISIBLE_DIGITS = 4;
5868
5883
  var E164_PATTERN = /^\+[1-9]\d{7,14}$/u;
@@ -5877,28 +5892,83 @@ var issueSmsCode = async (codeLength, ttlMs) => {
5877
5892
  const expiresAt = Date.now() + ttlMs;
5878
5893
  return { code, expiresAt, hash };
5879
5894
  };
5895
+ var checkWithVerificationProvider = async (provider, input) => {
5896
+ try {
5897
+ return { result: await provider.check(input) };
5898
+ } catch (error) {
5899
+ const mapped = mapVerificationProviderError(error);
5900
+ if (mapped === undefined)
5901
+ throw error;
5902
+ return { error: mapped };
5903
+ }
5904
+ };
5880
5905
  var isE164Phone = (phone) => E164_PATTERN.test(phone);
5881
5906
  var issueAndStoreSmsCode = async ({
5882
5907
  codeLength,
5883
5908
  enrollment,
5884
5909
  mfaStore,
5885
5910
  onSendSmsCode,
5886
- ttlMs
5911
+ purpose,
5912
+ verificationProvider,
5913
+ ttlMs,
5914
+ userId
5887
5915
  }) => {
5888
5916
  const phone = enrollment.smsPhone;
5889
5917
  if (phone === undefined)
5890
5918
  return;
5919
+ if (verificationProvider !== undefined) {
5920
+ const started = await verificationProvider.start({
5921
+ channel: "sms",
5922
+ purpose,
5923
+ subject: userId,
5924
+ to: phone
5925
+ });
5926
+ await mfaStore.saveEnrollment({
5927
+ ...enrollment,
5928
+ smsCodeSentAt: Date.now(),
5929
+ smsFailedAttempts: 0,
5930
+ smsPendingCodeExpiresAt: started.expiresAt,
5931
+ smsPendingCodeHash: undefined,
5932
+ smsPendingPurpose: purpose,
5933
+ smsProviderReference: started.reference,
5934
+ updatedAt: Date.now()
5935
+ });
5936
+ return started.expiresAt;
5937
+ }
5891
5938
  const { code, expiresAt, hash } = await issueSmsCode(codeLength, ttlMs);
5892
5939
  await mfaStore.saveEnrollment({
5893
5940
  ...enrollment,
5941
+ smsCodeSentAt: Date.now(),
5894
5942
  smsFailedAttempts: 0,
5895
5943
  smsPendingCodeExpiresAt: expiresAt,
5896
5944
  smsPendingCodeHash: hash,
5945
+ smsPendingPurpose: purpose,
5946
+ smsProviderReference: undefined,
5897
5947
  updatedAt: Date.now()
5898
5948
  });
5899
- await onSendSmsCode?.({ code, expiresAt, phone });
5949
+ await onSendSmsCode?.({ code, expiresAt, phone, purpose, userId });
5900
5950
  return expiresAt;
5901
5951
  };
5952
+ var mapVerificationProviderError = (error) => {
5953
+ if (!(error instanceof VerificationProviderError))
5954
+ return;
5955
+ if (error.kind === "rate_limited") {
5956
+ return {
5957
+ message: "Verification provider rate limit reached",
5958
+ status: "Too Many Requests"
5959
+ };
5960
+ }
5961
+ if (error.kind === "invalid_destination") {
5962
+ return {
5963
+ message: "Phone number cannot receive verification codes",
5964
+ status: "Bad Request"
5965
+ };
5966
+ }
5967
+ return {
5968
+ message: "Verification provider unavailable",
5969
+ status: "Service Unavailable"
5970
+ };
5971
+ };
5902
5972
  var maskPhone = (phone) => {
5903
5973
  const visible = phone.slice(-MASK_VISIBLE_DIGITS);
5904
5974
  const maskedLength = Math.max(phone.length - MASK_VISIBLE_DIGITS, 0);
@@ -5910,9 +5980,11 @@ var mfaSmsRoutes = ({
5910
5980
  mfaStore,
5911
5981
  onMfaEnrolled,
5912
5982
  onSendSmsCode,
5983
+ verificationProvider,
5913
5984
  smsCodeLength = DEFAULT_SMS_CODE_LENGTH,
5914
5985
  smsCodeTtlMs = DEFAULT_SMS_CODE_TTL_MS,
5915
5986
  smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS,
5987
+ smsResendCooldownMs = DEFAULT_SMS_RESEND_COOLDOWN_MS,
5916
5988
  smsSetupRoute = "/auth/mfa/sms/setup",
5917
5989
  smsVerifyRoute = "/auth/mfa/sms/verify"
5918
5990
  }) => new Elysia17().use(sessionStore()).post(smsSetupRoute, async ({
@@ -5921,7 +5993,7 @@ var mfaSmsRoutes = ({
5921
5993
  status,
5922
5994
  store: { session }
5923
5995
  }) => {
5924
- if (onSendSmsCode === undefined) {
5996
+ if (onSendSmsCode === undefined && verificationProvider === undefined) {
5925
5997
  return status("Not Implemented", "SMS MFA is not configured");
5926
5998
  }
5927
5999
  const userSession = await loadSessionFromSource({
@@ -5938,21 +6010,51 @@ var mfaSmsRoutes = ({
5938
6010
  const userId = getUserId(userSession.user);
5939
6011
  const existing = await mfaStore.getEnrollment(userId);
5940
6012
  const now = Date.now();
5941
- const { code, expiresAt, hash } = await issueSmsCode(smsCodeLength, smsCodeTtlMs);
6013
+ if (existing?.smsCodeSentAt !== undefined && now - existing.smsCodeSentAt < smsResendCooldownMs) {
6014
+ return status("Too Many Requests", "SMS resend cooldown active");
6015
+ }
6016
+ let started;
6017
+ try {
6018
+ started = verificationProvider ? await verificationProvider.start({
6019
+ channel: "sms",
6020
+ purpose: "mfa_enrollment",
6021
+ subject: userId,
6022
+ to: phone
6023
+ }) : undefined;
6024
+ } catch (error) {
6025
+ const mapped = mapVerificationProviderError(error);
6026
+ if (mapped === undefined)
6027
+ throw error;
6028
+ return status(mapped.status, mapped.message);
6029
+ }
6030
+ const local = started ? undefined : await issueSmsCode(smsCodeLength, smsCodeTtlMs);
5942
6031
  await mfaStore.saveEnrollment({
5943
6032
  backupCodeHashes: existing?.backupCodeHashes ?? [],
5944
6033
  createdAt: existing?.createdAt ?? now,
6034
+ lastUsedAt: existing?.lastUsedAt,
6035
+ smsCodeSentAt: now,
5945
6036
  smsFailedAttempts: 0,
5946
- smsPendingCodeExpiresAt: expiresAt,
5947
- smsPendingCodeHash: hash,
6037
+ smsPendingCodeExpiresAt: started?.expiresAt ?? local?.expiresAt,
6038
+ smsPendingCodeHash: local?.hash,
6039
+ smsPendingPurpose: "mfa_enrollment",
5948
6040
  smsPhone: phone,
6041
+ smsProviderReference: started?.reference,
5949
6042
  smsVerified: false,
6043
+ totpFailedAttempts: existing?.totpFailedAttempts ?? 0,
5950
6044
  totpSecretCiphertext: existing?.totpSecretCiphertext,
5951
6045
  totpVerified: existing?.totpVerified ?? false,
5952
6046
  updatedAt: now,
5953
6047
  userId
5954
6048
  });
5955
- await onSendSmsCode({ code, expiresAt, phone });
6049
+ if (local !== undefined && onSendSmsCode !== undefined) {
6050
+ await onSendSmsCode({
6051
+ code: local.code,
6052
+ expiresAt: local.expiresAt,
6053
+ phone,
6054
+ purpose: "mfa_enrollment",
6055
+ userId
6056
+ });
6057
+ }
5956
6058
  return status("OK", { phone: maskPhone(phone) });
5957
6059
  }, {
5958
6060
  body: t11.Object({ phone: t11.String() }),
@@ -5973,29 +6075,58 @@ var mfaSmsRoutes = ({
5973
6075
  }
5974
6076
  const userId = getUserId(userSession.user);
5975
6077
  const enrollment = await mfaStore.getEnrollment(userId);
5976
- if (!enrollment?.smsPendingCodeHash || enrollment.smsPendingCodeExpiresAt === undefined) {
6078
+ if (!enrollment?.smsPhone) {
6079
+ return status("Bad Request", "No SMS enrollment in progress");
6080
+ }
6081
+ const localCodeHash = enrollment.smsPendingCodeHash;
6082
+ const localCodeExpiresAt = enrollment.smsPendingCodeExpiresAt;
6083
+ const providerReference = enrollment.smsProviderReference;
6084
+ if (enrollment.smsPendingPurpose !== "mfa_enrollment" || localCodeExpiresAt === undefined) {
6085
+ return status("Bad Request", "No SMS enrollment in progress");
6086
+ }
6087
+ if (verificationProvider === undefined && localCodeHash === undefined) {
5977
6088
  return status("Bad Request", "No SMS enrollment in progress");
5978
6089
  }
5979
- if (Date.now() > enrollment.smsPendingCodeExpiresAt) {
6090
+ if (Date.now() > localCodeExpiresAt) {
5980
6091
  return status("Bad Request", "SMS code expired");
5981
6092
  }
5982
6093
  if ((enrollment.smsFailedAttempts ?? 0) >= smsMaxAttempts) {
5983
6094
  return status("Too Many Requests", "Too many attempts");
5984
6095
  }
5985
- const codeValid = await constantTimeEqual(await hashToken(code), enrollment.smsPendingCodeHash);
6096
+ let providerResult;
6097
+ if (verificationProvider !== undefined) {
6098
+ if (providerReference === undefined) {
6099
+ return status("Bad Request", "No SMS enrollment in progress");
6100
+ }
6101
+ const checked = await checkWithVerificationProvider(verificationProvider, {
6102
+ channel: "sms",
6103
+ code,
6104
+ purpose: "mfa_enrollment",
6105
+ reference: providerReference,
6106
+ subject: userId,
6107
+ to: enrollment.smsPhone
6108
+ });
6109
+ if (checked.error !== undefined) {
6110
+ return status(checked.error.status, checked.error.message);
6111
+ }
6112
+ providerResult = checked.result;
6113
+ }
6114
+ const codeValid = providerResult ? providerResult.status === "approved" : localCodeHash !== undefined && await constantTimeEqual(await hashToken(code), localCodeHash);
5986
6115
  if (!codeValid) {
5987
6116
  await mfaStore.saveEnrollment({
5988
6117
  ...enrollment,
5989
6118
  smsFailedAttempts: (enrollment.smsFailedAttempts ?? 0) + 1,
5990
6119
  updatedAt: Date.now()
5991
6120
  });
5992
- return status("Bad Request", "Invalid SMS code");
6121
+ return status(providerResult?.status === "max_attempts_reached" ? "Too Many Requests" : "Bad Request", providerResult?.status === "expired" ? "SMS code expired" : "Invalid SMS code");
5993
6122
  }
5994
6123
  await mfaStore.saveEnrollment({
5995
6124
  ...enrollment,
5996
6125
  smsFailedAttempts: 0,
5997
6126
  smsPendingCodeExpiresAt: undefined,
5998
6127
  smsPendingCodeHash: undefined,
6128
+ smsPendingPurpose: undefined,
6129
+ smsProviderReference: undefined,
5999
6130
  smsVerified: true,
6000
6131
  updatedAt: Date.now()
6001
6132
  });
@@ -6018,10 +6149,12 @@ var mfaChallenge = ({
6018
6149
  onMfaChallengeError,
6019
6150
  onMfaChallengeSuccess,
6020
6151
  onSendSmsCode,
6152
+ verificationProvider,
6021
6153
  sessionDurationMs = DEFAULT_MFA_SESSION_TTL_MS,
6022
6154
  smsCodeLength = DEFAULT_SMS_CODE_LENGTH,
6023
6155
  smsCodeTtlMs = DEFAULT_SMS_CODE_TTL_MS,
6024
6156
  smsMaxAttempts = DEFAULT_SMS_MAX_ATTEMPTS,
6157
+ smsResendCooldownMs = DEFAULT_SMS_RESEND_COOLDOWN_MS,
6025
6158
  totpMaxAttempts = DEFAULT_TOTP_MAX_ATTEMPTS
6026
6159
  }) => new Elysia18().use(sessionStore()).post(challengeRoute, async ({
6027
6160
  body: { action, code, factor },
@@ -6063,27 +6196,48 @@ var mfaChallenge = ({
6063
6196
  await onMfaChallengeSuccess?.({ user, userSessionId });
6064
6197
  return status("OK", { status: "authenticated" });
6065
6198
  };
6066
- const runSmsChallenge = async () => {
6067
- if (!enrollment.smsVerified || !enrollment.smsPhone) {
6068
- return status("Unauthorized", "No MFA challenge in progress");
6199
+ const sendSmsChallenge = async () => {
6200
+ if (enrollment.smsCodeSentAt !== undefined && Date.now() - enrollment.smsCodeSentAt < smsResendCooldownMs) {
6201
+ return status("Too Many Requests", "SMS resend cooldown active");
6069
6202
  }
6070
- if (action === "send") {
6203
+ try {
6071
6204
  await issueAndStoreSmsCode({
6072
6205
  codeLength: smsCodeLength,
6073
6206
  enrollment,
6074
6207
  mfaStore,
6075
6208
  onSendSmsCode,
6076
- ttlMs: smsCodeTtlMs
6209
+ purpose: "mfa_challenge",
6210
+ ttlMs: smsCodeTtlMs,
6211
+ userId: getUserId(user),
6212
+ verificationProvider
6077
6213
  });
6078
- return status("OK", { status: "sent" });
6214
+ } catch (error) {
6215
+ const mapped = mapVerificationProviderError(error);
6216
+ if (mapped === undefined)
6217
+ throw error;
6218
+ return status(mapped.status, mapped.message);
6079
6219
  }
6220
+ return status("OK", { status: "sent" });
6221
+ };
6222
+ const runSmsChallenge = async () => {
6223
+ if (!enrollment.smsVerified || !enrollment.smsPhone) {
6224
+ return status("Unauthorized", "No MFA challenge in progress");
6225
+ }
6226
+ if (action === "send")
6227
+ return sendSmsChallenge();
6080
6228
  if (code === undefined) {
6081
6229
  return status("Bad Request", "SMS code required");
6082
6230
  }
6083
- if (!enrollment.smsPendingCodeHash || enrollment.smsPendingCodeExpiresAt === undefined) {
6231
+ const localCodeHash = enrollment.smsPendingCodeHash;
6232
+ const localCodeExpiresAt = enrollment.smsPendingCodeExpiresAt;
6233
+ const providerReference = enrollment.smsProviderReference;
6234
+ if (enrollment.smsPendingPurpose !== "mfa_challenge" || localCodeExpiresAt === undefined) {
6084
6235
  return status("Bad Request", "No SMS code in progress");
6085
6236
  }
6086
- if (Date.now() > enrollment.smsPendingCodeExpiresAt) {
6237
+ if (verificationProvider === undefined && localCodeHash === undefined) {
6238
+ return status("Bad Request", "No SMS code in progress");
6239
+ }
6240
+ if (Date.now() > localCodeExpiresAt) {
6087
6241
  return status("Unauthorized", "SMS code expired");
6088
6242
  }
6089
6243
  if ((enrollment.smsFailedAttempts ?? 0) >= smsMaxAttempts) {
@@ -6093,7 +6247,25 @@ var mfaChallenge = ({
6093
6247
  });
6094
6248
  return status("Unauthorized", "Too many attempts");
6095
6249
  }
6096
- const smsValid = await constantTimeEqual(await hashToken(code), enrollment.smsPendingCodeHash);
6250
+ let providerResult;
6251
+ if (verificationProvider !== undefined) {
6252
+ if (providerReference === undefined) {
6253
+ return status("Bad Request", "No SMS code in progress");
6254
+ }
6255
+ const checked = await checkWithVerificationProvider(verificationProvider, {
6256
+ channel: "sms",
6257
+ code,
6258
+ purpose: "mfa_challenge",
6259
+ reference: providerReference,
6260
+ subject: getUserId(user),
6261
+ to: enrollment.smsPhone
6262
+ });
6263
+ if (checked.error !== undefined) {
6264
+ return status(checked.error.status, checked.error.message);
6265
+ }
6266
+ providerResult = checked.result;
6267
+ }
6268
+ const smsValid = providerResult ? providerResult.status === "approved" : localCodeHash !== undefined && await constantTimeEqual(await hashToken(code), localCodeHash);
6097
6269
  if (!smsValid) {
6098
6270
  await mfaStore.saveEnrollment({
6099
6271
  ...enrollment,
@@ -6104,7 +6276,7 @@ var mfaChallenge = ({
6104
6276
  error: new Error("invalid_mfa_code"),
6105
6277
  userId: getUserId(user)
6106
6278
  });
6107
- return status("Unauthorized", "Invalid MFA code");
6279
+ return status(providerResult?.status === "max_attempts_reached" ? "Too Many Requests" : "Unauthorized", providerResult?.status === "expired" ? "SMS code expired" : "Invalid MFA code");
6108
6280
  }
6109
6281
  await mfaStore.saveEnrollment({
6110
6282
  ...enrollment,
@@ -6112,6 +6284,8 @@ var mfaChallenge = ({
6112
6284
  smsFailedAttempts: 0,
6113
6285
  smsPendingCodeExpiresAt: undefined,
6114
6286
  smsPendingCodeHash: undefined,
6287
+ smsPendingPurpose: undefined,
6288
+ smsProviderReference: undefined,
6115
6289
  updatedAt: Date.now()
6116
6290
  });
6117
6291
  return promote();
@@ -31840,12 +32014,15 @@ var mfaEnrollmentsTable = pgTable("auth_mfa_enrollments", {
31840
32014
  backup_code_hashes: jsonb("backup_code_hashes").$type().notNull().default([]),
31841
32015
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
31842
32016
  last_used_at_ms: bigint("last_used_at_ms", { mode: "number" }),
32017
+ sms_code_sent_at_ms: bigint("sms_code_sent_at_ms", { mode: "number" }),
31843
32018
  sms_failed_attempts: smallint("sms_failed_attempts").notNull().default(0),
31844
32019
  sms_pending_code_expires_at_ms: bigint("sms_pending_code_expires_at_ms", {
31845
32020
  mode: "number"
31846
32021
  }),
31847
32022
  sms_pending_code_hash: text("sms_pending_code_hash"),
32023
+ sms_pending_purpose: text("sms_pending_purpose").$type(),
31848
32024
  sms_phone: varchar("sms_phone", { length: PHONE_LENGTH }),
32025
+ sms_provider_reference: text("sms_provider_reference"),
31849
32026
  sms_verified: boolean("sms_verified").notNull().default(false),
31850
32027
  totp_failed_attempts: smallint("totp_failed_attempts").notNull().default(0),
31851
32028
  totp_secret_ciphertext: text("totp_secret_ciphertext"),
@@ -31857,10 +32034,13 @@ var toEnrollment = (row) => ({
31857
32034
  backupCodeHashes: row.backup_code_hashes,
31858
32035
  createdAt: row.created_at_ms,
31859
32036
  lastUsedAt: row.last_used_at_ms ?? undefined,
32037
+ smsCodeSentAt: row.sms_code_sent_at_ms ?? undefined,
31860
32038
  smsFailedAttempts: row.sms_failed_attempts,
31861
32039
  smsPendingCodeExpiresAt: row.sms_pending_code_expires_at_ms ?? undefined,
31862
32040
  smsPendingCodeHash: row.sms_pending_code_hash ?? undefined,
32041
+ smsPendingPurpose: row.sms_pending_purpose ?? undefined,
31863
32042
  smsPhone: row.sms_phone ?? undefined,
32043
+ smsProviderReference: row.sms_provider_reference ?? undefined,
31864
32044
  smsVerified: row.sms_verified,
31865
32045
  totpFailedAttempts: row.totp_failed_attempts,
31866
32046
  totpSecretCiphertext: row.totp_secret_ciphertext ?? undefined,
@@ -31886,10 +32066,13 @@ var createPostgresMfaStore = (db) => ({
31886
32066
  backup_code_hashes: enrollment.backupCodeHashes,
31887
32067
  created_at_ms: enrollment.createdAt,
31888
32068
  last_used_at_ms: enrollment.lastUsedAt ?? null,
32069
+ sms_code_sent_at_ms: enrollment.smsCodeSentAt ?? null,
31889
32070
  sms_failed_attempts: enrollment.smsFailedAttempts ?? 0,
31890
32071
  sms_pending_code_expires_at_ms: enrollment.smsPendingCodeExpiresAt ?? null,
31891
32072
  sms_pending_code_hash: enrollment.smsPendingCodeHash ?? null,
32073
+ sms_pending_purpose: enrollment.smsPendingPurpose ?? null,
31892
32074
  sms_phone: enrollment.smsPhone ?? null,
32075
+ sms_provider_reference: enrollment.smsProviderReference ?? null,
31893
32076
  sms_verified: enrollment.smsVerified,
31894
32077
  totp_failed_attempts: enrollment.totpFailedAttempts ?? 0,
31895
32078
  totp_secret_ciphertext: enrollment.totpSecretCiphertext ?? null,
@@ -33643,23 +33826,28 @@ var portableJsonb = customType({
33643
33826
  fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
33644
33827
  toDriver: (value) => JSON.stringify(value)
33645
33828
  });
33646
- var agentDelegationsTable = pgTable("auth_agent_delegations", {
33829
+ var bunSqlJsonb = customType({
33830
+ dataType: () => "jsonb",
33831
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
33832
+ toDriver: (value) => value
33833
+ });
33834
+ var createAgentDelegationsTable = (json5) => pgTable("auth_agent_delegations", {
33647
33835
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull(),
33648
- authorization_details: portableJsonb("authorization_details").$type(),
33836
+ authorization_details: json5("authorization_details").$type(),
33649
33837
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33650
33838
  delegation_id: varchar("delegation_id", {
33651
33839
  length: ID_LENGTH7
33652
33840
  }).primaryKey(),
33653
33841
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }),
33654
33842
  organization_id: varchar("organization_id", { length: ID_LENGTH7 }),
33655
- scopes: portableJsonb("scopes").$type().notNull().default([]),
33843
+ scopes: json5("scopes").$type().notNull().default([]),
33656
33844
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33657
33845
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
33658
33846
  user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
33659
33847
  });
33660
- var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations", {
33848
+ var createAgentIdentityRegistrationsTable = (json5) => pgTable("auth_agent_identity_registrations", {
33661
33849
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull().unique(),
33662
- claim_attempt: portableJsonb("claim_attempt").$type(),
33850
+ claim_attempt: json5("claim_attempt").$type(),
33663
33851
  claim_attempt_token_hash: varchar("claim_attempt_token_hash", {
33664
33852
  length: ID_LENGTH7
33665
33853
  }).unique(),
@@ -33669,8 +33857,12 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
33669
33857
  claim_token_hash: varchar("claim_token_hash", {
33670
33858
  length: ID_LENGTH7
33671
33859
  }).notNull().unique(),
33672
- created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33673
- expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
33860
+ created_at_ms: bigint("created_at_ms", {
33861
+ mode: "number"
33862
+ }).notNull(),
33863
+ expires_at_ms: bigint("expires_at_ms", {
33864
+ mode: "number"
33865
+ }).notNull(),
33674
33866
  kind: varchar("kind", { length: 32 }).$type().notNull(),
33675
33867
  last_polled_at_ms: bigint("last_polled_at_ms", { mode: "number" }),
33676
33868
  login_hint: varchar("login_hint", { length: ID_LENGTH7 }),
@@ -33678,27 +33870,37 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
33678
33870
  length: ID_LENGTH7
33679
33871
  }).primaryKey(),
33680
33872
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33681
- updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
33873
+ updated_at_ms: bigint("updated_at_ms", {
33874
+ mode: "number"
33875
+ }).notNull(),
33682
33876
  upstream_client_id: varchar("upstream_client_id", {
33683
33877
  length: ID_LENGTH7
33684
33878
  }),
33685
33879
  upstream_issuer: varchar("upstream_issuer", { length: ID_LENGTH7 }),
33686
- upstream_subject: varchar("upstream_subject", { length: ID_LENGTH7 }),
33880
+ upstream_subject: varchar("upstream_subject", {
33881
+ length: ID_LENGTH7
33882
+ }),
33687
33883
  user_id: varchar("user_id", { length: ID_LENGTH7 }),
33688
33884
  version: integer("version").notNull()
33689
33885
  }, (table) => [
33690
33886
  uniqueIndex("auth_agent_identity_upstream_unique").on(table.upstream_issuer, table.upstream_subject, table.upstream_client_id)
33691
33887
  ]);
33692
- var agentRegistrationsTable = pgTable("auth_agent_registrations", {
33888
+ var createAgentRegistrationsTable = (json5) => pgTable("auth_agent_registrations", {
33693
33889
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).primaryKey(),
33694
- allowed_scopes: portableJsonb("allowed_scopes").$type().notNull().default([]),
33890
+ allowed_scopes: json5("allowed_scopes").$type().notNull().default([]),
33695
33891
  client_id: varchar("client_id", { length: ID_LENGTH7 }).unique(),
33696
33892
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33697
- metadata: portableJsonb("metadata").$type(),
33893
+ metadata: json5("metadata").$type(),
33698
33894
  name: varchar("name", { length: NAME_LENGTH }).notNull(),
33699
33895
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33700
33896
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull()
33701
33897
  });
33898
+ var agentDelegationsBunSqlTable = createAgentDelegationsTable(bunSqlJsonb);
33899
+ var agentDelegationsTable = createAgentDelegationsTable(portableJsonb);
33900
+ var agentIdentityRegistrationsBunSqlTable = createAgentIdentityRegistrationsTable(bunSqlJsonb);
33901
+ var agentIdentityRegistrationsTable = createAgentIdentityRegistrationsTable(portableJsonb);
33902
+ var agentRegistrationsBunSqlTable = createAgentRegistrationsTable(bunSqlJsonb);
33903
+ var agentRegistrationsTable = createAgentRegistrationsTable(portableJsonb);
33702
33904
  var toRegistration = (row) => ({
33703
33905
  agentId: row.agent_id,
33704
33906
  allowedScopes: row.allowed_scopes,
@@ -33765,24 +33967,24 @@ var identityRegistrationValues = (registration) => ({
33765
33967
  var createNeonAgentDelegationStore = (databaseUrl) => createDrizzleAgentDelegationStore(createNeonDatabase(databaseUrl));
33766
33968
  var createNeonAgentIdentityRegistrationStore = (databaseUrl) => createPostgresAgentIdentityRegistrationStore(createNeonDatabase(databaseUrl));
33767
33969
  var createNeonAgentRegistrationStore = (databaseUrl) => createPostgresAgentRegistrationStore(createNeonDatabase(databaseUrl));
33768
- var createDrizzleAgentDelegationStore = (db) => ({
33970
+ var createDrizzleAgentDelegationStoreFor = (db, table) => ({
33769
33971
  findActiveDelegation: async ({
33770
33972
  agentId,
33771
33973
  now = Date.now(),
33772
33974
  organizationId,
33773
33975
  userId
33774
33976
  }) => {
33775
- const organizationCondition = organizationId === undefined ? isNull(agentDelegationsTable.organization_id) : eq(agentDelegationsTable.organization_id, organizationId);
33776
- const [row] = await db.select().from(agentDelegationsTable).where(and(eq(agentDelegationsTable.agent_id, agentId), eq(agentDelegationsTable.user_id, userId), organizationCondition, eq(agentDelegationsTable.status, "active"), or(isNull(agentDelegationsTable.expires_at_ms), gt(agentDelegationsTable.expires_at_ms, now)))).orderBy(desc(agentDelegationsTable.updated_at_ms)).limit(1);
33977
+ const organizationCondition = organizationId === undefined ? isNull(table.organization_id) : eq(table.organization_id, organizationId);
33978
+ const [row] = await db.select().from(table).where(and(eq(table.agent_id, agentId), eq(table.user_id, userId), organizationCondition, eq(table.status, "active"), or(isNull(table.expires_at_ms), gt(table.expires_at_ms, now)))).orderBy(desc(table.updated_at_ms)).limit(1);
33777
33979
  return row === undefined ? undefined : toDelegation(row);
33778
33980
  },
33779
33981
  findByDelegationId: async (delegationId) => {
33780
- const [row] = await db.select().from(agentDelegationsTable).where(eq(agentDelegationsTable.delegation_id, delegationId)).limit(1);
33982
+ const [row] = await db.select().from(table).where(eq(table.delegation_id, delegationId)).limit(1);
33781
33983
  return row === undefined ? undefined : toDelegation(row);
33782
33984
  },
33783
33985
  listDelegations: async (agentId) => {
33784
- const base = db.select().from(agentDelegationsTable);
33785
- const rows = await (agentId === undefined ? base.orderBy(desc(agentDelegationsTable.created_at_ms)) : base.where(eq(agentDelegationsTable.agent_id, agentId)).orderBy(desc(agentDelegationsTable.created_at_ms)));
33986
+ const base = db.select().from(table);
33987
+ const rows = await (agentId === undefined ? base.orderBy(desc(table.created_at_ms)) : base.where(eq(table.agent_id, agentId)).orderBy(desc(table.created_at_ms)));
33786
33988
  return rows.map(toDelegation);
33787
33989
  },
33788
33990
  saveDelegation: async (delegation) => {
@@ -33798,36 +34000,38 @@ var createDrizzleAgentDelegationStore = (db) => ({
33798
34000
  updated_at_ms: delegation.updatedAt,
33799
34001
  user_id: delegation.userId
33800
34002
  };
33801
- await db.insert(agentDelegationsTable).values(values).onConflictDoUpdate({
34003
+ await db.insert(table).values(values).onConflictDoUpdate({
33802
34004
  set: values,
33803
- target: agentDelegationsTable.delegation_id
34005
+ target: table.delegation_id
33804
34006
  });
33805
34007
  }
33806
34008
  });
34009
+ var createDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsTable);
34010
+ var createBunSqlDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsBunSqlTable);
33807
34011
  var createPostgresAgentDelegationStore = createDrizzleAgentDelegationStore;
33808
- var createPostgresAgentIdentityRegistrationStore = (db) => ({
34012
+ var createPostgresAgentIdentityRegistrationStoreFor = (db, table) => ({
33809
34013
  create: async (registration) => {
33810
- const rows = await db.insert(agentIdentityRegistrationsTable).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: agentIdentityRegistrationsTable.registration_id });
34014
+ const rows = await db.insert(table).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: table.registration_id });
33811
34015
  return rows.length === 1;
33812
34016
  },
33813
34017
  findByAgentId: async (agentId) => {
33814
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.agent_id, agentId)).limit(1);
34018
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
33815
34019
  return row === undefined ? undefined : toIdentityRegistration(row);
33816
34020
  },
33817
34021
  findByAttemptTokenHash: async (attemptTokenHash) => {
33818
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_attempt_token_hash, attemptTokenHash)).limit(1);
34022
+ const [row] = await db.select().from(table).where(eq(table.claim_attempt_token_hash, attemptTokenHash)).limit(1);
33819
34023
  return row === undefined ? undefined : toIdentityRegistration(row);
33820
34024
  },
33821
34025
  findByClaimTokenHash: async (claimTokenHash) => {
33822
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_token_hash, claimTokenHash)).limit(1);
34026
+ const [row] = await db.select().from(table).where(eq(table.claim_token_hash, claimTokenHash)).limit(1);
33823
34027
  return row === undefined ? undefined : toIdentityRegistration(row);
33824
34028
  },
33825
34029
  findByRegistrationId: async (registrationId) => {
33826
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.registration_id, registrationId)).limit(1);
34030
+ const [row] = await db.select().from(table).where(eq(table.registration_id, registrationId)).limit(1);
33827
34031
  return row === undefined ? undefined : toIdentityRegistration(row);
33828
34032
  },
33829
34033
  findByUpstreamIdentity: async ({ clientId, issuer, subject }) => {
33830
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(and(eq(agentIdentityRegistrationsTable.upstream_client_id, clientId), eq(agentIdentityRegistrationsTable.upstream_issuer, issuer), eq(agentIdentityRegistrationsTable.upstream_subject, subject))).limit(1);
34034
+ const [row] = await db.select().from(table).where(and(eq(table.upstream_client_id, clientId), eq(table.upstream_issuer, issuer), eq(table.upstream_subject, subject))).limit(1);
33831
34035
  return row === undefined ? undefined : toIdentityRegistration(row);
33832
34036
  },
33833
34037
  replace: async (registration, expectedVersion) => {
@@ -33836,21 +34040,23 @@ var createPostgresAgentIdentityRegistrationStore = (db) => ({
33836
34040
  version: expectedVersion + 1
33837
34041
  };
33838
34042
  const values = identityRegistrationValues(next);
33839
- const rows = await db.update(agentIdentityRegistrationsTable).set(values).where(and(eq(agentIdentityRegistrationsTable.registration_id, registration.registrationId), eq(agentIdentityRegistrationsTable.version, expectedVersion))).returning({ id: agentIdentityRegistrationsTable.registration_id });
34043
+ const rows = await db.update(table).set(values).where(and(eq(table.registration_id, registration.registrationId), eq(table.version, expectedVersion))).returning({ id: table.registration_id });
33840
34044
  return rows.length === 1;
33841
34045
  }
33842
34046
  });
33843
- var createPostgresAgentRegistrationStore = (db) => ({
34047
+ var createBunSqlDrizzleAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsBunSqlTable);
34048
+ var createPostgresAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsTable);
34049
+ var createPostgresAgentRegistrationStoreFor = (db, table) => ({
33844
34050
  findByAgentId: async (agentId) => {
33845
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.agent_id, agentId)).limit(1);
34051
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
33846
34052
  return row === undefined ? undefined : toRegistration(row);
33847
34053
  },
33848
34054
  findByClientId: async (clientId) => {
33849
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.client_id, clientId)).limit(1);
34055
+ const [row] = await db.select().from(table).where(eq(table.client_id, clientId)).limit(1);
33850
34056
  return row === undefined ? undefined : toRegistration(row);
33851
34057
  },
33852
34058
  listRegistrations: async () => {
33853
- const rows = await db.select().from(agentRegistrationsTable).orderBy(desc(agentRegistrationsTable.created_at_ms));
34059
+ const rows = await db.select().from(table).orderBy(desc(table.created_at_ms));
33854
34060
  return rows.map(toRegistration);
33855
34061
  },
33856
34062
  saveRegistration: async (registration) => {
@@ -33864,12 +34070,14 @@ var createPostgresAgentRegistrationStore = (db) => ({
33864
34070
  status: registration.status,
33865
34071
  updated_at_ms: registration.updatedAt
33866
34072
  };
33867
- await db.insert(agentRegistrationsTable).values(values).onConflictDoUpdate({
34073
+ await db.insert(table).values(values).onConflictDoUpdate({
33868
34074
  set: values,
33869
- target: agentRegistrationsTable.agent_id
34075
+ target: table.agent_id
33870
34076
  });
33871
34077
  }
33872
34078
  });
34079
+ var createBunSqlDrizzleAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsBunSqlTable);
34080
+ var createPostgresAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsTable);
33873
34081
  // src/apikeys/inMemoryStores.ts
33874
34082
  var createInMemoryAccessTokenStore = () => {
33875
34083
  const tokens = new Map;
@@ -36213,6 +36421,15 @@ var mfaTotpLockoutMigration = {
36213
36421
  id: "0003_totp_lockout",
36214
36422
  sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "totp_failed_attempts" smallint NOT NULL DEFAULT 0;'
36215
36423
  };
36424
+ var mfaSmsDeliveryPolicyMigration = {
36425
+ id: "0004_sms_delivery_policy",
36426
+ sql: [
36427
+ 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_code_sent_at_ms" bigint;',
36428
+ 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_pending_purpose" text;',
36429
+ 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_provider_reference" text;'
36430
+ ].join(`
36431
+ `)
36432
+ };
36216
36433
  var oidcResourceAudienceMigration = {
36217
36434
  id: "0002_resource_audience",
36218
36435
  sql: [
@@ -36267,7 +36484,8 @@ var blockMigrations = {
36267
36484
  migrations: [
36268
36485
  ...initMigration("mfa", [mfaEnrollmentsTable]).migrations,
36269
36486
  mfaSmsColumnsMigration,
36270
- mfaTotpLockoutMigration
36487
+ mfaTotpLockoutMigration,
36488
+ mfaSmsDeliveryPolicyMigration
36271
36489
  ]
36272
36490
  },
36273
36491
  oidc: {
@@ -36780,6 +36998,7 @@ var buildAuthApplications = async (configuration) => {
36780
36998
  credentials,
36781
36999
  customProviders,
36782
37000
  mfa,
37001
+ verificationProvider,
36783
37002
  passwordless,
36784
37003
  lockout,
36785
37004
  sessions,
@@ -37012,7 +37231,8 @@ var buildAuthApplications = async (configuration) => {
37012
37231
  auditedMfa ? mfaRoutes({
37013
37232
  ...auditedMfa,
37014
37233
  authSessionStore,
37015
- cookieSecure: resolvedCookieSecure
37234
+ cookieSecure: resolvedCookieSecure,
37235
+ verificationProvider
37016
37236
  }) : new Elysia45,
37017
37237
  passwordless ? passwordlessRoutes({
37018
37238
  ...passwordless,
@@ -37477,6 +37697,9 @@ export {
37477
37697
  createCustomOAuth2Client,
37478
37698
  createCredentialOffer,
37479
37699
  createClientIdMetadataResolver,
37700
+ createBunSqlDrizzleAgentRegistrationStore,
37701
+ createBunSqlDrizzleAgentIdentityRegistrationStore,
37702
+ createBunSqlDrizzleAgentDelegationStore,
37480
37703
  createAuthHtmxRoutes,
37481
37704
  createAuthContext,
37482
37705
  createAuthApplications,
@@ -37519,20 +37742,24 @@ export {
37519
37742
  apiKeysRoutes,
37520
37743
  apiClientsTable,
37521
37744
  agentRegistrationsTable,
37745
+ agentRegistrationsBunSqlTable,
37522
37746
  agentRegistrationEndpoints,
37523
37747
  agentRegistrationDiscoveryMetadata,
37524
37748
  agentProtectedResourceMetadata,
37525
37749
  agentOAuthGuideUrl,
37526
37750
  agentOAuthGuideRoute,
37527
37751
  agentIdentityRegistrationsTable,
37752
+ agentIdentityRegistrationsBunSqlTable,
37528
37753
  agentHasScopes,
37529
37754
  agentDelegationsTable,
37755
+ agentDelegationsBunSqlTable,
37530
37756
  agentAuthPlugin,
37531
37757
  agentAuthChallenge,
37532
37758
  addToSessionRing,
37533
37759
  accessTokensTable,
37534
37760
  acceptInvitation,
37535
37761
  WEBAUTHN_CHALLENGE_COOKIE,
37762
+ VerificationProviderError,
37536
37763
  STATUS_LIST_TYP,
37537
37764
  STATUS_LIST_SUB_TYP,
37538
37765
  REQUEST_URI_PREFIX,
@@ -37550,6 +37777,7 @@ export {
37550
37777
  DEFAULT_STATUS_ROUTE,
37551
37778
  DEFAULT_SSO_SESSION_TTL_MS,
37552
37779
  DEFAULT_SSO_ROUTE,
37780
+ DEFAULT_SMS_RESEND_COOLDOWN_MS,
37553
37781
  DEFAULT_SMS_MAX_ATTEMPTS,
37554
37782
  DEFAULT_SMS_CODE_TTL_MS,
37555
37783
  DEFAULT_SMS_CODE_LENGTH,
@@ -37582,5 +37810,5 @@ export {
37582
37810
  AGENT_CLAIM_GRANT_TYPE
37583
37811
  };
37584
37812
 
37585
- //# debugId=72A82A16089AB9F664756E2164756E21
37813
+ //# debugId=588FAC011547AB7964756E2164756E21
37586
37814
  //# sourceMappingURL=index.js.map