@payez/next-mvp 4.1.10 → 4.1.20

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 (181) hide show
  1. package/dist/api-handlers/account/profile.d.ts +38 -0
  2. package/dist/api-handlers/account/profile.js +73 -45
  3. package/dist/api-handlers/account/recovery/send-code.d.ts +33 -0
  4. package/dist/api-handlers/account/recovery/send-code.js +52 -18
  5. package/dist/api-handlers/account/recovery/verify-code.d.ts +33 -0
  6. package/dist/api-handlers/account/recovery/verify-code.js +52 -18
  7. package/dist/api-handlers/account/verify-email.js +15 -1
  8. package/dist/api-handlers/account/verify-sms.js +15 -1
  9. package/dist/api-handlers/auth/passkey-signin.d.ts +29 -0
  10. package/dist/api-handlers/auth/passkey-signin.js +97 -0
  11. package/dist/api-handlers/mfa/backup-code-verify.d.ts +73 -0
  12. package/dist/api-handlers/mfa/backup-code-verify.js +153 -0
  13. package/dist/api-handlers/mfa/backup-codes.d.ts +7 -0
  14. package/dist/api-handlers/mfa/backup-codes.js +40 -0
  15. package/dist/api-handlers/mfa/methods.d.ts +3 -0
  16. package/dist/api-handlers/mfa/methods.js +41 -0
  17. package/dist/api-handlers/mfa/totp-confirm.d.ts +8 -0
  18. package/dist/api-handlers/mfa/totp-confirm.js +41 -0
  19. package/dist/api-handlers/mfa/totp-enroll.d.ts +8 -0
  20. package/dist/api-handlers/mfa/totp-enroll.js +41 -0
  21. package/dist/api-handlers/mfa/totp-verify.d.ts +47 -0
  22. package/dist/api-handlers/mfa/totp-verify.js +134 -0
  23. package/dist/api-handlers/passkeys/list.d.ts +7 -0
  24. package/dist/api-handlers/passkeys/list.js +29 -0
  25. package/dist/api-handlers/passkeys/manage.d.ts +3 -0
  26. package/dist/api-handlers/passkeys/manage.js +54 -0
  27. package/dist/api-handlers/passkeys/register-options.d.ts +8 -0
  28. package/dist/api-handlers/passkeys/register-options.js +41 -0
  29. package/dist/api-handlers/passkeys/register-verify.d.ts +7 -0
  30. package/dist/api-handlers/passkeys/register-verify.js +40 -0
  31. package/dist/api-handlers/session/viability.js +19 -0
  32. package/dist/auth/better-auth.d.ts +68 -5
  33. package/dist/auth/better-auth.js +271 -45
  34. package/dist/auth/utils/idp-client.d.ts +13 -22
  35. package/dist/auth/utils/idp-client.js +12 -82
  36. package/dist/client/better-auth-client.d.ts +14 -2
  37. package/dist/lib/ensure-fresh-access-token.js +13 -2
  38. package/dist/lib/session-store.js +28 -21
  39. package/dist/lib/startup-init.js +19 -19
  40. package/dist/lib/token-lifecycle.d.ts +2 -0
  41. package/dist/lib/token-lifecycle.js +61 -7
  42. package/dist/models/SessionModel.d.ts +17 -0
  43. package/dist/pages/login/page.d.ts +10 -1
  44. package/dist/pages/login/page.js +69 -80
  45. package/dist/pages/verify-code/page.d.ts +10 -1
  46. package/dist/pages/verify-code/page.js +72 -4
  47. package/dist/routes/auth/passkey-signin.d.ts +13 -0
  48. package/dist/routes/auth/passkey-signin.js +18 -0
  49. package/dist/routes/auth/viability.d.ts +2 -0
  50. package/dist/routes/auth/viability.js +88 -0
  51. package/dist/routes/mfa/backup-code-verify.d.ts +1 -0
  52. package/dist/routes/mfa/backup-code-verify.js +5 -0
  53. package/dist/routes/mfa/backup-codes.d.ts +10 -0
  54. package/dist/routes/mfa/backup-codes.js +14 -0
  55. package/dist/routes/mfa/methods.d.ts +21 -0
  56. package/dist/routes/mfa/methods.js +10 -0
  57. package/dist/routes/mfa/totp-confirm.d.ts +10 -0
  58. package/dist/routes/mfa/totp-confirm.js +14 -0
  59. package/dist/routes/mfa/totp-enroll.d.ts +10 -0
  60. package/dist/routes/mfa/totp-enroll.js +14 -0
  61. package/dist/routes/mfa/totp-verify.d.ts +14 -0
  62. package/dist/routes/mfa/totp-verify.js +18 -0
  63. package/dist/routes/passkeys/list.d.ts +10 -0
  64. package/dist/routes/passkeys/list.js +14 -0
  65. package/dist/routes/passkeys/manage.d.ts +18 -0
  66. package/dist/routes/passkeys/manage.js +13 -0
  67. package/dist/routes/passkeys/register-options.d.ts +10 -0
  68. package/dist/routes/passkeys/register-options.js +14 -0
  69. package/dist/routes/passkeys/register-verify.d.ts +10 -0
  70. package/dist/routes/passkeys/register-verify.js +14 -0
  71. package/dist/server/auth.d.ts +2 -2
  72. package/dist/server/decode-session.js +37 -3
  73. package/package.json +958 -893
  74. package/scripts/check-internal-url-usage.sh +73 -73
  75. package/src/api/index.ts +17 -17
  76. package/src/api-handlers/account/masked-info.ts +45 -45
  77. package/src/api-handlers/account/profile.ts +99 -80
  78. package/src/api-handlers/account/recovery/initiate.ts +23 -23
  79. package/src/api-handlers/account/recovery/send-code.ts +73 -25
  80. package/src/api-handlers/account/recovery/verify-code.ts +73 -25
  81. package/src/api-handlers/account/reset-password.ts +23 -23
  82. package/src/api-handlers/account/send-code.ts +76 -76
  83. package/src/api-handlers/account/validate-password.ts +118 -118
  84. package/src/api-handlers/account/verify-email.ts +15 -1
  85. package/src/api-handlers/account/verify-sms.ts +15 -1
  86. package/src/api-handlers/admin/stats.ts +249 -249
  87. package/src/api-handlers/anon/preferences.ts +123 -123
  88. package/src/api-handlers/auth/jwks.ts +20 -20
  89. package/src/api-handlers/auth/login.ts +240 -240
  90. package/src/api-handlers/auth/passkey-signin.ts +98 -0
  91. package/src/api-handlers/auth/validate.ts +43 -43
  92. package/src/api-handlers/mfa/backup-code-verify.ts +175 -0
  93. package/src/api-handlers/mfa/backup-codes.ts +41 -0
  94. package/src/api-handlers/mfa/methods.ts +46 -0
  95. package/src/api-handlers/mfa/totp-confirm.ts +42 -0
  96. package/src/api-handlers/mfa/totp-enroll.ts +42 -0
  97. package/src/api-handlers/mfa/totp-verify.ts +156 -0
  98. package/src/api-handlers/passkeys/list.ts +31 -0
  99. package/src/api-handlers/passkeys/manage.ts +54 -0
  100. package/src/api-handlers/passkeys/register-options.ts +42 -0
  101. package/src/api-handlers/passkeys/register-verify.ts +41 -0
  102. package/src/api-handlers/session/viability.ts +161 -142
  103. package/src/auth/better-auth.ts +708 -455
  104. package/src/auth/unauthenticated-routes.ts +2 -2
  105. package/src/auth/utils/idp-client.ts +13 -95
  106. package/src/client/better-auth-client.ts +70 -70
  107. package/src/client/fetchWithSession.ts +21 -21
  108. package/src/client/index.ts +13 -13
  109. package/src/client/useAnonSession.ts +131 -131
  110. package/src/components/admin/VibeAdminContext.tsx +87 -87
  111. package/src/config/logging-config.ts +82 -82
  112. package/src/config/unauthenticated-routes.ts +19 -19
  113. package/src/edge/internal-api-url.ts +65 -65
  114. package/src/edge/middleware.ts +42 -42
  115. package/src/hooks/useProfile.ts +75 -75
  116. package/src/lib/anon-session.ts +213 -213
  117. package/src/lib/auth-secret.ts +137 -137
  118. package/src/lib/demo-mode.ts +17 -17
  119. package/src/lib/ensure-fresh-access-token.ts +13 -2
  120. package/src/lib/idp-client-config.ts +559 -559
  121. package/src/lib/idp-fetch.ts +126 -126
  122. package/src/lib/internal-api.ts +171 -171
  123. package/src/lib/jwt-decode-client.ts +45 -45
  124. package/src/lib/rate-limit-service.ts +9 -9
  125. package/src/lib/redis.ts +26 -26
  126. package/src/lib/refresh-token-validator.ts +64 -64
  127. package/src/lib/secret-validation.ts +8 -8
  128. package/src/lib/session-store.ts +702 -695
  129. package/src/lib/session.ts +34 -34
  130. package/src/lib/startup-init.ts +251 -251
  131. package/src/lib/token-expiry.ts +40 -40
  132. package/src/lib/token-lifecycle.ts +533 -470
  133. package/src/lib/types/api-responses.ts +336 -336
  134. package/src/middleware/auth-decision.ts +43 -43
  135. package/src/models/DecodedAccessToken.ts +16 -16
  136. package/src/models/SessionModel.ts +282 -264
  137. package/src/pages/admin-roles/index.ts +9 -9
  138. package/src/pages/login/page.tsx +123 -228
  139. package/src/pages/security/EnhancedSecurityPage.tsx +9 -9
  140. package/src/pages/verify-code/page.tsx +71 -5
  141. package/src/routes/account/index.ts +31 -31
  142. package/src/routes/account/masked-info.ts +36 -36
  143. package/src/routes/account/send-code.ts +39 -39
  144. package/src/routes/account/verify-email.ts +40 -40
  145. package/src/routes/account/verify-sms.ts +40 -40
  146. package/src/routes/auth/index.ts +22 -22
  147. package/src/routes/auth/passkey-signin.ts +13 -0
  148. package/src/routes/auth/refresh.ts +48 -48
  149. package/src/routes/auth/session.ts +166 -166
  150. package/src/routes/auth/viability.ts +89 -0
  151. package/src/routes/index.ts +17 -17
  152. package/src/routes/mfa/backup-code-verify.ts +1 -0
  153. package/src/routes/mfa/backup-codes.ts +10 -0
  154. package/src/routes/mfa/methods.ts +22 -0
  155. package/src/routes/mfa/totp-confirm.ts +10 -0
  156. package/src/routes/mfa/totp-enroll.ts +10 -0
  157. package/src/routes/mfa/totp-verify.ts +14 -0
  158. package/src/routes/passkeys/list.ts +10 -0
  159. package/src/routes/passkeys/manage.ts +23 -0
  160. package/src/routes/passkeys/register-options.ts +10 -0
  161. package/src/routes/passkeys/register-verify.ts +10 -0
  162. package/src/routes/session/index.ts +7 -7
  163. package/src/routes/session/refresh-viability.ts +17 -17
  164. package/src/server/auth.ts +373 -373
  165. package/src/server/decode-session.ts +235 -202
  166. package/src/services/signalrActivityService.ts +258 -258
  167. package/src/theme/ThemeProvider.tsx +39 -39
  168. package/src/theme/default.ts +33 -33
  169. package/src/theme/index.ts +31 -31
  170. package/src/theme/types.ts +69 -69
  171. package/src/theme/useTheme.ts +57 -57
  172. package/src/theme/utils.ts +40 -40
  173. package/src/types/api.ts +12 -12
  174. package/src/types/auth.d.ts +23 -23
  175. package/src/types/auth.ts +22 -22
  176. package/src/types/logging.ts +11 -11
  177. package/src/types/recovery.ts +54 -54
  178. package/src/utils/api.ts +353 -353
  179. package/src/utils/circuitBreaker.ts +40 -40
  180. package/src/utils/error-message.ts +108 -108
  181. package/src/utils/layout/reservedSpace.ts +124 -124
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyPOST = exports.optionsPOST = void 0;
4
+ /**
5
+ * Ready-to-Use Passkey Sign-In Route (ANONYMOUS ceremony)
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/passkey/sign-in/options/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/auth/passkey-signin';
11
+ * // (optionsPOST is exported as POST; mount verify at its own path:)
12
+ * // app/api/passkey/sign-in/verify/route.ts
13
+ * export { verifyPOST as POST } from '@payez/next-mvp/routes/auth/passkey-signin';
14
+ * ```
15
+ */
16
+ var passkey_signin_1 = require("../../api-handlers/auth/passkey-signin");
17
+ Object.defineProperty(exports, "optionsPOST", { enumerable: true, get: function () { return passkey_signin_1.optionsPOST; } });
18
+ Object.defineProperty(exports, "verifyPOST", { enumerable: true, get: function () { return passkey_signin_1.verifyPOST; } });
@@ -37,6 +37,8 @@ export declare function GET(req: NextRequest): Promise<NextResponse<{
37
37
  tenantRequiresTwoFactor: boolean;
38
38
  userHasCompletedTenantTwoFactorRequirements: any;
39
39
  userStillNeedsTwoFactor: boolean;
40
+ tenantAllowed2FAMethods: string[] | null;
41
+ nextStep: "enroll_mfa" | "mfa_verify" | null | undefined;
40
42
  requires2FA: boolean;
41
43
  twoFactorComplete: any;
42
44
  accessTokenExpired: boolean;
@@ -33,6 +33,60 @@ async function getTenantRequiresTwoFactor() {
33
33
  return true;
34
34
  }
35
35
  }
