@absolutejs/auth 0.58.0 → 0.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -91,9 +91,12 @@ import { createSimpleWebAuthnAdapter } from '@absolutejs/auth/webauthn';
91
91
 
92
92
  ### Provider-managed phone verification
93
93
 
94
- `verificationProvider` is the vendor-neutral challenge lifecycle used by SMS
95
- MFA. Auth owns enrollment, resend cooldowns, failed-attempt policy, audit, and
96
- session promotion; the provider generates, delivers, and checks the code.
94
+ `verificationProvider` is the vendor-neutral phone-verification lifecycle.
95
+ The contract supports SMS, WhatsApp, and voice-call OTP; MFA currently selects
96
+ SMS while signup, recovery, phone change, and step-up flows can use the same
97
+ provider contract. Auth owns enrollment, atomic resend/code-consumption policy,
98
+ audit, and session promotion; the provider generates, delivers, checks, and
99
+ cancels the code.
97
100
 
98
101
  ```ts
99
102
  import { auth } from '@absolutejs/auth/server';
@@ -118,9 +121,11 @@ application-owned delivery system such as `@absolutejs/dispatch`. Its payload
118
121
  includes `purpose` and `userId` for safe templates, audit correlation, and
119
122
  tenant routing. Provider and local-code sends share the default 30-second
120
123
  per-enrollment resend cooldown; configure `mfa.smsResendCooldownMs` when needed.
124
+ MFA enrollment, replacement, and removal require a fresh authentication by
125
+ default (five minutes); configure `mfa.managementAuthMaxAgeMs` deliberately.
121
126
 
122
127
  Production databases must run the `mfa` migration block after upgrading to add
123
- the durable cooldown timestamp.
128
+ the atomic SMS challenge identifier.
124
129
 
125
130
  ### Delegated AI agents
126
131
 
@@ -2672,7 +2672,7 @@ var lockoutsTable = pgTable8("auth_lockouts", {
2672
2672
  });
2673
2673
 
2674
2674
  // src/mfa/postgresMfaStore.ts
2675
- import { eq as eq9 } from "drizzle-orm";
2675
+ import { and as and4, eq as eq9, isNull as isNull2, lte, or as or2, sql } from "drizzle-orm";
2676
2676
  import {
2677
2677
  bigint as bigint7,
2678
2678
  boolean as boolean3,
@@ -2688,6 +2688,7 @@ var mfaEnrollmentsTable = pgTable9("auth_mfa_enrollments", {
2688
2688
  backup_code_hashes: jsonb3("backup_code_hashes").$type().notNull().default([]),
2689
2689
  created_at_ms: bigint7("created_at_ms", { mode: "number" }).notNull(),
2690
2690
  last_used_at_ms: bigint7("last_used_at_ms", { mode: "number" }),
2691
+ sms_challenge_id: text4("sms_challenge_id"),
2691
2692
  sms_code_sent_at_ms: bigint7("sms_code_sent_at_ms", { mode: "number" }),
2692
2693
  sms_failed_attempts: smallint("sms_failed_attempts").notNull().default(0),
2693
2694
  sms_pending_code_expires_at_ms: bigint7("sms_pending_code_expires_at_ms", {
@@ -2706,7 +2707,7 @@ var mfaEnrollmentsTable = pgTable9("auth_mfa_enrollments", {
2706
2707
  });
2707
2708
 
2708
2709
  // src/oidc/postgresStores.ts
2709
- import { and as and4, desc as desc6, eq as eq10, gt as gt2, lt as lt3 } from "drizzle-orm";
2710
+ import { and as and5, desc as desc6, eq as eq10, gt as gt2, lt as lt3 } from "drizzle-orm";
2710
2711
  import {
2711
2712
  bigint as bigint8,
2712
2713
  boolean as boolean4,
@@ -2836,7 +2837,7 @@ var oauthRefreshTokensTable = pgTable10("auth_oauth_refresh_tokens", {
2836
2837
  });
2837
2838
 
2838
2839
  // src/organizations/postgresOrganizationStore.ts
2839
- import { and as and5, desc as desc7, eq as eq11 } from "drizzle-orm";
2840
+ import { and as and6, desc as desc7, eq as eq11 } from "drizzle-orm";
2840
2841
  import {
2841
2842
  bigint as bigint9,
2842
2843
  jsonb as jsonb5,
@@ -2912,7 +2913,7 @@ var setupSessionsTable = pgTable13("auth_setup_sessions", {
2912
2913
  });
2913
2914
 
2914
2915
  // src/roles/postgresRoleStore.ts
2915
- import { and as and6, eq as eq14 } from "drizzle-orm";
2916
+ import { and as and7, eq as eq14 } from "drizzle-orm";
2916
2917
  import {
2917
2918
  bigint as bigint12,
2918
2919
  jsonb as jsonb7,
@@ -2998,7 +2999,7 @@ var samlServiceProvidersTable = pgTable17("auth_saml_service_providers", {
2998
2999
  });
2999
3000
 
3000
3001
  // src/sso/postgresSsoConnectionStore.ts
3001
- import { and as and7, desc as desc9, eq as eq18 } from "drizzle-orm";
3002
+ import { and as and8, desc as desc9, eq as eq18 } from "drizzle-orm";
3002
3003
  import { bigint as bigint16, boolean as boolean5, jsonb as jsonb9, pgTable as pgTable18, varchar as varchar18 } from "drizzle-orm/pg-core";
3003
3004
  var ID_LENGTH15 = 255;
3004
3005
  var TYPE_LENGTH2 = 16;
@@ -3048,7 +3049,7 @@ var vcPresentationRequestsTable = pgTable19("auth_vc_presentation_requests", {
3048
3049
  });
3049
3050
 
3050
3051
  // src/vault/postgresVaultStore.ts
3051
- import { and as and8, eq as eq20 } from "drizzle-orm";
3052
+ import { and as and9, eq as eq20 } from "drizzle-orm";
3052
3053
  import {
3053
3054
  bigint as bigint18,
3054
3055
  pgTable as pgTable20,
@@ -3173,18 +3174,18 @@ var JOURNAL_DDL = `CREATE TABLE IF NOT EXISTS "auth_migrations" (
3173
3174
  var isJournalRow = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "id") === "string";
