@payez/next-mvp 4.1.11 → 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 (178) 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 +256 -42
  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/session-store.js +28 -21
  38. package/dist/lib/startup-init.js +19 -19
  39. package/dist/lib/token-lifecycle.js +40 -4
  40. package/dist/models/SessionModel.d.ts +17 -0
  41. package/dist/pages/login/page.d.ts +10 -1
  42. package/dist/pages/login/page.js +69 -80
  43. package/dist/pages/verify-code/page.d.ts +10 -1
  44. package/dist/pages/verify-code/page.js +72 -4
  45. package/dist/routes/auth/passkey-signin.d.ts +13 -0
  46. package/dist/routes/auth/passkey-signin.js +18 -0
  47. package/dist/routes/auth/viability.d.ts +2 -0
  48. package/dist/routes/auth/viability.js +88 -0
  49. package/dist/routes/mfa/backup-code-verify.d.ts +1 -0
  50. package/dist/routes/mfa/backup-code-verify.js +5 -0
  51. package/dist/routes/mfa/backup-codes.d.ts +10 -0
  52. package/dist/routes/mfa/backup-codes.js +14 -0
  53. package/dist/routes/mfa/methods.d.ts +21 -0
  54. package/dist/routes/mfa/methods.js +10 -0
  55. package/dist/routes/mfa/totp-confirm.d.ts +10 -0
  56. package/dist/routes/mfa/totp-confirm.js +14 -0
  57. package/dist/routes/mfa/totp-enroll.d.ts +10 -0
  58. package/dist/routes/mfa/totp-enroll.js +14 -0
  59. package/dist/routes/mfa/totp-verify.d.ts +14 -0
  60. package/dist/routes/mfa/totp-verify.js +18 -0
  61. package/dist/routes/passkeys/list.d.ts +10 -0
  62. package/dist/routes/passkeys/list.js +14 -0
  63. package/dist/routes/passkeys/manage.d.ts +18 -0
  64. package/dist/routes/passkeys/manage.js +13 -0
  65. package/dist/routes/passkeys/register-options.d.ts +10 -0
  66. package/dist/routes/passkeys/register-options.js +14 -0
  67. package/dist/routes/passkeys/register-verify.d.ts +10 -0
  68. package/dist/routes/passkeys/register-verify.js +14 -0
  69. package/dist/server/auth.d.ts +2 -2
  70. package/dist/server/decode-session.js +37 -3
  71. package/package.json +958 -893
  72. package/scripts/check-internal-url-usage.sh +73 -73
  73. package/src/api/index.ts +17 -17
  74. package/src/api-handlers/account/masked-info.ts +45 -45
  75. package/src/api-handlers/account/profile.ts +99 -80
  76. package/src/api-handlers/account/recovery/initiate.ts +23 -23
  77. package/src/api-handlers/account/recovery/send-code.ts +73 -25
  78. package/src/api-handlers/account/recovery/verify-code.ts +73 -25
  79. package/src/api-handlers/account/reset-password.ts +23 -23
  80. package/src/api-handlers/account/send-code.ts +76 -76
  81. package/src/api-handlers/account/validate-password.ts +118 -118
  82. package/src/api-handlers/account/verify-email.ts +15 -1
  83. package/src/api-handlers/account/verify-sms.ts +15 -1
  84. package/src/api-handlers/admin/stats.ts +249 -249
  85. package/src/api-handlers/anon/preferences.ts +123 -123
  86. package/src/api-handlers/auth/jwks.ts +20 -20
  87. package/src/api-handlers/auth/login.ts +240 -240
  88. package/src/api-handlers/auth/passkey-signin.ts +98 -0
  89. package/src/api-handlers/auth/validate.ts +43 -43
  90. package/src/api-handlers/mfa/backup-code-verify.ts +175 -0
  91. package/src/api-handlers/mfa/backup-codes.ts +41 -0
  92. package/src/api-handlers/mfa/methods.ts +46 -0
  93. package/src/api-handlers/mfa/totp-confirm.ts +42 -0
  94. package/src/api-handlers/mfa/totp-enroll.ts +42 -0
  95. package/src/api-handlers/mfa/totp-verify.ts +156 -0
  96. package/src/api-handlers/passkeys/list.ts +31 -0
  97. package/src/api-handlers/passkeys/manage.ts +54 -0
  98. package/src/api-handlers/passkeys/register-options.ts +42 -0
  99. package/src/api-handlers/passkeys/register-verify.ts +41 -0
  100. package/src/api-handlers/session/viability.ts +161 -142
  101. package/src/auth/better-auth.ts +247 -6
  102. package/src/auth/unauthenticated-routes.ts +2 -2
  103. package/src/auth/utils/idp-client.ts +13 -95
  104. package/src/client/better-auth-client.ts +70 -70
  105. package/src/client/fetchWithSession.ts +21 -21
  106. package/src/client/index.ts +13 -13
  107. package/src/client/useAnonSession.ts +131 -131
  108. package/src/components/admin/VibeAdminContext.tsx +87 -87
  109. package/src/config/logging-config.ts +82 -82
  110. package/src/config/unauthenticated-routes.ts +19 -19
  111. package/src/edge/internal-api-url.ts +65 -65
  112. package/src/edge/middleware.ts +42 -42
  113. package/src/hooks/useProfile.ts +75 -75
  114. package/src/lib/anon-session.ts +213 -213
  115. package/src/lib/auth-secret.ts +137 -137
  116. package/src/lib/demo-mode.ts +17 -17
  117. package/src/lib/idp-client-config.ts +559 -559
  118. package/src/lib/idp-fetch.ts +126 -126
  119. package/src/lib/internal-api.ts +171 -171
  120. package/src/lib/jwt-decode-client.ts +45 -45
  121. package/src/lib/rate-limit-service.ts +9 -9
  122. package/src/lib/redis.ts +26 -26
  123. package/src/lib/refresh-token-validator.ts +64 -64
  124. package/src/lib/secret-validation.ts +8 -8
  125. package/src/lib/session-store.ts +702 -695
  126. package/src/lib/session.ts +34 -34
  127. package/src/lib/startup-init.ts +251 -251
  128. package/src/lib/token-expiry.ts +40 -40
  129. package/src/lib/token-lifecycle.ts +533 -497
  130. package/src/lib/types/api-responses.ts +336 -336
  131. package/src/middleware/auth-decision.ts +43 -43
  132. package/src/models/DecodedAccessToken.ts +16 -16
  133. package/src/models/SessionModel.ts +282 -264
  134. package/src/pages/admin-roles/index.ts +9 -9
  135. package/src/pages/login/page.tsx +123 -228
  136. package/src/pages/security/EnhancedSecurityPage.tsx +9 -9
  137. package/src/pages/verify-code/page.tsx +71 -5
  138. package/src/routes/account/index.ts +31 -31
  139. package/src/routes/account/masked-info.ts +36 -36
  140. package/src/routes/account/send-code.ts +39 -39
  141. package/src/routes/account/verify-email.ts +40 -40
  142. package/src/routes/account/verify-sms.ts +40 -40
  143. package/src/routes/auth/index.ts +22 -22
  144. package/src/routes/auth/passkey-signin.ts +13 -0
  145. package/src/routes/auth/refresh.ts +48 -48
  146. package/src/routes/auth/session.ts +166 -166
  147. package/src/routes/auth/viability.ts +89 -0
  148. package/src/routes/index.ts +17 -17
  149. package/src/routes/mfa/backup-code-verify.ts +1 -0
  150. package/src/routes/mfa/backup-codes.ts +10 -0
  151. package/src/routes/mfa/methods.ts +22 -0
  152. package/src/routes/mfa/totp-confirm.ts +10 -0
  153. package/src/routes/mfa/totp-enroll.ts +10 -0
  154. package/src/routes/mfa/totp-verify.ts +14 -0
  155. package/src/routes/passkeys/list.ts +10 -0
  156. package/src/routes/passkeys/manage.ts +23 -0
  157. package/src/routes/passkeys/register-options.ts +10 -0
  158. package/src/routes/passkeys/register-verify.ts +10 -0
  159. package/src/routes/session/index.ts +7 -7
  160. package/src/routes/session/refresh-viability.ts +17 -17
  161. package/src/server/auth.ts +373 -373
  162. package/src/server/decode-session.ts +235 -202
  163. package/src/services/signalrActivityService.ts +258 -258
  164. package/src/theme/ThemeProvider.tsx +39 -39
  165. package/src/theme/default.ts +33 -33
  166. package/src/theme/index.ts +31 -31
  167. package/src/theme/types.ts +69 -69
  168. package/src/theme/useTheme.ts +57 -57
  169. package/src/theme/utils.ts +40 -40
  170. package/src/types/api.ts +12 -12
  171. package/src/types/auth.d.ts +23 -23
  172. package/src/types/auth.ts +22 -22
  173. package/src/types/logging.ts +11 -11
  174. package/src/types/recovery.ts +54 -54
  175. package/src/utils/api.ts +353 -353
  176. package/src/utils/circuitBreaker.ts +40 -40
  177. package/src/utils/error-message.ts +108 -108
  178. package/src/utils/layout/reservedSpace.ts +124 -124
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PATCH = PATCH;
4
+ exports.DELETE = DELETE;
5
+ const server_1 = require("next/server");
6
+ const idp_fetch_1 = require("../../lib/idp-fetch");
7
+ const env_1 = require("../../config/env");
8
+ /**
9
+ * Manage ONE passkey (PATCH rename / DELETE revoke, /api/Passkeys/{id},
10
+ * user JWT). The id arrives from the Next dynamic segment via the routes
11
+ * wrapper — it is never read from the body.
12
+ */
13
+ function upstreamError(result) {
14
+ return server_1.NextResponse.json({
15
+ success: false,
16
+ message: 'Upstream error',
17
+ error: { code: 'UPSTREAM_SERVICE_ERROR', status: result.status, details: result.json },
18
+ meta: { attemptedRefresh: result.attemptedRefresh },
19
+ }, { status: result.status });
20
+ }
21
+ function passthrough(json) {
22
+ const bodyJson = json;
23
+ if (bodyJson && typeof bodyJson === 'object' && 'success' in bodyJson && 'data' in bodyJson) {
24
+ if (bodyJson.success === true)
25
+ return server_1.NextResponse.json(bodyJson.data ?? { success: true }, { status: 200 });
26
+ return server_1.NextResponse.json(bodyJson, { status: 200 });
27
+ }
28
+ return server_1.NextResponse.json(bodyJson ?? { success: true }, { status: 200 });
29
+ }
30
+ async function PATCH(req, id) {
31
+ let body = '{}';
32
+ try {
33
+ const raw = await req.text();
34
+ if (raw && raw.trim().length > 0)
35
+ body = raw;
36
+ }
37
+ catch { }
38
+ const result = await (0, idp_fetch_1.idpFetchJSON)(req, `${env_1.ENV_CONFIG.IDP_URL}/api/Passkeys/${encodeURIComponent(id)}`, {
39
+ method: 'PATCH',
40
+ headers: { 'Content-Type': 'application/json' },
41
+ body,
42
+ });
43
+ if (!result.ok)
44
+ return upstreamError(result);
45
+ return passthrough(result.json);
46
+ }
47
+ async function DELETE(req, id) {
48
+ const result = await (0, idp_fetch_1.idpFetchJSON)(req, `${env_1.ENV_CONFIG.IDP_URL}/api/Passkeys/${encodeURIComponent(id)}`, {
49
+ method: 'DELETE',
50
+ });
51
+ if (!result.ok)
52
+ return upstreamError(result);
53
+ return passthrough(result.json);
54
+ }
@@ -0,0 +1,8 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ /**
3
+ * Begin the passkey REGISTRATION ceremony (POST /api/Passkeys/register/options,
4
+ * user JWT — a credential change; the IDP may demand step-up, surfaced as-is).
5
+ * Returns the WebAuthn PublicKeyCredentialCreationOptions (ride the envelope
6
+ * `data`, per the archived hand-roll contract).
7
+ */
8
+ export declare function POST(req: NextRequest): Promise<NextResponse<any>>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ const server_1 = require("next/server");
5
+ const idp_fetch_1 = require("../../lib/idp-fetch");
6
+ const env_1 = require("../../config/env");
7
+ /**
8
+ * Begin the passkey REGISTRATION ceremony (POST /api/Passkeys/register/options,
9
+ * user JWT — a credential change; the IDP may demand step-up, surfaced as-is).
10
+ * Returns the WebAuthn PublicKeyCredentialCreationOptions (ride the envelope
11
+ * `data`, per the archived hand-roll contract).
12
+ */
13
+ async function POST(req) {
14
+ let body = '{}';
15
+ try {
16
+ const raw = await req.text();
17
+ if (raw && raw.trim().length > 0)
18
+ body = raw;
19
+ }
20
+ catch { }
21
+ const result = await (0, idp_fetch_1.idpFetchJSON)(req, `${env_1.ENV_CONFIG.IDP_URL}/api/Passkeys/register/options`, {
22
+ method: 'POST',
23
+ headers: { 'Content-Type': 'application/json' },
24
+ body,
25
+ });
26
+ if (!result.ok) {
27
+ return server_1.NextResponse.json({
28
+ success: false,
29
+ message: 'Upstream error',
30
+ error: { code: 'UPSTREAM_SERVICE_ERROR', status: result.status, details: result.json },
31
+ meta: { attemptedRefresh: result.attemptedRefresh },
32
+ }, { status: result.status });
33
+ }
34
+ const bodyJson = result.json;
35
+ if (bodyJson && typeof bodyJson === 'object' && 'success' in bodyJson && 'data' in bodyJson) {
36
+ if (bodyJson.success === true)
37
+ return server_1.NextResponse.json(bodyJson.data, { status: 200 });
38
+ return server_1.NextResponse.json(bodyJson, { status: 200 });
39
+ }
40
+ return server_1.NextResponse.json(bodyJson ?? {}, { status: 200 });
41
+ }
@@ -0,0 +1,7 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ /**
3
+ * Finish the passkey REGISTRATION ceremony (POST /api/Passkeys/register/verify,
4
+ * user JWT). Body forwarded VERBATIM — it carries the enrolment handle plus the
5
+ * authenticator attestation produced by navigator.credentials.create().
6
+ */
7
+ export declare function POST(req: NextRequest): Promise<NextResponse<any>>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.POST = POST;
4
+ const server_1 = require("next/server");
5
+ const idp_fetch_1 = require("../../lib/idp-fetch");
6
+ const env_1 = require("../../config/env");
7
+ /**
8
+ * Finish the passkey REGISTRATION ceremony (POST /api/Passkeys/register/verify,
9
+ * user JWT). Body forwarded VERBATIM — it carries the enrolment handle plus the
10
+ * authenticator attestation produced by navigator.credentials.create().
11
+ */
12
+ async function POST(req) {
13
+ let body = '{}';
14
+ try {
15
+ const raw = await req.text();
16
+ if (raw && raw.trim().length > 0)
17
+ body = raw;
18
+ }
19
+ catch { }
20
+ const result = await (0, idp_fetch_1.idpFetchJSON)(req, `${env_1.ENV_CONFIG.IDP_URL}/api/Passkeys/register/verify`, {
21
+ method: 'POST',
22
+ headers: { 'Content-Type': 'application/json' },
23
+ body,
24
+ });
25
+ if (!result.ok) {
26
+ return server_1.NextResponse.json({
27
+ success: false,
28
+ message: 'Upstream error',
29
+ error: { code: 'UPSTREAM_SERVICE_ERROR', status: result.status, details: result.json },
30
+ meta: { attemptedRefresh: result.attemptedRefresh },
31
+ }, { status: result.status });
32
+ }
33
+ const bodyJson = result.json;
34
+ if (bodyJson && typeof bodyJson === 'object' && 'success' in bodyJson && 'data' in bodyJson) {
35
+ if (bodyJson.success === true)
36
+ return server_1.NextResponse.json(bodyJson.data, { status: 200 });
37
+ return server_1.NextResponse.json(bodyJson, { status: 200 });
38
+ }
39
+ return server_1.NextResponse.json(bodyJson ?? {}, { status: 200 });
40
+ }
@@ -103,6 +103,25 @@ async function GET(req) {
103
103
  // 2FA fields - critical for middleware redirect logic
104
104
  requires2FA, // From cached client config (client-wide setting)
105
105
  twoFactorComplete: effectiveTwoFactorComplete, // From session, BUT respects MFA TTL
106
+ // Cards 141688/141741 — the IDP's routing decision, relayed verbatim.
107
+ //
108
+ // THIS IS THE SECOND IMPLEMENTATION OF VIABILITY. The other is
109
+ // routes/auth/viability.ts, which is what the admin graft mounts.
110
+ // Both are publicly exported entry points, so both can be a consumer's
111
+ // only source of this answer. Adding the relay to just one would leave
112
+ // an app that mounts THIS one still blind to enroll_mfa — the exact
113
+ // seam these cards are about, reopened one export over.
114
+ //
115
+ // 'enroll_mfa' = no USABLE method, the user cannot complete a
116
+ // challenge. 'mfa_verify' = usable method exists. null = nothing due.
117
+ // NOT a completion signal: twoFactorComplete still owns that.
118
+ //
119
+ // No `?? null`: undefined (never captured — every session minted
120
+ // before this change) must stay distinguishable from null (the IDP
121
+ // said nothing is outstanding). Defaulting to null would tell the
122
+ // gate that every pre-existing session is fully authenticated,
123
+ // including zero-method users who must be routed to enrol.
124
+ nextStep: sessionData.nextStep,
106
125
  // Token status for refresh decisions
107
126
  accessTokenExpired,
108
127
  hasRefreshToken: !!sessionData.idpRefreshToken
@@ -9,6 +9,7 @@
9
9
  * @see BETTER-AUTH-MIGRATION-SPEC.md
10
10
  */
11
11
  import 'server-only';
12
+ import { betterAuth } from 'better-auth';
12
13
  import { type MagicLinkOptions } from 'better-auth/plugins/magic-link';
13
14
  import type { IDPClientConfig } from '../lib/idp-client-config';
14
15
  /**
@@ -22,9 +23,6 @@ export interface BetterAuthSocialProvider {
22
23
  accessType?: 'offline' | 'online';
23
24
  hd?: string;
24
25
  }
25
- /**
26
- * Build Better Auth social providers from IDP config.
27
- */
28
26
  export declare function buildBetterAuthProviders(config: IDPClientConfig): Record<string, BetterAuthSocialProvider>;
29
27
  /**
30
28
  * Optional configuration for `createBetterAuthInstance`.
@@ -37,6 +35,27 @@ export declare function buildBetterAuthProviders(config: IDPClientConfig): Recor
37
35
  */
38
36
  export interface CreateBetterAuthInstanceOptions {
39
37
  magicLink?: MagicLinkOptions;
38
+ /**
39
+ * Extra Better Auth plugins supplied by the consuming app.
40
+ *
41
+ * WHY THIS EXISTS — session minting is not delegable any other way. BA's
42
+ * `setSessionCookie` requires a `GenericEndpointContext`, which only BA's own
43
+ * endpoint machinery constructs, so an app that must mint a session for an
44
+ * identity established OUTSIDE BA's built-in providers (passkey sign-in being
45
+ * the first) cannot do it from a route handler. It needs a real BA endpoint,
46
+ * and endpoints only arrive via plugins.
47
+ *
48
+ * Deliberately GENERIC. The package gains "an app may supply plugins" rather
49
+ * than any knowledge of passkeys — the alternative was teaching this file
50
+ * about a specific auth method, which is how a package accumulates a consumer's
51
+ * feature list.
52
+ *
53
+ * The alternative to this option is an app hand-rolling the session cookie
54
+ * (`{token}.{base64(hmac)}`, standard padding, runtime `authSecret` from
55
+ * Redis). That fails as a session which DECODES BUT DOES NOT AUTHENTICATE —
56
+ * so this option exists specifically to make that shortcut unnecessary.
57
+ */
58
+ plugins?: Parameters<typeof betterAuth>[0]['plugins'];
40
59
  }
41
60
  /**
42
61
  * Create Better Auth instance from IDP config.
@@ -81,7 +100,7 @@ export declare function createBetterAuthInstance(idpConfig: IDPClientConfig, opt
81
100
  handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>;
82
101
  }[];
83
102
  };
84
- }, ...{
103
+ }, ...(import("better-auth").BetterAuthPlugin | {
85
104
  id: "magic-link";
86
105
  endpoints: {
87
106
  signInMagicLink: import("better-auth").StrictEndpoint<"/sign-in/magic-link", {
@@ -176,7 +195,7 @@ export declare function createBetterAuthInstance(idpConfig: IDPClientConfig, opt
176
195
  max: number;
177
196
  }[];
178
197
  options: MagicLinkOptions;
179
- }[]];
198
+ })[]];
180
199
  }>;
181
200
  /**
182
201
  * Better Auth is always enabled (NextAuth removed in 4.0).
@@ -231,6 +250,50 @@ export declare function getBetterAuthHandler(): Promise<{
231
250
  * This replaces the old databaseHooks approach which doesn't fire in stateless mode.
232
251
  */
233
252
  export declare function exchangeOAuthForIdpTokens(sessionToken: string, provider?: string): Promise<boolean>;
253
+ /**
254
+ * Write IDP tokens into an EXISTING Better Auth session. Storage only — this
255
+ * function never acquires tokens and never decides who the caller is.
256
+ *
257
+ * ── WHY THIS IS SPLIT OUT (BAPert ruling, 2026-08-04) ────────────────────────
258
+ *
259
+ * `exchangeOAuthForIdpTokens` above does TWO things: it ACQUIRES tokens by
260
+ * POSTing to `/api/ExternalAuth/oauth-callback`, and then it STORES them. Only
261
+ * the second half is reusable, and the first half is actively dangerous to
262
+ * reuse:
263
+ *
264
+ * oauth-callback mints an IDP bearer from an ASSERTED EMAIL with no
265
+ * cryptographic verification of any kind (card 138635).
266
+ *
267
+ * Passkey sign-in already holds something strictly better — a grant issued by
268
+ * `/api/ExternalAuth/passwordless/passkey/verify`, which checked a real
269
+ * signature against a registered credential. Routing that through
270
+ * oauth-callback to obtain a session would DOWNGRADE a cryptographically
271
+ * verified assertion into an unverified one, make passkey sign-in weaker than
272
+ * its own ceremony, and inherit 138635 wholesale.
273
+ *
274
+ * That is not hypothetical: "do what the OAuth path does" is the obvious
275
+ * implementation and it is the wrong one. Splitting acquisition from storage is
276
+ * what makes the wrong one hard to write by accident.
277
+ *
278
+ * ── WHAT CALLERS MUST HAVE DONE FIRST ───────────────────────────────────────
279
+ *
280
+ * A Better Auth session must ALREADY EXIST for `sessionToken`. This function
281
+ * enriches; it does not create. Better Auth owns session creation and cookie
282
+ * signing, and nothing in this package should replicate either — the cookie is
283
+ * `{token}.{base64(hmac)}` with standard padding, signed with the runtime
284
+ * `authSecret` from Redis, and hand-rolling that produces a session which
285
+ * decodes but does not authenticate.
286
+ *
287
+ * @param sessionToken the Better Auth session token (from its Set-Cookie)
288
+ * @param idpTokenData tokens + identity, already obtained by the CALLER'S OWN
289
+ * verified route. Built field-by-field by the caller so an
290
+ * unnamed field cannot ride along silently.
291
+ * @param authProvider provenance label recorded on the canonical row. Written
292
+ * to the historical `oauthProvider` key, which predates
293
+ * non-OAuth callers; the NAME is legacy, the VALUE should
294
+ * state what actually authenticated ('passkey', 'google').
295
+ */
296
+ export declare function storeIdpTokensInSession(sessionToken: string, idpTokenData: Record<string, unknown>, authProvider: string): Promise<boolean>;
234
297
  /**
235
298
  * Create a production-ready GET handler for the auth catch-all route.
236
299
  *