36
+ /**
37
+ * Which 2FA methods the TENANT permits — cards 141688 + 141741.
38
+ *
39
+ * WHY THIS IS HERE: this endpoint answered "is 2FA required, and is it done?"
40
+ * and said nothing about WITH WHAT. Both the middleware gate and the
41
+ * verify-code page call this route, and NEITHER had any method data — so
42
+ * nothing in the system asked whether the user CAN complete the challenge it
43
+ * is about to demand. A user whose tenant allows only `totp`, with no
44
+ * authenticator enrolled, is sent to a page that offers email and sms.
45
+ *
46
+ * ⚠ THIS IS NOT A COMPLETION SIGNAL AND MUST NEVER BE READ AS ONE.
47
+ * It says what the tenant PERMITS. It says nothing about what the user has
48
+ * enrolled, and nothing about whether they have verified. The invariant
49
+ * (QAPert, acceptance J2/J5) is: METHOD-PRESENCE IS NOT VERIFIED. A user with
50
+ * one method is still challenged and still gated until they actually verify.
51
+ * `userHasCompletedTenantTwoFactorRequirements` remains the only field that
52
+ * answers "are they through".
53
+ *
54
+ * STILL MISSING, deliberately not guessed here: the ENROLLED set. That lives
55
+ * behind /api/mfa/methods and needs a call this route does not currently make.
56
+ * Allowed-only closes the "offered a method the tenant forbids" half; it does
57
+ * NOT close "has nothing enrolled and no way to enrol". Both halves are named
58
+ * in the cards so neither gets lost.
59
+ *
60
+ * NULL MEANS UNKNOWN — IT DOES NOT MEAN "NONE", AND IT DOES NOT MEAN
61
+ * "email and sms". If the client config cannot be read we do not know what the
62
+ * tenant permits, and every available guess is wrong in a way that matters:
63
+ *
64
+ * - guessing ['email','sms'] fails OPEN. On a totp-only tenant that offers
65
+ * the user two methods the tenant forbids — which is defect 141688 itself,
66
+ * re-created by its own fix during a config outage.
67
+ * - guessing [] fails CLOSED but locks the user out of a challenge they may
68
+ * be perfectly able to complete.
69
+ *
70
+ * So we report the truth (we don't know) and let the consumer decide, rather
71
+ * than encoding a guess that reads like a measurement. Same reasoning as the
72
+ * nullable require_2fa fix: "absent" has to be expressible, or callers cannot
73
+ * tell a real value from a default.
74
+ *
75
+ * No local default: `allowed2FAMethods` is non-optional on AuthSettings and is
76
+ * populated on BOTH config construction paths (idp-client-config.ts:333, :514)
77
+ * with the tenant's value or the layer's own ['email','sms']. Repeating that
78
+ * default here would be a second source for one setting, free to drift.
79
+ */
80
+ async function getTenantAllowed2FAMethods() {
81
+ try {
82
+ const config = await (0, idp_client_config_1.getIDPClientConfig)();
83
+ return config.authSettings.allowed2FAMethods;
84
+ }
85
+ catch {
86
+ console.warn('[VIABILITY] Could not get client config — reporting allowed 2FA methods as UNKNOWN (null), not guessing');
87
+ return null;
88
+ }
89
+ }
36
90
  /**
37
91
  * GET /api/session/viability - Check if session is viable
38
92
  *
@@ -79,12 +133,38 @@ async function GET(req) {
79
133
  reason: 'Stale session - cookie exists but session not found in Redis'
80
134
  });
81
135
  }
136
+ // Cards 141688/141741 — the IDP's routing decision, relayed verbatim.
137
+ // See the SessionData.nextStep doc. This is the field that tells the gate
138
+ // whether the user CAN complete a challenge; without it both consumers were
139
+ // sending zero-method users to a page they had no way to act on.
140
+ //
141
+ // Declared once, here, above every return: `session` is settled by this
142
+ // point, and all three authenticated responses must carry the SAME value.
143
+ // Deriving it per-branch would let the paths drift apart silently.
144
+ //
145
+ // NO `?? null` HERE, DELIBERATELY — and this is the whole safety argument:
146
+ //
147
+ // undefined = we never captured it. Every session minted BEFORE this
148
+ // change is in that state, and there are live ones in Redis
149
+ // right now. JSON.stringify omits the key, so the consumer
150
+ // sees no field and knows it is uninformed.
151
+ // null = the IDP affirmatively said "nothing outstanding".
152
+ //
153
+ // Collapsing the first into the second with `?? null` would tell the gate
154
+ // "fully authenticated, nothing to do" about every pre-existing session —
155
+ // including a zero-method user who must be sent to enrol. That is a
156
+ // fail-open on the entire existing session population, produced by a
157
+ // default that reads like a measurement. Same mistake as the nullable
158
+ // require_2fa case: absent has to stay expressible.
159
+ const nextStep = session?.nextStep;
82
160
  // Check access token expiry
83
161
  const now = Math.floor(Date.now() / 1000);
84
162
  const accessTokenExpires = token.accessTokenExpires || token.exp;
85
163
  if (!accessTokenExpires) {
86
164
  // No expiry info, assume viable but recommend refresh
87
165
  const tenantRequiresTwoFactor = await getTenantRequiresTwoFactor();
166
+ // Cards 141688/141741 — see getTenantAllowed2FAMethods. NOT a completion signal.
167
+ const tenantAllowed2FAMethods = await getTenantAllowed2FAMethods();
88
168
  // CRITICAL: Check if MFA has expired (2FA TTL enforcement)
89
169
  const mfaExpiresAt = session?.mfaExpiresAt || 0;
90
170
  const mfaExpired = mfaExpiresAt > 0 && mfaExpiresAt < Date.now();
@@ -103,6 +183,8 @@ async function GET(req) {
103
183
  tenantRequiresTwoFactor,
104
184
  userHasCompletedTenantTwoFactorRequirements,
105
185
  userStillNeedsTwoFactor,
186
+ tenantAllowed2FAMethods,
187
+ nextStep,
106
188
  // Legacy field names for backwards compatibility
107
189
  requires2FA: tenantRequiresTwoFactor,
108
190
  twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
@@ -121,6 +203,8 @@ async function GET(req) {
121
203
  const hasRefreshToken = !!(session?.idpRefreshToken || session?.refreshToken || token.refreshToken);
122
204
  // CLEAR NAMING: Tenant-wide 2FA requirement from client config
123
205
  const tenantRequiresTwoFactor = await getTenantRequiresTwoFactor();
206
+ // Cards 141688/141741 — see getTenantAllowed2FAMethods. NOT a completion signal.
207
+ const tenantAllowed2FAMethods = await getTenantAllowed2FAMethods();
124
208
  // CRITICAL: Check if MFA has expired (2FA TTL enforcement)
125
209
  // The session may have mfaVerified=true from days ago, but if mfaExpiresAt
126
210
  // has passed, we must treat 2FA as incomplete to force re-verification.
@@ -159,6 +243,8 @@ async function GET(req) {
159
243
  tenantRequiresTwoFactor,
160
244
  userHasCompletedTenantTwoFactorRequirements,
161
245
  userStillNeedsTwoFactor,
246
+ tenantAllowed2FAMethods,
247
+ nextStep,
162
248
  // Legacy names for backwards compatibility
163
249
  requires2FA: tenantRequiresTwoFactor,
164
250
  twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
@@ -180,6 +266,8 @@ async function GET(req) {
180
266
  tenantRequiresTwoFactor,
181
267
  userHasCompletedTenantTwoFactorRequirements,
182
268
  userStillNeedsTwoFactor,
269
+ tenantAllowed2FAMethods,
270
+ nextStep,
183
271
  // Legacy names for backwards compatibility
184
272
  requires2FA: tenantRequiresTwoFactor,
185
273
  twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
@@ -0,0 +1 @@
1
+ export { POST } from '../../api-handlers/mfa/backup-code-verify';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ var backup_code_verify_1 = require("../../api-handlers/mfa/backup-code-verify");
5
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return backup_code_verify_1.POST; } });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use MFA Backup Codes Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/mfa/backup-codes/route.ts
7
+ * export { POST } from '@payez/next-mvp/routes/mfa/backup-codes';
8
+ * ```
9
+ */
10
+ export { POST } from '../../api-handlers/mfa/backup-codes';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use MFA Backup Codes Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/mfa/backup-codes/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/mfa/backup-codes';
11
+ * ```
12
+ */
13
+ var backup_codes_1 = require("../../api-handlers/mfa/backup-codes");
14
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return backup_codes_1.POST; } });
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Ready-to-Use MFA Methods Route (list / remove)
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/mfa/methods/route.ts
7
+ * export { GET } from '@payez/next-mvp/routes/mfa/methods';
8
+ * // app/api/mfa/methods/[id]/route.ts
9
+ * export { DELETE } from '@payez/next-mvp/routes/mfa/methods';
10
+ * ```
11
+ */
12
+ import { NextRequest } from 'next/server';
13
+ import { GET as listMethods } from '../../api-handlers/mfa/methods';
14
+ export declare const GET: typeof listMethods;
15
+ type Ctx = {
16
+ params: Promise<{
17
+ id: string;
18
+ }>;
19
+ };
20
+ export declare function DELETE(req: NextRequest, ctx: Ctx): Promise<import("next/server").NextResponse<any>>;
21
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ exports.DELETE = DELETE;
5
+ const methods_1 = require("../../api-handlers/mfa/methods");
6
+ exports.GET = methods_1.GET;
7
+ async function DELETE(req, ctx) {
8
+ const { id } = await ctx.params;
9
+ return (0, methods_1.DELETE)(req, id);
10
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use TOTP Confirm Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/mfa/totp/confirm/route.ts
7
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-confirm';
8
+ * ```
9
+ */
10
+ export { POST } from '../../api-handlers/mfa/totp-confirm';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use TOTP Confirm Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/mfa/totp/confirm/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-confirm';
11
+ * ```
12
+ */
13
+ var totp_confirm_1 = require("../../api-handlers/mfa/totp-confirm");
14
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return totp_confirm_1.POST; } });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use TOTP Enrol Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/mfa/totp/enroll/route.ts
7
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-enroll';
8
+ * ```
9
+ */
10
+ export { POST } from '../../api-handlers/mfa/totp-enroll';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use TOTP Enrol Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/mfa/totp/enroll/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-enroll';
11
+ * ```
12
+ */
13
+ var totp_enroll_1 = require("../../api-handlers/mfa/totp-enroll");
14
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return totp_enroll_1.POST; } });
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Ready-to-Use TOTP Verify Route (2FA CHALLENGE, not enrolment)
3
+ *
4
+ * Verifies an authenticator code at LOGIN and transitions the session to
5
+ * MFA-verified. Pair with totp-enroll/totp-confirm, which only ENROL a factor
6
+ * and deliberately do not touch session 2FA state.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // app/api/mfa/totp/verify/route.ts
11
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-verify';
12
+ * ```
13
+ */
14
+ export { POST } from '../../api-handlers/mfa/totp-verify';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use TOTP Verify Route (2FA CHALLENGE, not enrolment)
6
+ *
7
+ * Verifies an authenticator code at LOGIN and transitions the session to
8
+ * MFA-verified. Pair with totp-enroll/totp-confirm, which only ENROL a factor
9
+ * and deliberately do not touch session 2FA state.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // app/api/mfa/totp/verify/route.ts
14
+ * export { POST } from '@payez/next-mvp/routes/mfa/totp-verify';
15
+ * ```
16
+ */
17
+ var totp_verify_1 = require("../../api-handlers/mfa/totp-verify");
18
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return totp_verify_1.POST; } });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use Passkey List Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/passkeys/route.ts
7
+ * export { GET } from '@payez/next-mvp/routes/passkeys/list';
8
+ * ```
9
+ */
10
+ export { GET } from '../../api-handlers/passkeys/list';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GET = void 0;
4
+ /**
5
+ * Ready-to-Use Passkey List Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/passkeys/route.ts
10
+ * export { GET } from '@payez/next-mvp/routes/passkeys/list';
11
+ * ```
12
+ */
13
+ var list_1 = require("../../api-handlers/passkeys/list");
14
+ Object.defineProperty(exports, "GET", { enumerable: true, get: function () { return list_1.GET; } });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Ready-to-Use Passkey Manage Route (rename / revoke one key)
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/passkeys/[id]/route.ts
7
+ * export { PATCH, DELETE } from '@payez/next-mvp/routes/passkeys/manage';
8
+ * ```
9
+ */
10
+ import { NextRequest } from 'next/server';
11
+ type Ctx = {
12
+ params: Promise<{
13
+ id: string;
14
+ }>;
15
+ };
16
+ export declare function PATCH(req: NextRequest, ctx: Ctx): Promise<import("next/server").NextResponse<any>>;
17
+ export declare function DELETE(req: NextRequest, ctx: Ctx): Promise<import("next/server").NextResponse<any>>;
18
+ export {};
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PATCH = PATCH;
4
+ exports.DELETE = DELETE;
5
+ const manage_1 = require("../../api-handlers/passkeys/manage");
6
+ async function PATCH(req, ctx) {
7
+ const { id } = await ctx.params;
8
+ return (0, manage_1.PATCH)(req, id);
9
+ }
10
+ async function DELETE(req, ctx) {
11
+ const { id } = await ctx.params;
12
+ return (0, manage_1.DELETE)(req, id);
13
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use Passkey Registration Options Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/passkeys/register/options/route.ts
7
+ * export { POST } from '@payez/next-mvp/routes/passkeys/register-options';
8
+ * ```
9
+ */
10
+ export { POST } from '../../api-handlers/passkeys/register-options';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use Passkey Registration Options Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/passkeys/register/options/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/passkeys/register-options';
11
+ * ```
12
+ */
13
+ var register_options_1 = require("../../api-handlers/passkeys/register-options");
14
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return register_options_1.POST; } });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Ready-to-Use Passkey Registration Verify Route
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // app/api/passkeys/register/verify/route.ts
7
+ * export { POST } from '@payez/next-mvp/routes/passkeys/register-verify';
8
+ * ```
9
+ */
10
+ export { POST } from '../../api-handlers/passkeys/register-verify';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = void 0;
4
+ /**
5
+ * Ready-to-Use Passkey Registration Verify Route
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/passkeys/register/verify/route.ts
10
+ * export { POST } from '@payez/next-mvp/routes/passkeys/register-verify';
11
+ * ```
12
+ */
13
+ var register_verify_1 = require("../../api-handlers/passkeys/register-verify");
14
+ Object.defineProperty(exports, "POST", { enumerable: true, get: function () { return register_verify_1.POST; } });
@@ -55,7 +55,7 @@ export declare function getAuthInstance(): Promise<import("better-auth/types").A
55
55
  handler: (inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<void>;
56
56
  }[];
