@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,75 @@
1
+ /**
2
+ * Public Auth Settings Route
3
+ *
4
+ * Returns client auth settings for pre-login pages (signup, login).
5
+ * Does NOT require authentication - these are public client settings.
6
+ */
7
+
8
+ import { NextResponse } from 'next/server';
9
+ import { getIDPClientConfig } from '../../lib/idp-client-config';
10
+
11
+ export interface PublicAuthSettings {
12
+ // OAuth providers enabled for this client
13
+ enabledProviders: string[];
14
+
15
+ // Registration settings
16
+ allowPublicRegistration: boolean;
17
+ allowSocialLogin: boolean;
18
+
19
+ // Password settings
20
+ enablePasswordReset: boolean;
21
+
22
+ // 2FA settings (public - no secrets)
23
+ require2FA: boolean;
24
+ allowed2FAMethods: string[];
25
+ }
26
+
27
+ /**
28
+ * GET /api/auth/settings
29
+ *
30
+ * Returns public auth settings for the current client.
31
+ * Used by login/signup pages to determine what options to show.
32
+ */
33
+ export async function GET() {
34
+ try {
35
+ const config = await getIDPClientConfig();
36
+
37
+ const settings: PublicAuthSettings = {
38
+ // Get enabled OAuth provider names
39
+ enabledProviders: config.oauthProviders
40
+ ?.filter(p => p.enabled)
41
+ .map(p => p.provider) ?? [],
42
+
43
+ // Registration - default to true if not specified
44
+ allowPublicRegistration: true, // Could come from config.authSettings in future
45
+ allowSocialLogin: config.oauthProviders?.some(p => p.enabled) ?? false,
46
+
47
+ // Password reset
48
+ enablePasswordReset: true, // Could come from config.authSettings in future
49
+
50
+ // 2FA
51
+ require2FA: config.authSettings?.require2FA ?? true,
52
+ allowed2FAMethods: config.authSettings?.allowed2FAMethods ?? ['email', 'sms'],
53
+ };
54
+
55
+ return NextResponse.json({
56
+ success: true,
57
+ data: settings,
58
+ });
59
+ } catch (error) {
60
+ console.error('[AUTH_SETTINGS] Failed to get settings:', error);
61
+
62
+ // Return safe defaults on error
63
+ return NextResponse.json({
64
+ success: true,
65
+ data: {
66
+ enabledProviders: [],
67
+ allowPublicRegistration: true,
68
+ allowSocialLogin: false,
69
+ enablePasswordReset: true,
70
+ require2FA: true,
71
+ allowed2FAMethods: ['email', 'sms'],
72
+ } as PublicAuthSettings,
73
+ });
74
+ }
75
+ }
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Ready-to-Use Session Viability Route
3
+ *
4
+ * Checks if the current session is viable (valid and not expired).
5
+ * Used by client-side code to determine if a refresh is needed.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/session/viability/route.ts
10
+ * export { GET } from '@payez/next-mvp/routes/auth/viability';
11
+ * ```
12
+ *
13
+ * @version 2.0.0
14
+ * @since auth-ready-v2
15
+ */
16
+
17
+ import { NextRequest, NextResponse } from 'next/server';
18
+ import { getToken } from 'next-auth/jwt';
19
+ import { getSession } from '../../lib/session-store';
20
+ import { getJwtCookieName } from '../../lib/app-slug';
21
+ import { getIDPClientConfig } from '../../lib/idp-client-config';
22
+
23
+ /**
24
+ * Get NextAuth secret from IDP config (cached).
25
+ * NEVER use process.env.NEXTAUTH_SECRET at module level - it may not be set yet.
26
+ */
27
+ async function getNextAuthSecret(): Promise<string> {
28
+ const config = await getIDPClientConfig();
29
+ return config.nextAuthSecret || '';
30
+ }
31
+
32
+ /**
33
+ * Get tenant-wide 2FA requirement from cached client config (from broker handshake)
34
+ */
35
+ async function getTenantRequiresTwoFactor(): Promise<boolean> {
36
+ try {
37
+ const config = await getIDPClientConfig();
38
+ return config.authSettings?.require2FA ?? true; // Default to true for security
39
+ } catch {
40
+ console.warn('[VIABILITY] Could not get client config, defaulting tenantRequiresTwoFactor to true');
41
+ return true;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * GET /api/session/viability - Check if session is viable
47
+ *
48
+ * Returns:
49
+ * - viable: boolean - Whether the session can be used
50
+ * - needsRefresh: boolean - Whether a refresh is recommended
51
+ * - expiresIn: number - Seconds until token expires
52
+ */
53
+ export async function GET(req: NextRequest) {
54
+ try {
55
+ const cookieName = getJwtCookieName();
56
+ const secret = await getNextAuthSecret();
57
+ const token = await getToken({ req, secret, cookieName });
58
+
59
+ if (!token) {
60
+ return NextResponse.json({
61
+ viable: false,
62
+ needsRefresh: false,
63
+ authenticated: false,
64
+ reason: 'No session found'
65
+ });
66
+ }
67
+
68
+ // Support both field names: sessionToken (auth.ts JWT) and redisSessionId (legacy)
69
+ const sessionToken = (token as any).sessionToken || (token as any).redisSessionId;
70
+ const session = sessionToken ? await getSession(sessionToken) : null;
71
+
72
+ // CRITICAL: Detect stale cookie state (JWT exists but Redis session missing)
73
+ if (sessionToken && !session) {
74
+ console.warn('[VIABILITY] Stale cookie detected - session not in Redis');
75
+ return NextResponse.json({
76
+ viable: false,
77
+ needsRefresh: false,
78
+ authenticated: false,
79
+ sessionToken, // Return sessionToken so middleware can detect and clear stale cookie
80
+ reason: 'Stale session - cookie exists but session not found in Redis'
81
+ });
82
+ }
83
+
84
+ // Check access token expiry
85
+ const now = Math.floor(Date.now() / 1000);
86
+ const accessTokenExpires = (token as any).accessTokenExpires || token.exp;
87
+
88
+ if (!accessTokenExpires) {
89
+ // No expiry info, assume viable but recommend refresh
90
+ const tenantRequiresTwoFactor = await getTenantRequiresTwoFactor();
91
+
92
+ // CRITICAL: Check if MFA has expired (2FA TTL enforcement)
93
+ const mfaExpiresAt = session?.mfaExpiresAt || 0;
94
+ const mfaExpired = mfaExpiresAt > 0 && mfaExpiresAt < Date.now();
95
+ // Check mfaVerified (normalized name) with fallback to twoFactorComplete for compatibility
96
+ const mfaVerifiedInSession = session?.mfaVerified ?? (session as any)?.twoFactorComplete ?? false;
97
+
98
+ // User has completed 2FA requirements if: they verified AND it hasn't expired
99
+ const userHasCompletedTenantTwoFactorRequirements = mfaVerifiedInSession && !mfaExpired;
100
+
101
+ // userStillNeedsTwoFactor = inverse of completed (matches session callback logic)
102
+ const userStillNeedsTwoFactor = !userHasCompletedTenantTwoFactorRequirements;
103
+
104
+ return NextResponse.json({
105
+ viable: true,
106
+ needsRefresh: true,
107
+ authenticated: true,
108
+ sessionToken,
109
+ // Clear names for middleware decision-making
110
+ tenantRequiresTwoFactor,
111
+ userHasCompletedTenantTwoFactorRequirements,
112
+ userStillNeedsTwoFactor,
113
+ // Legacy field names for backwards compatibility
114
+ requires2FA: tenantRequiresTwoFactor,
115
+ twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
116
+ accessTokenExpired: false,
117
+ reason: 'No expiry information'
118
+ });
119
+ }
120
+
121
+ // Convert to seconds if needed
122
+ const expiryTime = accessTokenExpires > 1000000000000
123
+ ? Math.floor(accessTokenExpires / 1000)
124
+ : accessTokenExpires;
125
+
126
+ const expiresIn = expiryTime - now;
127
+ const isExpired = expiresIn <= 0;
128
+ const needsRefresh = expiresIn <= 300; // 5 minutes buffer
129
+
130
+ // Check if we have refresh capability (check normalized field name first)
131
+ const hasRefreshToken = !!(session?.idpRefreshToken || (session as any)?.refreshToken || (token as any).refreshToken);
132
+
133
+ // CLEAR NAMING: Tenant-wide 2FA requirement from client config
134
+ const tenantRequiresTwoFactor = await getTenantRequiresTwoFactor();
135
+
136
+ // CRITICAL: Check if MFA has expired (2FA TTL enforcement)
137
+ // The session may have mfaVerified=true from days ago, but if mfaExpiresAt
138
+ // has passed, we must treat 2FA as incomplete to force re-verification.
139
+ const mfaExpiresAt = session?.mfaExpiresAt || 0;
140
+ const mfaExpired = mfaExpiresAt > 0 && mfaExpiresAt < Date.now();
141
+ // Check mfaVerified (normalized name) with fallback to twoFactorComplete for compatibility
142
+ const mfaVerifiedInSession = session?.mfaVerified ?? (session as any)?.twoFactorComplete ?? false;
143
+
144
+ // DEBUG: Log what we're reading from the session
145
+ console.log('[VIABILITY] Session 2FA state:', {
146
+ sessionToken: sessionToken?.substring(0, 8) + '...',
147
+ 'session.mfaVerified': session?.mfaVerified,
148
+ 'session.twoFactorComplete': (session as any)?.twoFactorComplete,
149
+ mfaVerifiedInSession,
150
+ mfaExpiresAt,
151
+ mfaExpired,
152
+ hasRefreshToken,
153
+ 'session.idpRefreshToken': !!session?.idpRefreshToken,
154
+ 'session.refreshToken': !!(session as any)?.refreshToken,
155
+ });
156
+
157
+ // CLEAR NAMING: User has completed 2FA requirements if: they verified AND it hasn't expired
158
+ const userHasCompletedTenantTwoFactorRequirements = mfaVerifiedInSession && !mfaExpired;
159
+
160
+ // userStillNeedsTwoFactor = inverse of completed (matches session callback logic)
161
+ const userStillNeedsTwoFactor = !userHasCompletedTenantTwoFactorRequirements;
162
+
163
+ if (mfaExpired && mfaVerifiedInSession) {
164
+ console.warn('[VIABILITY] MFA expired - forcing 2FA re-verification');
165
+ }
166
+
167
+ if (isExpired) {
168
+ return NextResponse.json({
169
+ viable: false,
170
+ needsRefresh: hasRefreshToken,
171
+ expiresIn: 0,
172
+ hasRefreshToken,
173
+ authenticated: true,
174
+ sessionToken,
175
+ // Clear names
176
+ tenantRequiresTwoFactor,
177
+ userHasCompletedTenantTwoFactorRequirements,
178
+ userStillNeedsTwoFactor,
179
+ // Legacy names for backwards compatibility
180
+ requires2FA: tenantRequiresTwoFactor,
181
+ twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
182
+ accessTokenExpired: true,
183
+ reason: 'Token expired',
184
+ // RBAC fields
185
+ roles: session?.roles || [],
186
+ clientId: session?.idpClientId || process.env.IDP_CLIENT_ID || '',
187
+ });
188
+ }
189
+
190
+ return NextResponse.json({
191
+ viable: true,
192
+ needsRefresh,
193
+ expiresIn,
194
+ hasRefreshToken,
195
+ authenticated: true,
196
+ sessionToken,
197
+ // Clear names
198
+ tenantRequiresTwoFactor,
199
+ userHasCompletedTenantTwoFactorRequirements,
200
+ userStillNeedsTwoFactor,
201
+ // Legacy names for backwards compatibility
202
+ requires2FA: tenantRequiresTwoFactor,
203
+ twoFactorComplete: userHasCompletedTenantTwoFactorRequirements,
204
+ accessTokenExpired: false,
205
+ expiresAt: new Date(expiryTime * 1000).toISOString(),
206
+ // RBAC fields
207
+ roles: session?.roles || [],
208
+ clientId: session?.idpClientId || process.env.IDP_CLIENT_ID || '',
209
+ });
210
+ } catch (error) {
211
+ console.error('[VIABILITY_ROUTE] Error checking session viability:', error);
212
+ return NextResponse.json({
213
+ viable: false,
214
+ needsRefresh: false,
215
+ authenticated: false,
216
+ error: 'Failed to check session',
217
+ details: error instanceof Error ? error.message : 'Unknown error'
218
+ }, { status: 500 });
219
+ }
220
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @payez/next-mvp Route Module Exports
3
+ *
4
+ * Ready-to-use route handlers for quick integration
5
+ *
6
+ * @version 2.3.0
7
+ * @since auth-ready-v2
8
+ */
9
+
10
+ // Export auth routes
11
+ export * from './auth';
12
+
13
+ // Export account/2FA routes
14
+ export * from './account';
15
+
16
+ // Namespace exports for cleaner imports
17
+ export * as auth from './auth';
18
+ export * as account from './account';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Session Routes Index
3
+ *
4
+ * Re-exports all session-related route handlers for easy importing.
5
+ */
6
+
7
+ export { GET as refreshViabilityGET } from './refresh-viability';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Ready-to-Use Refresh Viability Route
3
+ *
4
+ * Checks if a session has a valid refresh token for automatic refresh.
5
+ * Used by middleware to decide whether to attempt refresh or redirect to login.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // app/api/session/refresh-viability/route.ts
10
+ * export { GET } from '@payez/next-mvp/routes/session/refresh-viability';
11
+ * ```
12
+ *
13
+ * @version 2.0.0
14
+ * @since auth-ready-v2
15
+ */
16
+
17
+ export { GET } from '../../api-handlers/session/refresh-viability';
@@ -0,0 +1,258 @@
1
+ import * as signalR from '@microsoft/signalr';
2
+
3
+ export interface HealthStatus {
4
+ isHealthy: boolean;
5
+ message: string;
6
+ lastHeartbeat: Date | null;
7
+ connectionId: string | null | undefined;
8
+ responseTime?: string;
9
+ }
10
+
11
+ export type HealthStatusCallback = (status: HealthStatus) => void;
12
+
13
+ /**
14
+ * SignalR-based health service following Occam's Razor principle:
15
+ * - If SignalR connection is alive = Service is working
16
+ * - If SignalR connection is dead = Service is not working
17
+ * - No complex orchestration, just connection state monitoring
18
+ */
19
+ class SignalRActivityService {
20
+ private connection: signalR.HubConnection | null = null;
21
+ private subscribers: Set<HealthStatusCallback> = new Set();
22
+ private currentStatus: HealthStatus = {
23
+ isHealthy: false,
24
+ message: 'Disconnected',
25
+ lastHeartbeat: null,
26
+ connectionId: null
27
+ };
28
+ private heartbeatTimeout: NodeJS.Timeout | null = null;
29
+ private readonly heartbeatTimeoutMs = 45000; // 45 seconds (server sends every 30s)
30
+
31
+ /**
32
+ * Start the health monitoring connection
33
+ * @param idpBaseUrl - The base URL of the IDP server (e.g., 'http://localhost:32785')
34
+ */
35
+ async start(idpBaseUrl: string): Promise<void> {
36
+ // If we already have a connected or connecting connection, don't start again
37
+ if (this.connection &&
38
+ (this.connection.state === signalR.HubConnectionState.Connected ||
39
+ this.connection.state === signalR.HubConnectionState.Connecting)) {
40
+ console.info('[SignalRHealth] Connection already active, skipping start');
41
+ return;
42
+ }
43
+
44
+ // Stop existing connection if it exists
45
+ if (this.connection) {
46
+ await this.stop();
47
+ }
48
+
49
+ try {
50
+ if (!idpBaseUrl) {
51
+ throw new Error('IDP base URL is required for health monitoring');
52
+ }
53
+
54
+ // Construct absolute hub URL safely
55
+ const activityHubUrl = new URL('/healthHub', idpBaseUrl).toString();
56
+ console.info('[SignalRHealth] Using hub URL:', activityHubUrl);
57
+
58
+ this.connection = new signalR.HubConnectionBuilder()
59
+ .withUrl(activityHubUrl, {
60
+ withCredentials: false,
61
+ transport: signalR.HttpTransportType.WebSockets | signalR.HttpTransportType.ServerSentEvents | signalR.HttpTransportType.LongPolling,
62
+ })
63
+ .withAutomaticReconnect({
64
+ nextRetryDelayInMilliseconds: (retryContext) => {
65
+ // More conservative backoff: 5s, 15s, 45s, then stop trying
66
+ const delays = [5000, 15000, 45000];
67
+ if (retryContext.previousRetryCount >= delays.length) {
68
+ return null; // Stop automatic reconnection
69
+ }
70
+ return delays[retryContext.previousRetryCount];
71
+ }
72
+ })
73
+ .configureLogging(signalR.LogLevel.Critical) // Only critical errors, hide connection noise
74
+ .build();
75
+
76
+ // Handle connection events
77
+ this.connection.onclose(() => {
78
+ this.updateStatus({
79
+ isHealthy: false,
80
+ message: 'Service unavailable',
81
+ lastHeartbeat: null,
82
+ connectionId: null
83
+ });
84
+ this.clearHeartbeatTimeout();
85
+ });
86
+
87
+ this.connection.onreconnecting(() => {
88
+ this.updateStatus({
89
+ isHealthy: false,
90
+ message: 'Service unavailable',
91
+ lastHeartbeat: this.currentStatus.lastHeartbeat,
92
+ connectionId: null
93
+ });
94
+ });
95
+
96
+ this.connection.onreconnected((connectionId) => {
97
+ this.updateStatus({
98
+ isHealthy: true,
99
+ message: 'Service operational',
100
+ lastHeartbeat: new Date(),
101
+ connectionId
102
+ });
103
+ this.resetHeartbeatTimeout();
104
+ });
105
+
106
+ // Handle heartbeat messages - this is the core health indicator
107
+ this.connection.on('Heartbeat', (data) => {
108
+ this.updateStatus({
109
+ isHealthy: true,
110
+ message: 'Service operational',
111
+ lastHeartbeat: new Date(),
112
+ connectionId: this.connection?.connectionId || null
113
+ });
114
+ this.resetHeartbeatTimeout();
115
+ });
116
+
117
+ // Handle initial health status
118
+ this.connection.on('HealthStatus', (data) => {
119
+ this.updateStatus({
120
+ isHealthy: data.status === 'healthy',
121
+ message: data.message || 'Service connected',
122
+ lastHeartbeat: new Date(),
123
+ connectionId: this.connection?.connectionId || null
124
+ });
125
+ this.resetHeartbeatTimeout();
126
+ });
127
+
128
+ // Start the connection
129
+ await this.connection.start();
130
+ console.info('[SignalRHealth] Connection started, connectionId:', this.connection.connectionId);
131
+
132
+ this.updateStatus({
133
+ isHealthy: true,
134
+ message: 'Service connected',
135
+ lastHeartbeat: new Date(),
136
+ connectionId: this.connection.connectionId
137
+ });
138
+
139
+ this.resetHeartbeatTimeout();
140
+
141
+ } catch (error) {
142
+ // Reduce console noise for expected connection failures
143
+ const errorMessage = error instanceof Error ? error.message : String(error);
144
+ console.warn('[SignalRHealth] Connection start failed:', errorMessage);
145
+ const isConnectionRefused = errorMessage.includes('ERR_CONNECTION_REFUSED') ||
146
+ errorMessage.includes('Failed to fetch') ||
147
+ errorMessage.includes('Failed to complete negotiation');
148
+
149
+ if (isConnectionRefused) {
150
+ // Service is down - this is expected, log at info level
151
+ console.info('SignalR Health Service: Backend service unavailable');
152
+ } else {
153
+ // Unexpected error - log as error
154
+ console.error('SignalR Health Service failed to start:', error);
155
+ }
156
+
157
+ this.updateStatus({
158
+ isHealthy: false,
159
+ message: 'Service unavailable',
160
+ lastHeartbeat: null,
161
+ connectionId: null
162
+ });
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Stop the health monitoring connection
168
+ */
169
+ async stop(): Promise<void> {
170
+ this.clearHeartbeatTimeout();
171
+
172
+ if (this.connection) {
173
+ try {
174
+ // Check if connection is in a state that can be stopped
175
+ if (this.connection.state !== signalR.HubConnectionState.Disconnected) {
176
+ await this.connection.stop();
177
+ }
178
+ } catch (error) {
179
+ // Ignore "connection was stopped before the hub handshake could complete" errors
180
+ // as these are expected during rapid start/stop cycles
181
+ const errorMessage = error instanceof Error ? error.message : String(error);
182
+ if (!errorMessage.includes('stopped before the hub handshake could complete')) {
183
+ console.error('Error stopping SignalR health connection:', error);
184
+ }
185
+ }
186
+ this.connection = null;
187
+ }
188
+
189
+ this.updateStatus({
190
+ isHealthy: false,
191
+ message: 'Disconnected',
192
+ lastHeartbeat: null,
193
+ connectionId: null
194
+ });
195
+ }
196
+
197
+ /**
198
+ * Subscribe to health status changes
199
+ */
200
+ subscribe(callback: HealthStatusCallback): () => void {
201
+ this.subscribers.add(callback);
202
+
203
+ // Immediately notify with current status
204
+ callback(this.currentStatus);
205
+
206
+ // Return unsubscribe function
207
+ return () => {
208
+ this.subscribers.delete(callback);
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Get current health status
214
+ */
215
+ getCurrentStatus(): HealthStatus {
216
+ return { ...this.currentStatus };
217
+ }
218
+
219
+ private updateStatus(newStatus: HealthStatus): void {
220
+ this.currentStatus = newStatus;
221
+ this.notifySubscribers();
222
+ }
223
+
224
+ private notifySubscribers(): void {
225
+ this.subscribers.forEach(callback => {
226
+ try {
227
+ callback(this.currentStatus);
228
+ } catch (error) {
229
+ console.error('Error in health status subscriber:', error);
230
+ }
231
+ });
232
+ }
233
+
234
+ private resetHeartbeatTimeout(): void {
235
+ this.clearHeartbeatTimeout();
236
+
237
+ // If we don't receive a heartbeat within the timeout period, consider service unhealthy
238
+ this.heartbeatTimeout = setTimeout(() => {
239
+ this.updateStatus({
240
+ isHealthy: false,
241
+ message: 'Service unavailable',
242
+ lastHeartbeat: this.currentStatus.lastHeartbeat,
243
+ connectionId: this.currentStatus.connectionId
244
+ });
245
+ }, this.heartbeatTimeoutMs);
246
+ }
247
+
248
+ private clearHeartbeatTimeout(): void {
249
+ if (this.heartbeatTimeout) {
250
+ clearTimeout(this.heartbeatTimeout);
251
+ this.heartbeatTimeout = null;
252
+ }
253
+ }
254
+
255
+ }
256
+
257
+ // Export singleton instance
258
+ export const signalRActivityService = new SignalRActivityService();