3174
3175
  var isBlockName = (value) => Object.hasOwn(blockMigrations, value);
3175
3176
  var allBlockNames = () => Object.keys(blockMigrations).filter(isBlockName);
3176
- var applyOne = async (client, id, sql, log) => {
3177
- await client.query(sql);
3177
+ var applyOne = async (client, id, sql2, log) => {
3178
+ await client.query(sql2);
3178
3179
  await client.query(`INSERT INTO "auth_migrations" ("id", "applied_at_ms") VALUES ($1, $2)`, [id, Date.now()]);
3179
3180
  log(`apply ${id}`);
3180
3181
  };
3181
- var runOne = async (client, id, sql, applied, result, log) => {
3182
+ var runOne = async (client, id, sql2, applied, result, log) => {
3182
3183
  if (applied.has(id)) {
3183
3184
  result.skipped.push(id);
3184
3185
  log(`skip ${id}`);
3185
3186
  return;
3186
3187
  }
3187
- await applyOne(client, id, sql, log);
3188
+ await applyOne(client, id, sql2, log);
3188
3189
  result.applied.push(id);
3189
3190
  };
3190
3191
  var runMigrations = async ({
@@ -3252,6 +3253,10 @@ var mfaSmsDeliveryPolicyMigration = {
3252
3253
  ].join(`
3253
3254
  `)
3254
3255
  };
3256
+ var mfaSmsAtomicChallengeMigration = {
3257
+ id: "0005_sms_atomic_challenge",
3258
+ sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "sms_challenge_id" text;'
3259
+ };
3255
3260
  var oidcResourceAudienceMigration = {
3256
3261
  id: "0002_resource_audience",
3257
3262
  sql: [
@@ -3307,7 +3312,8 @@ var blockMigrations = {
3307
3312
  ...initMigration("mfa", [mfaEnrollmentsTable]).migrations,
3308
3313
  mfaSmsColumnsMigration,
3309
3314
  mfaTotpLockoutMigration,
3310
- mfaSmsDeliveryPolicyMigration
3315
+ mfaSmsDeliveryPolicyMigration,
3316
+ mfaSmsAtomicChallengeMigration
3311
3317
  ]
3312
3318
  },
3313
3319
  oidc: {
@@ -3544,5 +3550,5 @@ var main = async () => {
3544
3550
  };
3545
3551
  await main();
3546
3552
 
3547
- //# debugId=19A5010083F8B61F64756E2164756E21
3553
+ //# debugId=F3F4FD6B1C5A081764756E2164756E21
3548
3554
  //# sourceMappingURL=migrate.js.map