57
57
  };
58
- }, ...{
58
+ }, ...(import("@better-auth/core").BetterAuthPlugin | {
59
59
  id: "magic-link";
60
60
  endpoints: {
61
61
  signInMagicLink: import("better-call").StrictEndpoint<"/sign-in/magic-link", {
@@ -150,7 +150,7 @@ export declare function getAuthInstance(): Promise<import("better-auth/types").A
150
150
  max: number;
151
151
  }[];
152
152
  options: import("better-auth/plugins/magic-link").MagicLinkOptions;
153
- }[]];
153
+ })[]];
154
154
  }>>;
155
155
  /**
156
156
  * Get the current session from a request.
@@ -96,8 +96,30 @@ async function tryBetterAuthSession(requestCookies) {
96
96
  try {
97
97
  const { getRedis } = await Promise.resolve().then(() => __importStar(require('../lib/redis')));
98
98
  const { getAppSlug } = await Promise.resolve().then(() => __importStar(require('../lib/app-slug')));
99
- const baKey = `ba:${getAppSlug()}:${result.session.token}`;
100
- const baRaw = await getRedis().get(baKey);
99
+ // KEY-COMPOSER MISMATCH FIX (2026-08-02).
100
+ // better-auth writes this key as `ba:${idpConfig.clientSlug || getAppSlug()}:...`
101
+ // (better-auth.ts:99). This reader used getAppSlug() ALONE, so on any
102
+ // deployment where the IDP returns a clientSlug that differs from
103
+ // APP_SLUG the lookup missed entirely: idpTokens stayed null, and every
104
+ // caller looked unauthenticated regardless of their real session.
105
+ // Observed live: writer produced ba:idp_admin_ui_graft:<token> while this
106
+ // reader asked for ba:payez_idp_admin_web:<token>.
107
+ //
108
+ // Try the writer's composition FIRST, then the original as a fallback.
109
+ // Additive on purpose: it can only ever find MORE sessions than before,
110
+ // so no consumer whose keys already resolved can regress.
111
+ let baRaw = null;
112
+ try {
113
+ const idpCfg = await (0, idp_client_config_1.getIDPClientConfig)();
114
+ const writerSlug = idpCfg?.clientSlug;
115
+ if (writerSlug) {
116
+ baRaw = await getRedis().get(`ba:${writerSlug}:${result.session.token}`);
117
+ }
118
+ }
119
+ catch { /* config unavailable — fall through to the legacy key */ }
120
+ if (!baRaw) {
121
+ baRaw = await getRedis().get(`ba:${getAppSlug()}:${result.session.token}`);
122
+ }
101
123
  if (baRaw) {
102
124
  const baData = JSON.parse(baRaw);
103
125
  idpTokens = baData.idpTokens;
@@ -115,7 +137,19 @@ async function tryBetterAuthSession(requestCookies) {
115
137
  idpAccessTokenExpires: idpTokens?.idpAccessTokenExpires
116
138
  || (result.session.expiresAt ? new Date(result.session.expiresAt).getTime() : Date.now() + 24 * 60 * 60 * 1000),
117
139
  mfaVerified: idpTokens?.mfaVerified ?? false,
118
- oauthProvider: 'google',
140
+ /**
141
+ * ⚠ WAS HARDCODED `'google'` — third site of QAPert finding #3 (card
142
+ * 167892), found by sweeping rather than by report.
143
+ *
144
+ * Note the line ABOVE is already honest: mfaVerified derives from what
145
+ * was stored. This one asserted the provider anyway, so a passkey
146
+ * sign-in decoded here was relabelled a Google OAuth sign-in — the
147
+ * provenance the sign-in path deliberately records, overwritten on read.
148
+ *
149
+ * The IDP emits NO provider claim (DotNetPert), so when it was not
150
+ * stored the honest answer is UNSET, not a guess.
151
+ */
152
+ oauthProvider: idpTokens?.oauthProvider ?? undefined,
119
153
  idpClientId: idpTokens?.idpClientId ?? idpTokens?.clientId,
120
154
  merchantId: idpTokens?.merchantId,
121
155
  };