@payez/next-mvp 3.0.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.
Files changed (654) hide show
  1. package/README.md +782 -0
  2. package/dist/api/auth-handler.d.ts +67 -0
  3. package/dist/api/auth-handler.js +397 -0
  4. package/dist/api/index.d.ts +10 -0
  5. package/dist/api/index.js +19 -0
  6. package/dist/api-handlers/account/change-password.d.ts +9 -0
  7. package/dist/api-handlers/account/change-password.js +112 -0
  8. package/dist/api-handlers/account/masked-info.d.ts +2 -0
  9. package/dist/api-handlers/account/masked-info.js +41 -0
  10. package/dist/api-handlers/account/profile.d.ts +3 -0
  11. package/dist/api-handlers/account/profile.js +63 -0
  12. package/dist/api-handlers/account/recovery/initiate.d.ts +2 -0
  13. package/dist/api-handlers/account/recovery/initiate.js +26 -0
  14. package/dist/api-handlers/account/recovery/send-code.d.ts +2 -0
  15. package/dist/api-handlers/account/recovery/send-code.js +28 -0
  16. package/dist/api-handlers/account/recovery/verify-code.d.ts +2 -0
  17. package/dist/api-handlers/account/recovery/verify-code.js +28 -0
  18. package/dist/api-handlers/account/reset-password.d.ts +2 -0
  19. package/dist/api-handlers/account/reset-password.js +26 -0
  20. package/dist/api-handlers/account/send-code.d.ts +24 -0
  21. package/dist/api-handlers/account/send-code.js +60 -0
  22. package/dist/api-handlers/account/update-phone.d.ts +27 -0
  23. package/dist/api-handlers/account/update-phone.js +64 -0
  24. package/dist/api-handlers/account/validate-password.d.ts +17 -0
  25. package/dist/api-handlers/account/validate-password.js +81 -0
  26. package/dist/api-handlers/account/verify-email.d.ts +26 -0
  27. package/dist/api-handlers/account/verify-email.js +106 -0
  28. package/dist/api-handlers/account/verify-sms.d.ts +26 -0
  29. package/dist/api-handlers/account/verify-sms.js +106 -0
  30. package/dist/api-handlers/admin/analytics.d.ts +20 -0
  31. package/dist/api-handlers/admin/analytics.js +379 -0
  32. package/dist/api-handlers/admin/audit.d.ts +20 -0
  33. package/dist/api-handlers/admin/audit.js +214 -0
  34. package/dist/api-handlers/admin/index.d.ts +21 -0
  35. package/dist/api-handlers/admin/index.js +41 -0
  36. package/dist/api-handlers/admin/redis-sessions.d.ts +36 -0
  37. package/dist/api-handlers/admin/redis-sessions.js +204 -0
  38. package/dist/api-handlers/admin/sessions.d.ts +21 -0
  39. package/dist/api-handlers/admin/sessions.js +284 -0
  40. package/dist/api-handlers/admin/site-logs.d.ts +46 -0
  41. package/dist/api-handlers/admin/site-logs.js +318 -0
  42. package/dist/api-handlers/admin/users.d.ts +20 -0
  43. package/dist/api-handlers/admin/users.js +222 -0
  44. package/dist/api-handlers/admin/vibe-data.d.ts +80 -0
  45. package/dist/api-handlers/admin/vibe-data.js +268 -0
  46. package/dist/api-handlers/anon/preferences.d.ts +37 -0
  47. package/dist/api-handlers/anon/preferences.js +96 -0
  48. package/dist/api-handlers/auth/jwks.d.ts +2 -0
  49. package/dist/api-handlers/auth/jwks.js +24 -0
  50. package/dist/api-handlers/auth/login.d.ts +42 -0
  51. package/dist/api-handlers/auth/login.js +178 -0
  52. package/dist/api-handlers/auth/refresh.d.ts +74 -0
  53. package/dist/api-handlers/auth/refresh.js +635 -0
  54. package/dist/api-handlers/auth/signout.d.ts +37 -0
  55. package/dist/api-handlers/auth/signout.js +187 -0
  56. package/dist/api-handlers/auth/status.d.ts +8 -0
  57. package/dist/api-handlers/auth/status.js +26 -0
  58. package/dist/api-handlers/auth/update-session.d.ts +37 -0
  59. package/dist/api-handlers/auth/update-session.js +95 -0
  60. package/dist/api-handlers/auth/validate.d.ts +6 -0
  61. package/dist/api-handlers/auth/validate.js +43 -0
  62. package/dist/api-handlers/auth/verify-code.d.ts +43 -0
  63. package/dist/api-handlers/auth/verify-code.js +94 -0
  64. package/dist/api-handlers/session/refresh-viability.d.ts +14 -0
  65. package/dist/api-handlers/session/refresh-viability.js +39 -0
  66. package/dist/api-handlers/session/viability.d.ts +13 -0
  67. package/dist/api-handlers/session/viability.js +146 -0
  68. package/dist/api-handlers/test/force-expire.d.ts +23 -0
  69. package/dist/api-handlers/test/force-expire.js +65 -0
  70. package/dist/auth/auth-decision.d.ts +39 -0
  71. package/dist/auth/auth-decision.js +182 -0
  72. package/dist/auth/auth-options.d.ts +57 -0
  73. package/dist/auth/auth-options.js +213 -0
  74. package/dist/auth/callbacks/index.d.ts +6 -0
  75. package/dist/auth/callbacks/index.js +12 -0
  76. package/dist/auth/callbacks/jwt.d.ts +45 -0
  77. package/dist/auth/callbacks/jwt.js +305 -0
  78. package/dist/auth/callbacks/session.d.ts +60 -0
  79. package/dist/auth/callbacks/session.js +170 -0
  80. package/dist/auth/callbacks/signin.d.ts +23 -0
  81. package/dist/auth/callbacks/signin.js +44 -0
  82. package/dist/auth/events/index.d.ts +4 -0
  83. package/dist/auth/events/index.js +8 -0
  84. package/dist/auth/events/signout.d.ts +17 -0
  85. package/dist/auth/events/signout.js +32 -0
  86. package/dist/auth/providers/credentials.d.ts +32 -0
  87. package/dist/auth/providers/credentials.js +223 -0
  88. package/dist/auth/providers/index.d.ts +5 -0
  89. package/dist/auth/providers/index.js +21 -0
  90. package/dist/auth/providers/oauth.d.ts +26 -0
  91. package/dist/auth/providers/oauth.js +105 -0
  92. package/dist/auth/route-config.d.ts +66 -0
  93. package/dist/auth/route-config.js +190 -0
  94. package/dist/auth/types/auth-types.d.ts +417 -0
  95. package/dist/auth/types/auth-types.js +53 -0
  96. package/dist/auth/types/index.d.ts +6 -0
  97. package/dist/auth/types/index.js +22 -0
  98. package/dist/auth/unauthenticated-routes.d.ts +1 -0
  99. package/dist/auth/unauthenticated-routes.js +19 -0
  100. package/dist/auth/utils/idp-client.d.ts +94 -0
  101. package/dist/auth/utils/idp-client.js +383 -0
  102. package/dist/auth/utils/index.d.ts +5 -0
  103. package/dist/auth/utils/index.js +21 -0
  104. package/dist/auth/utils/token-utils.d.ts +84 -0
  105. package/dist/auth/utils/token-utils.js +219 -0
  106. package/dist/client/AuthContext.d.ts +19 -0
  107. package/dist/client/AuthContext.js +112 -0
  108. package/dist/client/fetch-with-auth.d.ts +11 -0
  109. package/dist/client/fetch-with-auth.js +44 -0
  110. package/dist/client/fetchWithSession.d.ts +3 -0
  111. package/dist/client/fetchWithSession.js +24 -0
  112. package/dist/client/index.d.ts +9 -0
  113. package/dist/client/index.js +20 -0
  114. package/dist/client/useAnonSession.d.ts +36 -0
  115. package/dist/client/useAnonSession.js +99 -0
  116. package/dist/components/SessionSync.d.ts +13 -0
  117. package/dist/components/SessionSync.js +119 -0
  118. package/dist/components/SignalRHealthCheck.d.ts +10 -0
  119. package/dist/components/SignalRHealthCheck.js +97 -0
  120. package/dist/components/account/UserAvatarMenu.d.ts +20 -0
  121. package/dist/components/account/UserAvatarMenu.js +80 -0
  122. package/dist/components/account/index.d.ts +7 -0
  123. package/dist/components/account/index.js +10 -0
  124. package/dist/components/admin/AlertSettingsTab.d.ts +48 -0
  125. package/dist/components/admin/AlertSettingsTab.js +351 -0
  126. package/dist/components/admin/AnalyticsTab.d.ts +22 -0
  127. package/dist/components/admin/AnalyticsTab.js +167 -0
  128. package/dist/components/admin/DataBrowserTab.d.ts +19 -0
  129. package/dist/components/admin/DataBrowserTab.js +252 -0
  130. package/dist/components/admin/LoggingSettingsTab.d.ts +73 -0
  131. package/dist/components/admin/LoggingSettingsTab.js +339 -0
  132. package/dist/components/admin/SessionsTab.d.ts +37 -0
  133. package/dist/components/admin/SessionsTab.js +165 -0
  134. package/dist/components/admin/StatsTab.d.ts +53 -0
  135. package/dist/components/admin/StatsTab.js +161 -0
  136. package/dist/components/admin/VibeAdminContext.d.ts +32 -0
  137. package/dist/components/admin/VibeAdminContext.js +38 -0
  138. package/dist/components/admin/VibeAdminLayout.d.ts +11 -0
  139. package/dist/components/admin/VibeAdminLayout.js +69 -0
  140. package/dist/components/admin/index.d.ts +29 -0
  141. package/dist/components/admin/index.js +44 -0
  142. package/dist/components/auth/FederatedAuthSection.d.ts +8 -0
  143. package/dist/components/auth/FederatedAuthSection.js +45 -0
  144. package/dist/components/auth/ModeAwareLoginPage.d.ts +10 -0
  145. package/dist/components/auth/ModeAwareLoginPage.js +42 -0
  146. package/dist/components/auth/ModeAwareSignupPage.d.ts +9 -0
  147. package/dist/components/auth/ModeAwareSignupPage.js +78 -0
  148. package/dist/components/auth/TraditionalAuthSection.d.ts +14 -0
  149. package/dist/components/auth/TraditionalAuthSection.js +20 -0
  150. package/dist/components/recovery/CompleteStep.d.ts +5 -0
  151. package/dist/components/recovery/CompleteStep.js +8 -0
  152. package/dist/components/recovery/InitiateRecoveryStep.d.ts +8 -0
  153. package/dist/components/recovery/InitiateRecoveryStep.js +20 -0
  154. package/dist/components/recovery/SelectMethodStep.d.ts +8 -0
  155. package/dist/components/recovery/SelectMethodStep.js +8 -0
  156. package/dist/components/recovery/SetPasswordStep.d.ts +6 -0
  157. package/dist/components/recovery/SetPasswordStep.js +20 -0
  158. package/dist/components/recovery/VerifyCodeStep.d.ts +10 -0
  159. package/dist/components/recovery/VerifyCodeStep.js +24 -0
  160. package/dist/components/reserved/ReservedRecoveryWarning.d.ts +38 -0
  161. package/dist/components/reserved/ReservedRecoveryWarning.js +92 -0
  162. package/dist/components/reserved/ReservedStatusBox.d.ts +30 -0
  163. package/dist/components/reserved/ReservedStatusBox.js +71 -0
  164. package/dist/components/ui/BetaBadge.d.ts +29 -0
  165. package/dist/components/ui/BetaBadge.js +38 -0
  166. package/dist/components/ui/Footer.d.ts +37 -0
  167. package/dist/components/ui/Footer.js +41 -0
  168. package/dist/config/env.d.ts +66 -0
  169. package/dist/config/env.js +57 -0
  170. package/dist/config/logger.d.ts +57 -0
  171. package/dist/config/logger.js +73 -0
  172. package/dist/config/logging-config.d.ts +30 -0
  173. package/dist/config/logging-config.js +122 -0
  174. package/dist/config/unauthenticated-routes.d.ts +17 -0
  175. package/dist/config/unauthenticated-routes.js +24 -0
  176. package/dist/config/vibe-log-transport.d.ts +79 -0
  177. package/dist/config/vibe-log-transport.js +203 -0
  178. package/dist/edge/internal-api-url.d.ts +53 -0
  179. package/dist/edge/internal-api-url.js +63 -0
  180. package/dist/edge/middleware.d.ts +14 -0
  181. package/dist/edge/middleware.js +32 -0
  182. package/dist/hooks/useAuth.d.ts +23 -0
  183. package/dist/hooks/useAuth.js +81 -0
  184. package/dist/hooks/useAuthSettings.d.ts +59 -0
  185. package/dist/hooks/useAuthSettings.js +93 -0
  186. package/dist/hooks/useAvailableProviders.d.ts +45 -0
  187. package/dist/hooks/useAvailableProviders.js +108 -0
  188. package/dist/hooks/usePasswordValidation.d.ts +27 -0
  189. package/dist/hooks/usePasswordValidation.js +102 -0
  190. package/dist/hooks/useProfile.d.ts +15 -0
  191. package/dist/hooks/useProfile.js +59 -0
  192. package/dist/hooks/usePublicAuthSettings.d.ts +56 -0
  193. package/dist/hooks/usePublicAuthSettings.js +131 -0
  194. package/dist/hooks/useSessionExpiration.d.ts +57 -0
  195. package/dist/hooks/useSessionExpiration.js +72 -0
  196. package/dist/hooks/useViabilitySession.d.ts +75 -0
  197. package/dist/hooks/useViabilitySession.js +268 -0
  198. package/dist/index.d.ts +12 -0
  199. package/dist/index.js +54 -0
  200. package/dist/lib/anon-session.d.ts +74 -0
  201. package/dist/lib/anon-session.js +169 -0
  202. package/dist/lib/api-handler.d.ts +123 -0
  203. package/dist/lib/api-handler.js +478 -0
  204. package/dist/lib/app-slug.d.ts +95 -0
  205. package/dist/lib/app-slug.js +172 -0
  206. package/dist/lib/demo-mode.d.ts +6 -0
  207. package/dist/lib/demo-mode.js +16 -0
  208. package/dist/lib/geolocation.d.ts +64 -0
  209. package/dist/lib/geolocation.js +235 -0
  210. package/dist/lib/idp-client-config.d.ts +75 -0
  211. package/dist/lib/idp-client-config.js +351 -0
  212. package/dist/lib/idp-fetch.d.ts +14 -0
  213. package/dist/lib/idp-fetch.js +91 -0
  214. package/dist/lib/internal-api.d.ts +87 -0
  215. package/dist/lib/internal-api.js +122 -0
  216. package/dist/lib/jwt-decode-client.d.ts +10 -0
  217. package/dist/lib/jwt-decode-client.js +46 -0
  218. package/dist/lib/jwt-decode.d.ts +48 -0
  219. package/dist/lib/jwt-decode.js +57 -0
  220. package/dist/lib/nextauth-secret.d.ts +10 -0
  221. package/dist/lib/nextauth-secret.js +104 -0
  222. package/dist/lib/rate-limit-service.d.ts +23 -0
  223. package/dist/lib/rate-limit-service.js +6 -0
  224. package/dist/lib/redis.d.ts +5 -0
  225. package/dist/lib/redis.js +28 -0
  226. package/dist/lib/refresh-token-validator.d.ts +13 -0
  227. package/dist/lib/refresh-token-validator.js +117 -0
  228. package/dist/lib/roles.d.ts +145 -0
  229. package/dist/lib/roles.js +168 -0
  230. package/dist/lib/secret-validation.d.ts +4 -0
  231. package/dist/lib/secret-validation.js +14 -0
  232. package/dist/lib/session-store.d.ts +166 -0
  233. package/dist/lib/session-store.js +537 -0
  234. package/dist/lib/session.d.ts +21 -0
  235. package/dist/lib/session.js +26 -0
  236. package/dist/lib/site-logger.d.ts +214 -0
  237. package/dist/lib/site-logger.js +210 -0
  238. package/dist/lib/standardized-client-api.d.ts +161 -0
  239. package/dist/lib/standardized-client-api.js +786 -0
  240. package/dist/lib/startup-init.d.ts +40 -0
  241. package/dist/lib/startup-init.js +261 -0
  242. package/dist/lib/test-aware-get-token.d.ts +2 -0
  243. package/dist/lib/test-aware-get-token.js +81 -0
  244. package/dist/lib/token-expiry.d.ts +14 -0
  245. package/dist/lib/token-expiry.js +39 -0
  246. package/dist/lib/token-lifecycle.d.ts +52 -0
  247. package/dist/lib/token-lifecycle.js +398 -0
  248. package/dist/lib/types/api-responses.d.ts +128 -0
  249. package/dist/lib/types/api-responses.js +171 -0
  250. package/dist/lib/user-agent-parser.d.ts +50 -0
  251. package/dist/lib/user-agent-parser.js +220 -0
  252. package/dist/logging/api/admin-analytics.d.ts +3 -0
  253. package/dist/logging/api/admin-analytics.js +45 -0
  254. package/dist/logging/api/audit-log.d.ts +3 -0
  255. package/dist/logging/api/audit-log.js +52 -0
  256. package/dist/logging/components/AdminAnalyticsLayout.d.ts +10 -0
  257. package/dist/logging/components/AdminAnalyticsLayout.js +11 -0
  258. package/dist/logging/components/AuditLogViewer.d.ts +7 -0
  259. package/dist/logging/components/AuditLogViewer.js +51 -0
  260. package/dist/logging/components/ErrorMetricsCard.d.ts +7 -0
  261. package/dist/logging/components/ErrorMetricsCard.js +16 -0
  262. package/dist/logging/components/HealthMetricsCard.d.ts +7 -0
  263. package/dist/logging/components/HealthMetricsCard.js +19 -0
  264. package/dist/logging/hooks/useAdminAnalytics.d.ts +24 -0
  265. package/dist/logging/hooks/useAdminAnalytics.js +22 -0
  266. package/dist/logging/hooks/useAuditLog.d.ts +6 -0
  267. package/dist/logging/hooks/useAuditLog.js +25 -0
  268. package/dist/logging/hooks/useErrorMetrics.d.ts +6 -0
  269. package/dist/logging/hooks/useErrorMetrics.js +38 -0
  270. package/dist/logging/hooks/useHealthMetrics.d.ts +6 -0
  271. package/dist/logging/hooks/useHealthMetrics.js +41 -0
  272. package/dist/logging/index.d.ts +11 -0
  273. package/dist/logging/index.js +40 -0
  274. package/dist/logging/types/analytics.d.ts +68 -0
  275. package/dist/logging/types/analytics.js +3 -0
  276. package/dist/logging/types/audit.d.ts +29 -0
  277. package/dist/logging/types/audit.js +2 -0
  278. package/dist/logging/types/index.d.ts +2 -0
  279. package/dist/logging/types/index.js +19 -0
  280. package/dist/middleware/auth-decision.d.ts +33 -0
  281. package/dist/middleware/auth-decision.js +65 -0
  282. package/dist/middleware/create-middleware.d.ts +100 -0
  283. package/dist/middleware/create-middleware.js +445 -0
  284. package/dist/middleware/rbac-check.d.ts +44 -0
  285. package/dist/middleware/rbac-check.js +191 -0
  286. package/dist/middleware/twofa-presets.d.ts +134 -0
  287. package/dist/middleware/twofa-presets.js +175 -0
  288. package/dist/models/DecodedAccessToken.d.ts +17 -0
  289. package/dist/models/DecodedAccessToken.js +2 -0
  290. package/dist/models/SessionModel.d.ts +122 -0
  291. package/dist/models/SessionModel.js +136 -0
  292. package/dist/pages/admin-login/page.d.ts +31 -0
  293. package/dist/pages/admin-login/page.js +83 -0
  294. package/dist/pages/admin-roles/RolesAdminPage.d.ts +15 -0
  295. package/dist/pages/admin-roles/RolesAdminPage.js +78 -0
  296. package/dist/pages/admin-roles/index.d.ts +8 -0
  297. package/dist/pages/admin-roles/index.js +15 -0
  298. package/dist/pages/admin-roles/modals.d.ts +72 -0
  299. package/dist/pages/admin-roles/modals.js +154 -0
  300. package/dist/pages/client-admin/ClientSiteAdminPage.d.ts +79 -0
  301. package/dist/pages/client-admin/ClientSiteAdminPage.js +177 -0
  302. package/dist/pages/client-admin/index.d.ts +32 -0
  303. package/dist/pages/client-admin/index.js +37 -0
  304. package/dist/pages/login/page.d.ts +22 -0
  305. package/dist/pages/login/page.js +239 -0
  306. package/dist/pages/profile/EnhancedProfilePage.d.ts +13 -0
  307. package/dist/pages/profile/EnhancedProfilePage.js +150 -0
  308. package/dist/pages/profile/index.d.ts +8 -0
  309. package/dist/pages/profile/index.js +16 -0
  310. package/dist/pages/profile/page.d.ts +19 -0
  311. package/dist/pages/profile/page.js +47 -0
  312. package/dist/pages/profile/profile-patch.d.ts +1 -0
  313. package/dist/pages/profile/profile-patch.js +281 -0
  314. package/dist/pages/recovery/page.d.ts +1 -0
  315. package/dist/pages/recovery/page.js +142 -0
  316. package/dist/pages/roles/MyRolesPage.d.ts +24 -0
  317. package/dist/pages/roles/MyRolesPage.js +71 -0
  318. package/dist/pages/roles/components.d.ts +63 -0
  319. package/dist/pages/roles/components.js +108 -0
  320. package/dist/pages/roles/index.d.ts +8 -0
  321. package/dist/pages/roles/index.js +19 -0
  322. package/dist/pages/security/EnhancedSecurityPage.d.ts +14 -0
  323. package/dist/pages/security/EnhancedSecurityPage.js +248 -0
  324. package/dist/pages/security/index.d.ts +8 -0
  325. package/dist/pages/security/index.js +16 -0
  326. package/dist/pages/security/page.d.ts +21 -0
  327. package/dist/pages/security/page.js +212 -0
  328. package/dist/pages/security/security-patch.d.ts +1 -0
  329. package/dist/pages/security/security-patch.js +302 -0
  330. package/dist/pages/settings/EnhancedSettingsPage.d.ts +46 -0
  331. package/dist/pages/settings/EnhancedSettingsPage.js +231 -0
  332. package/dist/pages/settings/index.d.ts +8 -0
  333. package/dist/pages/settings/index.js +16 -0
  334. package/dist/pages/settings/page.d.ts +7 -0
  335. package/dist/pages/settings/page.js +26 -0
  336. package/dist/pages/showcase/ShowcasePage.d.ts +13 -0
  337. package/dist/pages/showcase/ShowcasePage.js +140 -0
  338. package/dist/pages/showcase/index.d.ts +12 -0
  339. package/dist/pages/showcase/index.js +17 -0
  340. package/dist/pages/test-env/EmergencyLogoutPage.d.ts +14 -0
  341. package/dist/pages/test-env/EmergencyLogoutPage.js +98 -0
  342. package/dist/pages/test-env/JwtInspectPage.d.ts +14 -0
  343. package/dist/pages/test-env/JwtInspectPage.js +114 -0
  344. package/dist/pages/test-env/RefreshTokenPage.d.ts +15 -0
  345. package/dist/pages/test-env/RefreshTokenPage.js +91 -0
  346. package/dist/pages/test-env/TestEnvPage.d.ts +13 -0
  347. package/dist/pages/test-env/TestEnvPage.js +49 -0
  348. package/dist/pages/test-env/index.d.ts +24 -0
  349. package/dist/pages/test-env/index.js +32 -0
  350. package/dist/pages/verify-code/page.d.ts +30 -0
  351. package/dist/pages/verify-code/page.js +408 -0
  352. package/dist/routes/account/index.d.ts +28 -0
  353. package/dist/routes/account/index.js +71 -0
  354. package/dist/routes/account/masked-info.d.ts +33 -0
  355. package/dist/routes/account/masked-info.js +39 -0
  356. package/dist/routes/account/send-code.d.ts +37 -0
  357. package/dist/routes/account/send-code.js +42 -0
  358. package/dist/routes/account/update-phone.d.ts +13 -0
  359. package/dist/routes/account/update-phone.js +17 -0
  360. package/dist/routes/account/verify-email.d.ts +38 -0
  361. package/dist/routes/account/verify-email.js +43 -0
  362. package/dist/routes/account/verify-sms.d.ts +38 -0
  363. package/dist/routes/account/verify-sms.js +43 -0
  364. package/dist/routes/auth/index.d.ts +19 -0
  365. package/dist/routes/auth/index.js +64 -0
  366. package/dist/routes/auth/logout.d.ts +31 -0
  367. package/dist/routes/auth/logout.js +113 -0
  368. package/dist/routes/auth/nextauth.d.ts +19 -0
  369. package/dist/routes/auth/nextauth.js +72 -0
  370. package/dist/routes/auth/refresh.d.ts +30 -0
  371. package/dist/routes/auth/refresh.js +51 -0
  372. package/dist/routes/auth/session.d.ts +72 -0
  373. package/dist/routes/auth/session.js +180 -0
  374. package/dist/routes/auth/settings.d.ts +25 -0
  375. package/dist/routes/auth/settings.js +55 -0
  376. package/dist/routes/auth/viability.d.ts +52 -0
  377. package/dist/routes/auth/viability.js +201 -0
  378. package/dist/routes/index.d.ts +12 -0
  379. package/dist/routes/index.js +54 -0
  380. package/dist/routes/session/index.d.ts +6 -0
  381. package/dist/routes/session/index.js +10 -0
  382. package/dist/routes/session/refresh-viability.d.ts +16 -0
  383. package/dist/routes/session/refresh-viability.js +20 -0
  384. package/dist/services/signalrActivityService.d.ts +44 -0
  385. package/dist/services/signalrActivityService.js +257 -0
  386. package/dist/stores/authStore.d.ts +154 -0
  387. package/dist/stores/authStore.js +1531 -0
  388. package/dist/theme/ThemeProvider.d.ts +14 -0
  389. package/dist/theme/ThemeProvider.js +28 -0
  390. package/dist/theme/default.d.ts +8 -0
  391. package/dist/theme/default.js +33 -0
  392. package/dist/theme/index.d.ts +15 -0
  393. package/dist/theme/index.js +25 -0
  394. package/dist/theme/types.d.ts +56 -0
  395. package/dist/theme/types.js +8 -0
  396. package/dist/theme/useTheme.d.ts +60 -0
  397. package/dist/theme/useTheme.js +63 -0
  398. package/dist/theme/utils.d.ts +13 -0
  399. package/dist/theme/utils.js +39 -0
  400. package/dist/types/api.d.ts +134 -0
  401. package/dist/types/api.js +44 -0
  402. package/dist/types/auth.d.ts +19 -0
  403. package/dist/types/auth.js +2 -0
  404. package/dist/types/logging.d.ts +42 -0
  405. package/dist/types/logging.js +2 -0
  406. package/dist/types/recovery.d.ts +48 -0
  407. package/dist/types/recovery.js +2 -0
  408. package/dist/types/security.d.ts +1 -0
  409. package/dist/types/security.js +2 -0
  410. package/dist/utils/api.d.ts +85 -0
  411. package/dist/utils/api.js +287 -0
  412. package/dist/utils/circuitBreaker.d.ts +43 -0
  413. package/dist/utils/circuitBreaker.js +91 -0
  414. package/dist/utils/error-message.d.ts +1 -0
  415. package/dist/utils/error-message.js +103 -0
  416. package/dist/utils/layout/reservedSpace.d.ts +59 -0
  417. package/dist/utils/layout/reservedSpace.js +102 -0
  418. package/dist/utils/logout.d.ts +14 -0
  419. package/dist/utils/logout.js +32 -0
  420. package/dist/vibe/client.d.ts +261 -0
  421. package/dist/vibe/client.js +445 -0
  422. package/dist/vibe/errors.d.ts +83 -0
  423. package/dist/vibe/errors.js +146 -0
  424. package/dist/vibe/generic.d.ts +234 -0
  425. package/dist/vibe/generic.js +369 -0
  426. package/dist/vibe/hooks/index.d.ts +169 -0
  427. package/dist/vibe/hooks/index.js +252 -0
  428. package/dist/vibe/index.d.ts +23 -0
  429. package/dist/vibe/index.js +67 -0
  430. package/dist/vibe/sessions.d.ts +161 -0
  431. package/dist/vibe/sessions.js +391 -0
  432. package/dist/vibe/types.d.ts +353 -0
  433. package/dist/vibe/types.js +315 -0
  434. package/package.json +855 -0
  435. package/scripts/check-internal-url-usage.sh +73 -0
  436. package/scripts/dev-broker.ps1 +35 -0
  437. package/scripts/dev-local.ps1 +45 -0
  438. package/src/api/auth-handler.ts +550 -0
  439. package/src/api/index.ts +18 -0
  440. package/src/api-handlers/account/change-password.ts +145 -0
  441. package/src/api-handlers/account/masked-info.ts +45 -0
  442. package/src/api-handlers/account/profile.ts +80 -0
  443. package/src/api-handlers/account/recovery/initiate.ts +23 -0
  444. package/src/api-handlers/account/recovery/send-code.ts +25 -0
  445. package/src/api-handlers/account/recovery/verify-code.ts +25 -0
  446. package/src/api-handlers/account/reset-password.ts +23 -0
  447. package/src/api-handlers/account/send-code.ts +76 -0
  448. package/src/api-handlers/account/update-phone.ts +79 -0
  449. package/src/api-handlers/account/validate-password.ts +118 -0
  450. package/src/api-handlers/account/verify-email.ts +125 -0
  451. package/src/api-handlers/account/verify-sms.ts +125 -0
  452. package/src/api-handlers/admin/analytics.ts +445 -0
  453. package/src/api-handlers/admin/audit.ts +225 -0
  454. package/src/api-handlers/admin/index.ts +59 -0
  455. package/src/api-handlers/admin/redis-sessions.ts +253 -0
  456. package/src/api-handlers/admin/sessions.ts +320 -0
  457. package/src/api-handlers/admin/site-logs.ts +367 -0
  458. package/src/api-handlers/admin/users.ts +244 -0
  459. package/src/api-handlers/admin/vibe-data.ts +326 -0
  460. package/src/api-handlers/anon/preferences.ts +123 -0
  461. package/src/api-handlers/auth/jwks.ts +20 -0
  462. package/src/api-handlers/auth/login.ts +240 -0
  463. package/src/api-handlers/auth/refresh.ts +687 -0
  464. package/src/api-handlers/auth/signout.ts +212 -0
  465. package/src/api-handlers/auth/status.ts +23 -0
  466. package/src/api-handlers/auth/update-session.ts +125 -0
  467. package/src/api-handlers/auth/validate.ts +44 -0
  468. package/src/api-handlers/auth/verify-code.ts +129 -0
  469. package/src/api-handlers/session/refresh-viability.ts +36 -0
  470. package/src/api-handlers/session/viability.ts +166 -0
  471. package/src/api-handlers/test/force-expire.ts +67 -0
  472. package/src/auth/auth-decision.ts +230 -0
  473. package/src/auth/auth-options.ts +237 -0
  474. package/src/auth/callbacks/index.ts +7 -0
  475. package/src/auth/callbacks/jwt.ts +382 -0
  476. package/src/auth/callbacks/session.ts +243 -0
  477. package/src/auth/callbacks/signin.ts +56 -0
  478. package/src/auth/events/index.ts +5 -0
  479. package/src/auth/events/signout.ts +33 -0
  480. package/src/auth/providers/credentials.ts +256 -0
  481. package/src/auth/providers/index.ts +6 -0
  482. package/src/auth/providers/oauth.ts +114 -0
  483. package/src/auth/route-config.ts +220 -0
  484. package/src/auth/types/auth-types.ts +555 -0
  485. package/src/auth/types/index.ts +7 -0
  486. package/src/auth/unauthenticated-routes.ts +3 -0
  487. package/src/auth/utils/idp-client.ts +444 -0
  488. package/src/auth/utils/index.ts +6 -0
  489. package/src/auth/utils/token-utils.ts +244 -0
  490. package/src/client/AuthContext.tsx +140 -0
  491. package/src/client/fetch-with-auth.ts +48 -0
  492. package/src/client/fetchWithSession.ts +21 -0
  493. package/src/client/index.ts +13 -0
  494. package/src/client/useAnonSession.ts +131 -0
  495. package/src/components/SessionSync.tsx +137 -0
  496. package/src/components/SignalRHealthCheck.tsx +131 -0
  497. package/src/components/account/UserAvatarMenu.tsx +217 -0
  498. package/src/components/account/index.ts +8 -0
  499. package/src/components/admin/AlertSettingsTab.tsx +728 -0
  500. package/src/components/admin/AnalyticsTab.tsx +703 -0
  501. package/src/components/admin/DataBrowserTab.tsx +505 -0
  502. package/src/components/admin/LoggingSettingsTab.tsx +665 -0
  503. package/src/components/admin/SessionsTab.tsx +414 -0
  504. package/src/components/admin/StatsTab.tsx +379 -0
  505. package/src/components/admin/VibeAdminContext.tsx +87 -0
  506. package/src/components/admin/VibeAdminLayout.tsx +185 -0
  507. package/src/components/admin/index.ts +59 -0
  508. package/src/components/auth/FederatedAuthSection.tsx +95 -0
  509. package/src/components/auth/ModeAwareLoginPage.tsx +135 -0
  510. package/src/components/auth/ModeAwareSignupPage.tsx +267 -0
  511. package/src/components/auth/TraditionalAuthSection.tsx +99 -0
  512. package/src/components/recovery/CompleteStep.tsx +36 -0
  513. package/src/components/recovery/InitiateRecoveryStep.tsx +68 -0
  514. package/src/components/recovery/SelectMethodStep.tsx +73 -0
  515. package/src/components/recovery/SetPasswordStep.tsx +97 -0
  516. package/src/components/recovery/VerifyCodeStep.tsx +90 -0
  517. package/src/components/reserved/ReservedRecoveryWarning.tsx +160 -0
  518. package/src/components/reserved/ReservedStatusBox.tsx +118 -0
  519. package/src/components/ui/BetaBadge.tsx +58 -0
  520. package/src/components/ui/Footer.tsx +93 -0
  521. package/src/config/env.ts +57 -0
  522. package/src/config/logger.ts +62 -0
  523. package/src/config/logging-config.ts +82 -0
  524. package/src/config/unauthenticated-routes.ts +19 -0
  525. package/src/config/vibe-log-transport.ts +250 -0
  526. package/src/edge/internal-api-url.ts +65 -0
  527. package/src/edge/middleware.ts +42 -0
  528. package/src/hooks/useAuth.ts +115 -0
  529. package/src/hooks/useAuthSettings.ts +97 -0
  530. package/src/hooks/useAvailableProviders.ts +118 -0
  531. package/src/hooks/usePasswordValidation.ts +127 -0
  532. package/src/hooks/useProfile.ts +75 -0
  533. package/src/hooks/usePublicAuthSettings.ts +149 -0
  534. package/src/hooks/useSessionExpiration.ts +102 -0
  535. package/src/hooks/useViabilitySession.ts +335 -0
  536. package/src/index.ts +63 -0
  537. package/src/lib/anon-session.ts +213 -0
  538. package/src/lib/api-handler.ts +625 -0
  539. package/src/lib/app-slug.ts +178 -0
  540. package/src/lib/demo-mode.ts +13 -0
  541. package/src/lib/geolocation.ts +265 -0
  542. package/src/lib/idp-client-config.ts +442 -0
  543. package/src/lib/idp-fetch.ts +101 -0
  544. package/src/lib/internal-api.ts +171 -0
  545. package/src/lib/jwt-decode-client.ts +45 -0
  546. package/src/lib/jwt-decode.ts +83 -0
  547. package/src/lib/nextauth-secret.ts +126 -0
  548. package/src/lib/rate-limit-service.ts +9 -0
  549. package/src/lib/redis.ts +27 -0
  550. package/src/lib/refresh-token-validator.ts +64 -0
  551. package/src/lib/roles.ts +177 -0
  552. package/src/lib/secret-validation.ts +8 -0
  553. package/src/lib/session-store.ts +637 -0
  554. package/src/lib/session.ts +34 -0
  555. package/src/lib/site-logger.ts +245 -0
  556. package/src/lib/standardized-client-api.ts +896 -0
  557. package/src/lib/startup-init.ts +247 -0
  558. package/src/lib/test-aware-get-token.ts +30 -0
  559. package/src/lib/token-expiry.ts +40 -0
  560. package/src/lib/token-lifecycle.ts +477 -0
  561. package/src/lib/types/api-responses.ts +336 -0
  562. package/src/lib/user-agent-parser.ts +252 -0
  563. package/src/logging/api/admin-analytics.ts +51 -0
  564. package/src/logging/api/audit-log.ts +53 -0
  565. package/src/logging/components/AdminAnalyticsLayout.tsx +49 -0
  566. package/src/logging/components/AuditLogViewer.tsx +125 -0
  567. package/src/logging/components/ErrorMetricsCard.tsx +98 -0
  568. package/src/logging/components/HealthMetricsCard.tsx +70 -0
  569. package/src/logging/hooks/useAdminAnalytics.ts +22 -0
  570. package/src/logging/hooks/useAuditLog.ts +24 -0
  571. package/src/logging/hooks/useErrorMetrics.ts +40 -0
  572. package/src/logging/hooks/useHealthMetrics.ts +44 -0
  573. package/src/logging/index.ts +18 -0
  574. package/src/logging/types/analytics.ts +81 -0
  575. package/src/logging/types/audit.ts +31 -0
  576. package/src/logging/types/index.ts +3 -0
  577. package/src/middleware/auth-decision.ts +43 -0
  578. package/src/middleware/create-middleware.ts +626 -0
  579. package/src/middleware/rbac-check.ts +244 -0
  580. package/src/middleware/twofa-presets.ts +224 -0
  581. package/src/models/DecodedAccessToken.ts +17 -0
  582. package/src/models/SessionModel.ts +258 -0
  583. package/src/pages/admin-login/page.tsx +229 -0
  584. package/src/pages/admin-roles/RolesAdminPage.tsx +357 -0
  585. package/src/pages/admin-roles/index.ts +9 -0
  586. package/src/pages/admin-roles/modals.tsx +469 -0
  587. package/src/pages/client-admin/ClientSiteAdminPage.tsx +380 -0
  588. package/src/pages/client-admin/index.ts +33 -0
  589. package/src/pages/login/page.tsx +463 -0
  590. package/src/pages/profile/EnhancedProfilePage.tsx +479 -0
  591. package/src/pages/profile/index.ts +9 -0
  592. package/src/pages/profile/page.tsx +166 -0
  593. package/src/pages/recovery/page.tsx +234 -0
  594. package/src/pages/roles/MyRolesPage.tsx +211 -0
  595. package/src/pages/roles/components.tsx +294 -0
  596. package/src/pages/roles/index.ts +17 -0
  597. package/src/pages/security/EnhancedSecurityPage.tsx +574 -0
  598. package/src/pages/security/index.ts +9 -0
  599. package/src/pages/security/page.tsx +507 -0
  600. package/src/pages/settings/EnhancedSettingsPage.tsx +642 -0
  601. package/src/pages/settings/index.ts +9 -0
  602. package/src/pages/settings/page.tsx +47 -0
  603. package/src/pages/showcase/ShowcasePage.tsx +530 -0
  604. package/src/pages/showcase/index.ts +13 -0
  605. package/src/pages/test-env/EmergencyLogoutPage.tsx +179 -0
  606. package/src/pages/test-env/JwtInspectPage.tsx +418 -0
  607. package/src/pages/test-env/RefreshTokenPage.tsx +155 -0
  608. package/src/pages/test-env/TestEnvPage.tsx +116 -0
  609. package/src/pages/test-env/index.ts +25 -0
  610. package/src/pages/verify-code/page.tsx +648 -0
  611. package/src/routes/account/index.ts +32 -0
  612. package/src/routes/account/masked-info.ts +37 -0
  613. package/src/routes/account/send-code.ts +40 -0
  614. package/src/routes/account/update-phone.ts +13 -0
  615. package/src/routes/account/verify-email.ts +41 -0
  616. package/src/routes/account/verify-sms.ts +41 -0
  617. package/src/routes/auth/index.ts +23 -0
  618. package/src/routes/auth/logout.ts +127 -0
  619. package/src/routes/auth/nextauth.ts +71 -0
  620. package/src/routes/auth/refresh.ts +54 -0
  621. package/src/routes/auth/session.ts +193 -0
  622. package/src/routes/auth/settings.ts +75 -0
  623. package/src/routes/auth/viability.ts +220 -0
  624. package/src/routes/index.ts +18 -0
  625. package/src/routes/session/index.ts +7 -0
  626. package/src/routes/session/refresh-viability.ts +17 -0
  627. package/src/services/signalrActivityService.ts +258 -0
  628. package/src/stores/authStore.ts +1904 -0
  629. package/src/templates/instrumentation.ts +41 -0
  630. package/src/theme/ThemeProvider.tsx +39 -0
  631. package/src/theme/default.ts +33 -0
  632. package/src/theme/index.ts +31 -0
  633. package/src/theme/types.ts +69 -0
  634. package/src/theme/useTheme.ts +57 -0
  635. package/src/theme/utils.ts +40 -0
  636. package/src/types/api.ts +13 -0
  637. package/src/types/auth.d.ts +15 -0
  638. package/src/types/auth.ts +22 -0
  639. package/src/types/logging.ts +11 -0
  640. package/src/types/next-auth.d.ts +15 -0
  641. package/src/types/recovery.ts +54 -0
  642. package/src/types/security.ts +1 -0
  643. package/src/utils/api.ts +353 -0
  644. package/src/utils/circuitBreaker.ts +40 -0
  645. package/src/utils/error-message.ts +108 -0
  646. package/src/utils/layout/reservedSpace.ts +124 -0
  647. package/src/utils/logout.ts +30 -0
  648. package/src/vibe/client.ts +590 -0
  649. package/src/vibe/errors.ts +185 -0
  650. package/src/vibe/generic.ts +429 -0
  651. package/src/vibe/hooks/index.ts +367 -0
  652. package/src/vibe/index.ts +121 -0
  653. package/src/vibe/sessions.ts +551 -0
  654. package/src/vibe/types.ts +577 -0
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ /**
3
+ * Token Lifecycle Management for @payez/next-mvp
4
+ *
5
+ * Ensures tokens are fresh before making API calls.
6
+ * Checks expiration and triggers refresh if needed.
7
+ *
8
+ * Pattern: Check first, refresh if needed, fail gracefully if refresh fails.
9
+ *
10
+ * HANDLES CONCURRENT REFRESH: When multiple API calls arrive simultaneously
11
+ * with expired tokens, only one will actually perform the refresh. Others
12
+ * receive 409 (conflict) and wait for the refresh to complete, then use
13
+ * the freshly refreshed tokens.
14
+ *
15
+ * REQUIRED: Your app must expose the refresh route:
16
+ * ```typescript
17
+ * // app/api/auth/refresh/route.ts
18
+ * export { POST } from '@payez/next-mvp/routes/auth/refresh';
19
+ * ```
20
+ *
21
+ * @version 2.0.0
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.ensureFreshToken = ensureFreshToken;
25
+ exports.getFreshAuthHeader = getFreshAuthHeader;
26
+ const jwt_1 = require("next-auth/jwt");
27
+ const session_store_1 = require("./session-store");
28
+ const app_slug_1 = require("./app-slug");
29
+ const idp_client_config_1 = require("./idp-client-config");
30
+ // 5 minute threshold for "needs refresh" - matches refresh handler pattern
31
+ const REFRESH_THRESHOLD_MS = 5 * 60 * 1000;
32
+ // Concurrent refresh handling configuration
33
+ const CONCURRENT_REFRESH_POLL_INTERVAL_MS = 200; // How often to poll session during concurrent refresh
34
+ const CONCURRENT_REFRESH_MAX_WAIT_MS = 8000; // Max time to wait for concurrent refresh to complete
35
+ const REFRESH_RETRY_DELAY_MS = 500; // Delay before retrying after failed concurrent refresh
36
+ const KEY_PROPAGATION_DELAY_MS = 150; // Delay after refresh to allow JWKS cache updates in downstream services
37
+ /**
38
+ * Check if token needs refresh based on expiration time
39
+ */
40
+ function needsRefresh(accessTokenExpires) {
41
+ if (!accessTokenExpires)
42
+ return true;
43
+ const timeUntilExpiry = accessTokenExpires - Date.now();
44
+ return timeUntilExpiry <= REFRESH_THRESHOLD_MS;
45
+ }
46
+ /**
47
+ * Helper to delay execution
48
+ */
49
+ function delay(ms) {
50
+ return new Promise(resolve => setTimeout(resolve, ms));
51
+ }
52
+ /**
53
+ * Wait for a concurrent refresh to complete by polling the session.
54
+ * Returns true if session becomes fresh, false if timeout reached.
55
+ */
56
+ async function waitForConcurrentRefresh(sessionToken, maxWaitMs = CONCURRENT_REFRESH_MAX_WAIT_MS) {
57
+ const startTime = Date.now();
58
+ while (Date.now() - startTime < maxWaitMs) {
59
+ await delay(CONCURRENT_REFRESH_POLL_INTERVAL_MS);
60
+ const sessionData = await (0, session_store_1.getSession)(sessionToken);
61
+ if (!sessionData) {
62
+ return { success: false };
63
+ }
64
+ // Check if token is now fresh
65
+ if (!needsRefresh(sessionData.idpAccessTokenExpires)) {
66
+ return { success: true, sessionData };
67
+ }
68
+ // Check if session has a new access token (even if still within threshold)
69
+ if (sessionData.idpAccessToken && sessionData.idpAccessTokenExpires &&
70
+ sessionData.idpAccessTokenExpires > Date.now()) {
71
+ return { success: true, sessionData };
72
+ }
73
+ }
74
+ return { success: false };
75
+ }
76
+ /**
77
+ * Get the internal API URL for making internal service calls.
78
+ * INTERNAL_API_URL is REQUIRED - no fallbacks.
79
+ */
80
+ function getInternalApiUrl(request) {
81
+ const internalUrl = process.env.INTERNAL_API_URL;
82
+ if (!internalUrl) {
83
+ throw new Error('[INTERNAL_API_URL] FATAL: INTERNAL_API_URL environment variable is REQUIRED. ' +
84
+ 'Set it to this app\'s internal K8s service URL (e.g., http://myapp.namespace.svc.cluster.local:80) ' +
85
+ 'or http://localhost:3000 for local development.');
86
+ }
87
+ return internalUrl;
88
+ }
89
+ /**
90
+ * Trigger a token refresh via the refresh API endpoint.
91
+ *
92
+ * HANDLES CONCURRENT REFRESH (409):
93
+ * When another request is already refreshing the token, this function
94
+ * waits for that refresh to complete instead of failing immediately.
95
+ * This prevents race conditions where multiple parallel API calls
96
+ * could cause unnecessary refresh failures.
97
+ *
98
+ * TERMINAL STATES:
99
+ * Returns { success: false, terminal: true } when the session cannot be
100
+ * recovered (e.g., no refresh token). Callers should redirect to login.
101
+ */
102
+ async function triggerRefresh(request, sessionToken, retryCount = 0) {
103
+ const maxRetries = 2;
104
+ try {
105
+ const baseUrl = getInternalApiUrl(request);
106
+ const requestId = `refresh_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
107
+ const response = await fetch(`${baseUrl}/api/auth/refresh`, {
108
+ method: 'POST',
109
+ headers: {
110
+ 'Content-Type': 'application/json',
111
+ 'Cookie': request.headers.get('cookie') || '',
112
+ 'X-Session-Token': sessionToken,
113
+ 'X-Request-Id': requestId,
114
+ },
115
+ });
116
+ // Handle 409 Conflict - another refresh is in progress
117
+ if (response.status === 409) {
118
+ // Wait for the concurrent refresh to complete
119
+ const waitResult = await waitForConcurrentRefresh(sessionToken);
120
+ if (waitResult.success) {
121
+ return { success: true };
122
+ }
123
+ // Concurrent refresh didn't produce a fresh token - try again if we have retries left
124
+ if (retryCount < maxRetries) {
125
+ await delay(REFRESH_RETRY_DELAY_MS);
126
+ return triggerRefresh(request, sessionToken, retryCount + 1);
127
+ }
128
+ return { success: false };
129
+ }
130
+ // Handle other non-OK responses
131
+ if (!response.ok) {
132
+ // Parse response body to check for terminal errors
133
+ let responseData = {};
134
+ try {
135
+ responseData = await response.json();
136
+ }
137
+ catch {
138
+ // Ignore parse errors
139
+ }
140
+ // Log the failure for debugging
141
+ console.warn('[TOKEN_LIFECYCLE] Refresh request failed:', {
142
+ status: response.status,
143
+ statusText: response.statusText,
144
+ baseUrl,
145
+ retryCount,
146
+ code: responseData.code,
147
+ terminal: responseData.terminal
148
+ });
149
+ // CHECK FOR TERMINAL STATE: No refresh token = session is dead
150
+ // Don't retry - user must re-authenticate
151
+ if (responseData.code === 'NO_REFRESH_TOKEN' || responseData.terminal === true) {
152
+ console.error('[TOKEN_LIFECYCLE] TERMINAL: Session has no refresh token - user must re-login');
153
+ return { success: false, terminal: true, code: responseData.code };
154
+ }
155
+ // For other 401s, check if maybe session was refreshed by another request
156
+ if (response.status === 401 && retryCount < maxRetries) {
157
+ await delay(REFRESH_RETRY_DELAY_MS);
158
+ const sessionData = await (0, session_store_1.getSession)(sessionToken);
159
+ if (sessionData && !needsRefresh(sessionData.idpAccessTokenExpires)) {
160
+ return { success: true };
161
+ }
162
+ }
163
+ return { success: false, code: responseData.code };
164
+ }
165
+ const result = await response.json();
166
+ const success = result.refreshed === true || result.reason === 'already_fresh';
167
+ return { success };
168
+ }
169
+ catch (error) {
170
+ // Log network errors for debugging
171
+ console.error('[TOKEN_LIFECYCLE] Refresh network error:', {
172
+ error: error instanceof Error ? error.message : String(error),
173
+ retryCount
174
+ });
175
+ // On network error, check if maybe another request refreshed the token
176
+ if (retryCount < maxRetries) {
177
+ await delay(REFRESH_RETRY_DELAY_MS);
178
+ const sessionData = await (0, session_store_1.getSession)(sessionToken);
179
+ if (sessionData && !needsRefresh(sessionData.idpAccessTokenExpires)) {
180
+ return { success: true };
181
+ }
182
+ }
183
+ return { success: false };
184
+ }
185
+ }
186
+ /**
187
+ * Ensures we have a fresh access token before making API calls.
188
+ *
189
+ * This utility checks token expiration and triggers a refresh if needed,
190
+ * preventing 401 errors from expired tokens being sent to downstream APIs.
191
+ *
192
+ * @param request - The incoming NextRequest
193
+ * @returns TokenResult with accessToken and sessionData, or TokenError
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * import { ensureFreshToken } from '@payez/next-mvp/lib/token-lifecycle';
198
+ *
199
+ * export async function GET(request: NextRequest) {
200
+ * const tokenResult = await ensureFreshToken(request);
201
+ * if (!tokenResult.success) {
202
+ * return NextResponse.json({ error: tokenResult.error }, { status: 401 });
203
+ * }
204
+ *
205
+ * // Use tokenResult.accessToken for downstream API calls
206
+ * const response = await fetch('https://api.example.com/data', {
207
+ * headers: { 'Authorization': `Bearer ${tokenResult.accessToken}` }
208
+ * });
209
+ * }
210
+ * ```
211
+ */
212
+ /**
213
+ * Get NextAuth secret from IDP config (cached).
214
+ * NEVER use process.env.NEXTAUTH_SECRET directly - it may not be set.
215
+ */
216
+ async function getNextAuthSecret() {
217
+ const config = await (0, idp_client_config_1.getIDPClientConfig)();
218
+ return config.nextAuthSecret || '';
219
+ }
220
+ async function ensureFreshToken(request) {
221
+ try {
222
+ // 1. Get NextAuth JWT to extract sessionToken
223
+ // Use IDP config to get the secret (same as viability.ts)
224
+ const secret = await getNextAuthSecret();
225
+ if (!secret) {
226
+ console.error('[TOKEN_LIFECYCLE] NEXTAUTH_SECRET not available from IDP config');
227
+ return { success: false, error: 'NO_SESSION', message: 'Auth not configured' };
228
+ }
229
+ const cookieName = (0, app_slug_1.getJwtCookieName)();
230
+ const token = await (0, jwt_1.getToken)({
231
+ req: request,
232
+ secret,
233
+ cookieName,
234
+ });
235
+ // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
236
+ const sessionTokenFromJwt = (token?.sessionToken || token?.redisSessionId);
237
+ if (!sessionTokenFromJwt) {
238
+ // Debug: log what we got including cookie presence and value info
239
+ const cookieHeader = request.headers.get('cookie') || '';
240
+ const hasCookie = cookieHeader.includes(cookieName);
241
+ // Extract the actual cookie value to check if it's empty
242
+ const cookieMatch = cookieHeader.match(new RegExp(`${cookieName}=([^;]*)`));
243
+ const cookieValue = cookieMatch ? cookieMatch[1] : null;
244
+ const cookieValueLength = cookieValue?.length || 0;
245
+ console.warn('[TOKEN_LIFECYCLE] NO_SESSION -', {
246
+ token: token ? 'exists but no sessionToken/redisSessionId' : 'null',
247
+ cookieName,
248
+ hasCookie,
249
+ cookieValueLength,
250
+ cookieValuePreview: cookieValue ? cookieValue.substring(0, 20) + '...' : 'EMPTY',
251
+ cookieHeaderLength: cookieHeader.length,
252
+ secretLength: secret.length,
253
+ });
254
+ return {
255
+ success: false,
256
+ error: 'NO_SESSION',
257
+ message: 'No session available',
258
+ };
259
+ }
260
+ const sessionToken = sessionTokenFromJwt;
261
+ // 2. Get session data from Redis
262
+ let sessionData = await (0, session_store_1.getSession)(sessionToken);
263
+ if (!sessionData) {
264
+ return {
265
+ success: false,
266
+ error: 'NO_SESSION',
267
+ message: 'Session expired or not found',
268
+ };
269
+ }
270
+ // DEBUG: Log session data before refresh check
271
+ const tokenExpiresStr = sessionData.idpAccessTokenExpires
272
+ ? new Date(sessionData.idpAccessTokenExpires).toISOString()
273
+ : 'undefined';
274
+ let needsRefreshNow = needsRefresh(sessionData.idpAccessTokenExpires);
275
+ // VALIDATION: Check if the actual JWT token's exp matches what Redis claims
276
+ // This catches cases where accessTokenExpires was updated but accessToken wasn't
277
+ let tokenMismatch = false;
278
+ if (sessionData.idpAccessToken && !needsRefreshNow) {
279
+ try {
280
+ const tokenParts = sessionData.idpAccessToken.split('.');
281
+ if (tokenParts.length === 3) {
282
+ const payload = JSON.parse(Buffer.from(tokenParts[1], 'base64url').toString());
283
+ const jwtExpMs = (payload.exp || 0) * 1000;
284
+ const now = Date.now();
285
+ // If the JWT is actually expired, force a refresh regardless of what Redis says
286
+ if (jwtExpMs < now) {
287
+ console.warn('[TOKEN_LIFECYCLE] Token mismatch detected! JWT expired but Redis claims valid', {
288
+ jwtExp: new Date(jwtExpMs).toISOString(),
289
+ redisAccessTokenExpires: tokenExpiresStr,
290
+ now: new Date(now).toISOString(),
291
+ mismatchMs: sessionData.idpAccessTokenExpires ? sessionData.idpAccessTokenExpires - jwtExpMs : 'N/A'
292
+ });
293
+ needsRefreshNow = true;
294
+ tokenMismatch = true;
295
+ }
296
+ }
297
+ }
298
+ catch (e) {
299
+ // If we can't decode, proceed with normal logic
300
+ console.warn('[TOKEN_LIFECYCLE] Could not validate JWT exp claim:', e);
301
+ }
302
+ }
303
+ console.log('[TOKEN_LIFECYCLE] ensureFreshToken check:', {
304
+ sessionToken: sessionToken.substring(0, 8) + '...',
305
+ accessTokenExpires: tokenExpiresStr,
306
+ now: new Date().toISOString(),
307
+ needsRefresh: needsRefreshNow,
308
+ tokenMismatch,
309
+ hasRefreshToken: !!sessionData.idpRefreshToken
310
+ });
311
+ // 3. Check if token needs refresh
312
+ if (needsRefreshNow) {
313
+ // 4. Trigger refresh
314
+ console.log('[TOKEN_LIFECYCLE] Triggering refresh...');
315
+ const refreshResult = await triggerRefresh(request, sessionToken);
316
+ if (!refreshResult.success) {
317
+ // Check for terminal state - session cannot be recovered
318
+ if (refreshResult.terminal) {
319
+ console.error('[TOKEN_LIFECYCLE] TERMINAL: Session expired with no refresh token - redirect to login');
320
+ return {
321
+ success: false,
322
+ error: 'SESSION_EXPIRED_NO_REFRESH',
323
+ message: 'Session expired. Please sign in again.',
324
+ terminal: true,
325
+ };
326
+ }
327
+ console.warn('[TOKEN_LIFECYCLE] Refresh failed');
328
+ return {
329
+ success: false,
330
+ error: 'REFRESH_FAILED',
331
+ message: 'Token refresh failed',
332
+ };
333
+ }
334
+ // 5. Re-fetch session data after refresh
335
+ sessionData = await (0, session_store_1.getSession)(sessionToken);
336
+ console.log('[TOKEN_LIFECYCLE] After refresh:', {
337
+ hasAccessToken: !!sessionData?.idpAccessToken,
338
+ newAccessTokenExpires: sessionData?.idpAccessTokenExpires
339
+ ? new Date(sessionData.idpAccessTokenExpires).toISOString()
340
+ : 'undefined'
341
+ });
342
+ if (!sessionData?.idpAccessToken) {
343
+ return {
344
+ success: false,
345
+ error: 'REFRESH_FAILED',
346
+ message: 'No access token after refresh',
347
+ };
348
+ }
349
+ // 5.5. Key propagation delay - allow downstream services (like Vibe) to cache new JWKS
350
+ // This is critical when IDP rotates signing keys - the new token's kid may not be
351
+ // immediately available in Vibe's JWKS cache
352
+ await delay(KEY_PROPAGATION_DELAY_MS);
353
+ }
354
+ // 6. Validate we have a token
355
+ if (!sessionData.idpAccessToken) {
356
+ return {
357
+ success: false,
358
+ error: 'NO_TOKEN',
359
+ message: 'No access token available',
360
+ };
361
+ }
362
+ return {
363
+ success: true,
364
+ accessToken: sessionData.idpAccessToken,
365
+ sessionData,
366
+ };
367
+ }
368
+ catch (error) {
369
+ console.error('[TOKEN_LIFECYCLE] Error:', error);
370
+ return {
371
+ success: false,
372
+ error: 'NO_SESSION',
373
+ message: error instanceof Error ? error.message : 'Unknown error',
374
+ };
375
+ }
376
+ }
377
+ /**
378
+ * Get authorization header from fresh token.
379
+ * Convenience wrapper for API routes.
380
+ *
381
+ * @param request - The incoming NextRequest
382
+ * @returns Authorization header string or null if token unavailable
383
+ *
384
+ * @example
385
+ * ```typescript
386
+ * const authHeader = await getFreshAuthHeader(request);
387
+ * if (!authHeader) {
388
+ * return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
389
+ * }
390
+ * ```
391
+ */
392
+ async function getFreshAuthHeader(request) {
393
+ const result = await ensureFreshToken(request);
394
+ if (!result.success) {
395
+ return null;
396
+ }
397
+ return `Bearer ${result.accessToken}`;
398
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * BASE STANDARDIZED RESPONSE FORMAT
3
+ * This is THE ONLY acceptable response format from our APIs
4
+ */
5
+ export interface StandardizedApiResponse<TData = unknown> {
6
+ /** REQUIRED: Operation success status */
7
+ success: true;
8
+ /** REQUIRED: The actual data payload */
9
+ data: TData;
10
+ /** REQUIRED: Human-readable success message */
11
+ message: string;
12
+ /** REQUIRED: Unique operation code for tracking */
13
+ operation_code: string;
14
+ /** Optional: Server timestamp */
15
+ timestamp?: string;
16
+ /** Optional: Request ID for tracing */
17
+ request_id?: string;
18
+ }
19
+ /**
20
+ * STANDARDIZED ERROR RESPONSE FORMAT
21
+ * This is THE ONLY acceptable error format from our APIs
22
+ */
23
+ export interface StandardizedErrorResponse {
24
+ /** REQUIRED: Always false for errors */
25
+ success: false;
26
+ /** REQUIRED: Standard error code */
27
+ error_code: string;
28
+ /** REQUIRED: Human-readable error message */
29
+ message: string;
30
+ /** REQUIRED: Operation that failed */
31
+ operation: string;
32
+ /** Optional: Additional error details - can be any structure from IDP */
33
+ details?: unknown;
34
+ /** Optional: Validation errors */
35
+ validation_errors?: Record<string, string[]>;
36
+ /** Optional: Server timestamp */
37
+ timestamp?: string;
38
+ /** Optional: Request ID for tracing */
39
+ request_id?: string;
40
+ }
41
+ /**
42
+ * STANDARDIZED PAGINATED RESPONSE FORMAT
43
+ * For endpoints that return paged data
44
+ */
45
+ export interface StandardizedPagedResponse<TData = unknown> {
46
+ /** REQUIRED: Always true for success */
47
+ success: true;
48
+ /** REQUIRED: Array of data items */
49
+ data: TData[];
50
+ /** REQUIRED: Human-readable success message */
51
+ message: string;
52
+ /** REQUIRED: Unique operation code */
53
+ operation_code: string;
54
+ /** REQUIRED: Pagination metadata */
55
+ pagination: {
56
+ /** Current page number (1-based) */
57
+ current_page: number;
58
+ /** Total number of pages */
59
+ total_pages: number;
60
+ /** Number of items per page */
61
+ page_size: number;
62
+ /** Total number of items across all pages */
63
+ total_items: number;
64
+ /** True if there are more pages after current */
65
+ has_next_page: boolean;
66
+ /** True if there are pages before current */
67
+ has_previous_page: boolean;
68
+ };
69
+ /** Optional: Server timestamp */
70
+ timestamp?: string;
71
+ /** Optional: Request ID for tracing */
72
+ request_id?: string;
73
+ }
74
+ /**
75
+ * VALIDATION ERROR RESPONSE FORMAT
76
+ * For input validation failures
77
+ */
78
+ export interface StandardizedValidationResponse {
79
+ /** REQUIRED: Always false for validation errors */
80
+ success: false;
81
+ /** REQUIRED: Always 'VALIDATION_ERROR' */
82
+ error_code: 'VALIDATION_ERROR';
83
+ /** REQUIRED: Summary message */
84
+ message: string;
85
+ /** REQUIRED: Operation that failed */
86
+ operation: string;
87
+ /** REQUIRED: Field-specific validation errors */
88
+ payload: {
89
+ /** Field name mapped to array of error messages */
90
+ validation_errors: Record<string, string[]>;
91
+ /** The invalid value that caused the error */
92
+ invalid_value?: unknown;
93
+ /** The field that caused the primary error */
94
+ primary_field?: string;
95
+ };
96
+ }
97
+ /** ALL POSSIBLE STANDARDIZED RESPONSES */
98
+ export type StandardizedResponse<TData = unknown> = StandardizedApiResponse<TData> | StandardizedPagedResponse<TData> | StandardizedErrorResponse | StandardizedValidationResponse;
99
+ /**
100
+ * Type guard to check if response is a success response
101
+ * THROWS if response doesn't match standardized format
102
+ */
103
+ export declare function isSuccessResponse<TData = unknown>(response: unknown): response is StandardizedApiResponse<TData>;
104
+ /**
105
+ * Type guard to check if response is a paged success response
106
+ * THROWS if response doesn't match standardized format
107
+ */
108
+ export declare function isPagedResponse<TData = unknown>(response: unknown): response is StandardizedPagedResponse<TData>;
109
+ /**
110
+ * Type guard to check if response is an error response
111
+ * THROWS if response doesn't match standardized format
112
+ */
113
+ export declare function isErrorResponse(response: unknown): response is StandardizedErrorResponse;
114
+ /**
115
+ * Type guard to check if response is a validation error
116
+ * THROWS if response doesn't match standardized format
117
+ */
118
+ export declare function isValidationErrorResponse(response: unknown): response is StandardizedValidationResponse;
119
+ /**
120
+ * VALIDATES AND NORMALIZES API RESPONSES
121
+ * This function BREAKS THE BUILD if responses don't match our standard
122
+ * NO EXCEPTIONS - ZERO TOLERANCE FOR BAD RESPONSES
123
+ */
124
+ export declare function validateStandardizedResponse<TData = unknown>(response: unknown, endpoint?: string): StandardizedResponse<TData>;
125
+ /** Extract the data type from a standardized response */
126
+ export type ExtractResponseData<T> = T extends StandardizedApiResponse<infer U> ? U : T extends StandardizedPagedResponse<infer U> ? U[] : never;
127
+ /** Extract the error code from an error response */
128
+ export type ExtractErrorCode<T> = T extends StandardizedErrorResponse ? T['error_code'] : T extends StandardizedValidationResponse ? T['error_code'] : never;