@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,445 @@
1
+ "use strict";
2
+ /**
3
+ * MVP Middleware - Authentication & Route Protection
4
+ *
5
+ * Creates a Next.js middleware handler that protects routes based on:
6
+ * - Authentication status (session cookie → Redis viability check)
7
+ * - 2FA completion status
8
+ * - RBAC permissions (if enabled)
9
+ *
10
+ * Usage: Export the result from your app's middleware.ts:
11
+ * export default createMvpMiddleware();
12
+ *
13
+ * With custom options:
14
+ * export default createMvpMiddleware({
15
+ * circuitBreaker: myCircuitBreaker,
16
+ * logger: myLogger,
17
+ * viabilityEndpoint: '/api/session/refresh-viability',
18
+ * });
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.createMvpMiddleware = createMvpMiddleware;
22
+ const server_1 = require("next/server");
23
+ const route_config_1 = require("../auth/route-config");
24
+ const internal_api_url_1 = require("../edge/internal-api-url");
25
+ const app_slug_1 = require("../lib/app-slug");
26
+ const rbac_check_1 = require("./rbac-check");
27
+ // =============================================================================
28
+ // DEFAULT IMPLEMENTATIONS
29
+ // =============================================================================
30
+ /** Default no-op circuit breaker (always closed) */
31
+ const defaultCircuitBreaker = {
32
+ isOpen: () => false,
33
+ canAttemptRefresh: () => true,
34
+ recordSuccess: () => { },
35
+ recordFailure: () => { },
36
+ isNetworkError: (error) => {
37
+ return error?.cause?.code === 'ECONNREFUSED' ||
38
+ error?.code === 'ECONNREFUSED' ||
39
+ error?.message?.includes('ECONNREFUSED') ||
40
+ error?.message?.includes('fetch failed') ||
41
+ error?.message?.includes('ENOTFOUND') ||
42
+ error?.message?.includes('ETIMEDOUT') ||
43
+ error?.message?.includes('ECONNRESET');
44
+ }
45
+ };
46
+ /** Default console logger */
47
+ const defaultLogger = {
48
+ info: (msg, data) => console.log(`[MIDDLEWARE] ${msg}`, data || ''),
49
+ warn: (msg, data) => console.warn(`[MIDDLEWARE] ${msg}`, data || ''),
50
+ error: (msg, data) => console.error(`[MIDDLEWARE] ${msg}`, data || ''),
51
+ };
52
+ // =============================================================================
53
+ // HELPERS
54
+ // =============================================================================
55
+ const LOGIN_PAGE = '/account-auth/login';
56
+ const VERIFY_CODE_PAGE = '/account-auth/verify-code';
57
+ function isLoginPage(pathname) {
58
+ return pathname === LOGIN_PAGE;
59
+ }
60
+ /** Ensures callback URLs never point to auth pages (prevents redirect loops) */
61
+ function getSafeCallbackUrl(pathname, searchParams) {
62
+ if (pathname.startsWith('/account-auth/')) {
63
+ return '/';
64
+ }
65
+ const existing = searchParams?.get('callbackUrl');
66
+ if (existing && !existing.startsWith('/account-auth/')) {
67
+ return existing;
68
+ }
69
+ return pathname;
70
+ }
71
+ /** Clear all session cookies on a response */
72
+ function clearSessionCookies(response, request) {
73
+ const sessionCookie = (0, app_slug_1.getSessionCookieName)();
74
+ const secureCookie = (0, app_slug_1.getSecureSessionCookieName)();
75
+ // Clear main cookies
76
+ response.cookies.set(sessionCookie, '', { path: '/', expires: new Date(0), httpOnly: true, sameSite: 'lax' });
77
+ response.cookies.set(secureCookie, '', { path: '/', expires: new Date(0), httpOnly: true, sameSite: 'lax', secure: true });
78
+ // Clear any chunked cookies (NextAuth chunks large cookies)
79
+ for (const [name] of request.cookies) {
80
+ if (name.startsWith(`${sessionCookie}.`) || name.startsWith(`${secureCookie}.`)) {
81
+ const isSecure = name.startsWith('__Secure-');
82
+ response.cookies.set(name, '', {
83
+ path: '/',
84
+ expires: new Date(0),
85
+ httpOnly: true,
86
+ sameSite: 'lax',
87
+ ...(isSecure && { secure: true })
88
+ });
89
+ }
90
+ }
91
+ }
92
+ /** Create redirect response, optionally clearing cookies */
93
+ function redirectTo(request, location, clearCookies = false) {
94
+ const response = server_1.NextResponse.redirect(new URL(location, request.url));
95
+ if (clearCookies) {
96
+ clearSessionCookies(response, request);
97
+ }
98
+ return response;
99
+ }
100
+ // =============================================================================
101
+ // AUTH DECISION ENGINE
102
+ // =============================================================================
103
+ /**
104
+ * Pure function that determines what action to take based on auth state.
105
+ * No side effects - just examines context and returns a decision.
106
+ */
107
+ function makeAuthDecision(ctx) {
108
+ const { pathname, isPublicRoute, isLoginPage: onLoginPage, searchParams, sessionPointer, sessionStatus, circuitBreakerOpen } = ctx;
109
+ const safeCallback = getSafeCallbackUrl(pathname);
110
+ // --- Public routes: Allow, but enforce 2FA for authenticated users ---
111
+ if (isPublicRoute && !onLoginPage) {
112
+ if (needsTwoFactorRedirect(pathname, sessionPointer, sessionStatus)) {
113
+ return redirect2FA(safeCallback);
114
+ }
115
+ return { type: 'allow' };
116
+ }
117
+ // --- Circuit breaker open: Service degraded ---
118
+ if (circuitBreakerOpen) {
119
+ if (onLoginPage)
120
+ return { type: 'allow' };
121
+ return {
122
+ type: 'redirect',
123
+ location: `${LOGIN_PAGE}?error=ServiceUnavailable`,
124
+ reason: 'circuit_breaker_open',
125
+ clearCookies: true
126
+ };
127
+ }
128
+ // --- No session cookie: Need to login ---
129
+ if (!sessionPointer.exists) {
130
+ if (onLoginPage)
131
+ return { type: 'allow' };
132
+ if (pathname === '/') {
133
+ const unauthUrl = process.env.UNAUTHENTICATED_REDIRECT_URL || '/account-auth/login';
134
+ return { type: 'redirect', location: unauthUrl, reason: 'unauthenticated_root' };
135
+ }
136
+ if (pathname.startsWith('/api/')) {
137
+ return { type: 'allow' }; // Let API return proper 401 JSON
138
+ }
139
+ return {
140
+ type: 'redirect',
141
+ location: `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}`,
142
+ reason: 'no_session'
143
+ };
144
+ }
145
+ // --- Service error: Can't verify session ---
146
+ if (sessionStatus.exists === null || sessionStatus.forceInvalid === null) {
147
+ return { type: 'service_error', reason: 'viability_check_failed' };
148
+ }
149
+ // --- Session force-invalidated (admin action, password change, etc.) ---
150
+ if (sessionStatus.forceInvalid) {
151
+ if (onLoginPage)
152
+ return { type: 'allow' };
153
+ if (pathname.startsWith('/api/'))
154
+ return { type: 'allow' };
155
+ return {
156
+ type: 'redirect',
157
+ location: `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&reason=invalidated`,
158
+ reason: 'force_invalidated',
159
+ clearCookies: true
160
+ };
161
+ }
162
+ // --- Stale session (cookie exists but Redis entry gone) ---
163
+ if (!sessionStatus.exists) {
164
+ if (onLoginPage)
165
+ return { type: 'allow' };
166
+ if (pathname.startsWith('/api/'))
167
+ return { type: 'allow' };
168
+ return {
169
+ type: 'redirect',
170
+ location: `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&reason=stale`,
171
+ reason: 'stale_session',
172
+ clearCookies: true
173
+ };
174
+ }
175
+ // --- 2FA required but not completed ---
176
+ if (needsTwoFactorRedirect(pathname, sessionPointer, sessionStatus)) {
177
+ if (onLoginPage) {
178
+ const cb = getSafeCallbackUrl(pathname, searchParams);
179
+ return { type: 'redirect', location: `${VERIFY_CODE_PAGE}?callbackUrl=${encodeURIComponent(cb)}`, reason: '2fa_from_login' };
180
+ }
181
+ return redirect2FA(safeCallback);
182
+ }
183
+ // --- Token expired: Try refresh ---
184
+ if (sessionPointer.expired) {
185
+ if (onLoginPage)
186
+ return { type: 'allow' };
187
+ if (sessionPointer.hasRefreshToken) {
188
+ return { type: 'refresh_needed' };
189
+ }
190
+ return {
191
+ type: 'redirect',
192
+ location: `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&error=SessionExpired`,
193
+ reason: 'token_expired_no_refresh'
194
+ };
195
+ }
196
+ // --- Authenticated user on login page: Send to their destination ---
197
+ if (onLoginPage) {
198
+ const dest = getSafeCallbackUrl(pathname, searchParams);
199
+ return { type: 'redirect', location: dest, reason: 'already_authenticated' };
200
+ }
201
+ // --- All checks passed ---
202
+ return { type: 'allow' };
203
+ }
204
+ /** Check if user needs 2FA redirect */
205
+ function needsTwoFactorRedirect(pathname, session, status) {
206
+ if (!session.exists || !status.exists)
207
+ return false;
208
+ if (!status.requires2FA || status.twoFactorComplete)
209
+ return false;
210
+ if (pathname === VERIFY_CODE_PAGE)
211
+ return false;
212
+ if ((0, route_config_1.should2FABypass)(pathname))
213
+ return false;
214
+ if (pathname.startsWith('/api/'))
215
+ return false; // APIs return JSON errors
216
+ return true;
217
+ }
218
+ function redirect2FA(callbackUrl) {
219
+ return {
220
+ type: 'redirect',
221
+ location: `${VERIFY_CODE_PAGE}?callbackUrl=${encodeURIComponent(callbackUrl)}`,
222
+ reason: '2fa_required'
223
+ };
224
+ }
225
+ // =============================================================================
226
+ // MIDDLEWARE FACTORY
227
+ // =============================================================================
228
+ function createMvpMiddleware(options = {}) {
229
+ // Resolve options with defaults
230
+ const cb = options.circuitBreaker || defaultCircuitBreaker;
231
+ const log = options.logger || defaultLogger;
232
+ const viabilityEndpoint = options.viabilityEndpoint || '/api/session/viability';
233
+ const refreshEndpoint = options.refreshEndpoint || '/api/auth/refresh';
234
+ const bypassPaths = options.bypassPaths || [];
235
+ return async function middleware(request) {
236
+ const { pathname, searchParams } = request.nextUrl;
237
+ // =========================================================================
238
+ // CRITICAL: Auth routes MUST bypass middleware
239
+ // =========================================================================
240
+ // These routes are called internally by middleware itself (viability check,
241
+ // token refresh). Without this bypass, we get infinite loops or 403s.
242
+ // This has caused production outages. DO NOT REMOVE.
243
+ // =========================================================================
244
+ if (pathname.startsWith('/api/auth/') || pathname.startsWith('/api/session/')) {
245
+ return server_1.NextResponse.next();
246
+ }
247
+ // Check custom bypass paths
248
+ for (const bypassPath of bypassPaths) {
249
+ if (pathname.startsWith(bypassPath)) {
250
+ return server_1.NextResponse.next();
251
+ }
252
+ }
253
+ const isPublic = (0, route_config_1.isUnauthenticatedRoute)(pathname);
254
+ const isLogin = isLoginPage(pathname);
255
+ // --- Optimization: Skip viability check for unauthenticated public browsing ---
256
+ if (isPublic && !isLogin) {
257
+ const hasCookie = request.cookies.get((0, app_slug_1.getSessionCookieName)())?.value ||
258
+ request.cookies.get((0, app_slug_1.getSecureSessionCookieName)())?.value;
259
+ if (!hasCookie) {
260
+ return server_1.NextResponse.next();
261
+ }
262
+ // Has cookie - continue to viability check for 2FA enforcement
263
+ }
264
+ // --- Fetch session viability from internal API ---
265
+ const { sessionStatus, sessionPointer } = await checkViability(request, viabilityEndpoint, log);
266
+ // --- Handle stale session early (cookie exists but session doesn't) ---
267
+ if (!isPublic && sessionStatus.exists === false && sessionPointer.sessionToken) {
268
+ const safeCallback = getSafeCallbackUrl(pathname);
269
+ log.warn('Stale session detected', {
270
+ sessionToken: sessionPointer.sessionToken?.substring(0, 8) + '...',
271
+ pathname
272
+ });
273
+ return redirectTo(request, `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}`, true);
274
+ }
275
+ // --- Run decision engine ---
276
+ const decision = makeAuthDecision({
277
+ pathname,
278
+ isPublicRoute: isPublic,
279
+ isLoginPage: isLogin,
280
+ searchParams,
281
+ sessionPointer,
282
+ sessionStatus,
283
+ circuitBreakerOpen: cb.isOpen(),
284
+ });
285
+ // --- Execute decision ---
286
+ return executeDecision(request, decision, pathname, sessionPointer, sessionStatus, {
287
+ circuitBreaker: cb,
288
+ logger: log,
289
+ refreshEndpoint,
290
+ onRefreshSuccess: options.onRefreshSuccess,
291
+ onRefreshFailure: options.onRefreshFailure,
292
+ });
293
+ };
294
+ }
295
+ /** Check session viability via internal API */
296
+ async function checkViability(request, endpoint, log) {
297
+ const sessionStatus = {
298
+ exists: false,
299
+ forceInvalid: false,
300
+ requires2FA: false,
301
+ twoFactorComplete: false,
302
+ };
303
+ const sessionPointer = {
304
+ exists: false,
305
+ sessionToken: undefined,
306
+ expired: false,
307
+ hasRefreshToken: false,
308
+ roles: [],
309
+ clientId: '',
310
+ };
311
+ try {
312
+ const baseUrl = (0, internal_api_url_1.getInternalApiUrl)(request);
313
+ const response = await fetch(new URL(endpoint, baseUrl), {
314
+ method: 'GET',
315
+ headers: {
316
+ 'Accept': 'application/json',
317
+ 'Cache-Control': 'no-store',
318
+ 'Cookie': request.headers.get('cookie') || ''
319
+ },
320
+ credentials: 'include'
321
+ });
322
+ if (response.ok) {
323
+ const data = await response.json();
324
+ // Support both response formats (viability and refresh-viability)
325
+ sessionStatus.exists = data.authenticated ?? (data.sessionToken && data.reason !== 'session_not_found');
326
+ sessionStatus.requires2FA = data.requires2FA || false;
327
+ sessionStatus.twoFactorComplete = data.twoFactorComplete || false;
328
+ sessionPointer.exists = sessionStatus.exists ?? false;
329
+ sessionPointer.sessionToken = data.sessionToken;
330
+ sessionPointer.expired = data.accessTokenExpired || false;
331
+ sessionPointer.hasRefreshToken = data.hasRefreshToken ?? data.canRefresh ?? false;
332
+ sessionPointer.roles = data.roles || [];
333
+ sessionPointer.clientId = data.clientId || '';
334
+ }
335
+ else {
336
+ log.error('Viability check failed', { status: response.status });
337
+ sessionStatus.exists = null;
338
+ sessionStatus.forceInvalid = null;
339
+ }
340
+ }
341
+ catch (error) {
342
+ log.error('Viability check error', { error: error instanceof Error ? error.message : String(error) });
343
+ sessionStatus.exists = null;
344
+ sessionStatus.forceInvalid = null;
345
+ }
346
+ return { sessionStatus, sessionPointer };
347
+ }
348
+ /** Execute the auth decision */
349
+ async function executeDecision(request, decision, pathname, sessionPointer, sessionStatus, opts) {
350
+ const safeCallback = getSafeCallbackUrl(pathname);
351
+ switch (decision.type) {
352
+ case 'allow':
353
+ return handleAllow(request, pathname, sessionPointer, sessionStatus);
354
+ case 'redirect':
355
+ return redirectTo(request, decision.location, decision.clearCookies);
356
+ case 'service_error':
357
+ return server_1.NextResponse.redirect(new URL('/service-unavailable', request.url));
358
+ case 'refresh_needed':
359
+ return handleRefresh(request, safeCallback, opts);
360
+ }
361
+ }
362
+ /** Handle 'allow' decision - run RBAC if enabled */
363
+ async function handleAllow(request, pathname, sessionPointer, sessionStatus) {
364
+ const isPublic = (0, route_config_1.isUnauthenticatedRoute)(pathname);
365
+ if ((0, rbac_check_1.isRBACEnabled)() && !isPublic) {
366
+ if (!sessionPointer.clientId) {
367
+ console.error('[MIDDLEWARE] RBAC: No clientId');
368
+ return server_1.NextResponse.redirect(new URL('/error?code=no_client_id', request.url));
369
+ }
370
+ try {
371
+ const result = await (0, rbac_check_1.checkPagePermission)(pathname, sessionPointer.roles, sessionPointer.clientId);
372
+ if (!result.allowed) {
373
+ console.log('[MIDDLEWARE] RBAC denied:', { pathname, reason: result.reason });
374
+ return server_1.NextResponse.redirect(new URL(result.redirect || '/unauthorized', request.url));
375
+ }
376
+ if (result.requires_2fa && !sessionStatus.twoFactorComplete) {
377
+ return server_1.NextResponse.redirect(new URL(`${VERIFY_CODE_PAGE}?callbackUrl=${encodeURIComponent(pathname)}`, request.url));
378
+ }
379
+ }
380
+ catch (error) {
381
+ console.error('[MIDDLEWARE] RBAC error:', error);
382
+ return server_1.NextResponse.redirect(new URL('/error?code=rbac_error', request.url));
383
+ }
384
+ }
385
+ return server_1.NextResponse.next();
386
+ }
387
+ /** Handle token refresh */
388
+ async function handleRefresh(request, safeCallback, opts) {
389
+ const { circuitBreaker: cb, logger: log, refreshEndpoint, onRefreshSuccess, onRefreshFailure } = opts;
390
+ // Check if circuit breaker allows refresh attempt
391
+ if (!cb.canAttemptRefresh()) {
392
+ log.warn('Circuit breaker preventing refresh attempt');
393
+ return redirectTo(request, `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&error=ServiceUnavailable`, true);
394
+ }
395
+ try {
396
+ const baseUrl = (0, internal_api_url_1.getInternalApiUrl)(request);
397
+ const response = await fetch(new URL(refreshEndpoint, baseUrl), {
398
+ method: 'POST',
399
+ headers: {
400
+ 'Accept': 'application/json',
401
+ 'Content-Type': 'application/json',
402
+ 'Cookie': request.headers.get('cookie') || '',
403
+ 'x-session-token': request.cookies.get((0, app_slug_1.getSessionCookieName)())?.value ||
404
+ request.cookies.get((0, app_slug_1.getSecureSessionCookieName)())?.value || ''
405
+ },
406
+ credentials: 'include'
407
+ });
408
+ if (response.ok) {
409
+ const data = await response.json();
410
+ if (data.refreshed || data.reason === 'already_fresh') {
411
+ cb.recordSuccess();
412
+ onRefreshSuccess?.();
413
+ log.info('Token refresh successful');
414
+ return server_1.NextResponse.next();
415
+ }
416
+ }
417
+ // Refresh failed - check for permanent failures (401/403) vs transient (5xx)
418
+ // CRITICAL: Always clear cookies on 401/403 to prevent redirect loops
419
+ // CRITICAL: Only record circuit breaker failures for network errors, not HTTP errors
420
+ // HTTP 500 means the server responded - it's reachable. Only network failures should trip the breaker.
421
+ const isPermanentFailure = response.status === 401 || response.status === 403;
422
+ const errorParam = isPermanentFailure ? 'SessionExpired' : 'RefreshError';
423
+ log.warn('Refresh failed', {
424
+ status: response.status,
425
+ isPermanentFailure,
426
+ clearingCookies: isPermanentFailure
427
+ });
428
+ onRefreshFailure?.(response.status, false);
429
+ return redirectTo(request, `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&error=${errorParam}`, isPermanentFailure);
430
+ }
431
+ catch (error) {
432
+ const isNetwork = cb.isNetworkError(error);
433
+ log.error('Refresh error', {
434
+ error: error instanceof Error ? error.message : String(error),
435
+ isNetworkError: isNetwork
436
+ });
437
+ // Only record circuit breaker failure for actual network errors
438
+ if (isNetwork) {
439
+ cb.recordFailure(error);
440
+ }
441
+ onRefreshFailure?.(0, isNetwork);
442
+ // Network error - don't clear cookies, might be transient
443
+ return redirectTo(request, `${LOGIN_PAGE}?callbackUrl=${encodeURIComponent(safeCallback)}&error=RefreshError`, false);
444
+ }
445
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Page RBAC Check Module
3
+ *
4
+ * Checks page-level permissions via Vibe API.
5
+ * Uses in-memory cache to reduce API calls.
6
+ * Fails closed (DENY) on errors or timeout.
7
+ *
8
+ * @version 1.0.0
9
+ * @since page-rbac-2026-01
10
+ */
11
+ export interface RBACResult {
12
+ allowed: boolean;
13
+ requires_2fa?: boolean;
14
+ requires_elevated_auth?: boolean;
15
+ reason?: string;
16
+ required_roles?: string[];
17
+ required_claims?: Array<{
18
+ type: string;
19
+ value: string;
20
+ }>;
21
+ matched_rule?: string;
22
+ redirect?: string;
23
+ cache_ttl?: number;
24
+ }
25
+ /**
26
+ * Clear cache (for testing or config changes).
27
+ */
28
+ export declare function clearRBACCache(): void;
29
+ /**
30
+ * Check if user has permission to access a page.
31
+ *
32
+ * FAIL CLOSED: If Vibe API is unreachable or times out, access is DENIED.
33
+ *
34
+ * @param path - The route path to check
35
+ * @param userRoles - User's roles from session
36
+ * @param clientId - Client ID for multi-tenancy
37
+ * @param userClaims - Optional claims for claim-based authorization
38
+ * @returns RBAC result with allowed/denied status
39
+ */
40
+ export declare function checkPagePermission(path: string, userRoles: string[], clientId: string, userClaims?: Record<string, string>): Promise<RBACResult>;
41
+ /**
42
+ * Check if RBAC is enabled for this deployment.
43
+ */
44
+ export declare function isRBACEnabled(): boolean;
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Page RBAC Check Module
4
+ *
5
+ * Checks page-level permissions via Vibe API.
6
+ * Uses in-memory cache to reduce API calls.
7
+ * Fails closed (DENY) on errors or timeout.
8
+ *
9
+ * @version 1.0.0
10
+ * @since page-rbac-2026-01
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.clearRBACCache = clearRBACCache;
14
+ exports.checkPagePermission = checkPagePermission;
15
+ exports.isRBACEnabled = isRBACEnabled;
16
+ const crypto_1 = require("crypto");
17
+ // ============================================================================
18
+ // CACHE
19
+ // ============================================================================
20
+ const rbacCache = new Map();
21
+ const DEFAULT_CACHE_TTL = 60; // 60 seconds
22
+ const MAX_CACHE_TTL = 300; // 5 minutes max - prevents cache poisoning
23
+ const MAX_CACHE_SIZE = 1000;
24
+ /**
25
+ * Generate cache key for RBAC result.
26
+ * Uses SHA-256 hash to avoid key collisions and limit key size.
27
+ */
28
+ function getCacheKey(clientId, path, roles) {
29
+ const sortedRoles = [...roles].sort().join(',');
30
+ const input = JSON.stringify({ clientId, path, roles: sortedRoles });
31
+ return (0, crypto_1.createHash)('sha256').update(input).digest('hex').substring(0, 32);
32
+ }
33
+ /**
34
+ * Get cached RBAC result if valid.
35
+ */
36
+ function getCachedResult(key) {
37
+ const cached = rbacCache.get(key);
38
+ if (cached && cached.expires > Date.now()) {
39
+ return cached.result;
40
+ }
41
+ // Clean up expired entry
42
+ if (cached) {
43
+ rbacCache.delete(key);
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * Cache an RBAC result.
49
+ */
50
+ function setCachedResult(key, result) {
51
+ // Prevent unbounded cache growth
52
+ if (rbacCache.size >= MAX_CACHE_SIZE) {
53
+ // Remove oldest entries (first 100)
54
+ const keysToDelete = Array.from(rbacCache.keys()).slice(0, 100);
55
+ keysToDelete.forEach(k => rbacCache.delete(k));
56
+ }
57
+ // SECURITY: Clamp TTL to prevent cache poisoning attacks
58
+ const ttl = Math.min(result.cache_ttl ?? DEFAULT_CACHE_TTL, MAX_CACHE_TTL);
59
+ rbacCache.set(key, {
60
+ result,
61
+ expires: Date.now() + (ttl * 1000),
62
+ });
63
+ }
64
+ /**
65
+ * Clear cache (for testing or config changes).
66
+ */
67
+ function clearRBACCache() {
68
+ rbacCache.clear();
69
+ }
70
+ // ============================================================================
71
+ // SIGNATURE
72
+ // ============================================================================
73
+ /**
74
+ * Generate HMAC-SHA256 signature for Vibe API request.
75
+ * SECURITY: Signing key is required in production.
76
+ */
77
+ function generateSignature(path, clientId, timestamp) {
78
+ const signingKey = process.env.VIBE_SIGNING_KEY;
79
+ // SECURITY: Require signing key in production
80
+ if (!signingKey) {
81
+ if (process.env.NODE_ENV === 'production') {
82
+ throw new Error('[RBAC] VIBE_SIGNING_KEY is required in production');
83
+ }
84
+ return ''; // Signature optional in dev only
85
+ }
86
+ const stringToSign = `${timestamp}|GET|/api/v1/rbac/check|${path}|${clientId}`;
87
+ return (0, crypto_1.createHmac)('sha256', Buffer.from(signingKey, 'base64'))
88
+ .update(stringToSign)
89
+ .digest('base64');
90
+ }
91
+ // ============================================================================
92
+ // RBAC CHECK
93
+ // ============================================================================
94
+ /**
95
+ * Check if user has permission to access a page.
96
+ *
97
+ * FAIL CLOSED: If Vibe API is unreachable or times out, access is DENIED.
98
+ *
99
+ * @param path - The route path to check
100
+ * @param userRoles - User's roles from session
101
+ * @param clientId - Client ID for multi-tenancy
102
+ * @param userClaims - Optional claims for claim-based authorization
103
+ * @returns RBAC result with allowed/denied status
104
+ */
105
+ async function checkPagePermission(path, userRoles, clientId, userClaims) {
106
+ // Check cache first
107
+ const cacheKey = getCacheKey(clientId, path, userRoles);
108
+ const cached = getCachedResult(cacheKey);
109
+ if (cached) {
110
+ return cached;
111
+ }
112
+ const vibeApiUrl = process.env.VIBE_API_URL;
113
+ if (!vibeApiUrl) {
114
+ console.error('[RBAC] VIBE_API_URL not configured');
115
+ return {
116
+ allowed: false,
117
+ reason: 'rbac_not_configured',
118
+ redirect: '/error?code=rbac_not_configured',
119
+ };
120
+ }
121
+ // Build request URL
122
+ const url = new URL('/api/v1/rbac/check', vibeApiUrl);
123
+ url.searchParams.set('path', path);
124
+ url.searchParams.set('roles', userRoles.join(','));
125
+ // Add claims if provided
126
+ if (userClaims && Object.keys(userClaims).length > 0) {
127
+ const claimsParam = Object.entries(userClaims)
128
+ .map(([type, value]) => `${type}:${value}`)
129
+ .join(',');
130
+ url.searchParams.set('claims', claimsParam);
131
+ }
132
+ // Generate signature
133
+ const timestamp = Math.floor(Date.now() / 1000);
134
+ const signature = generateSignature(path, clientId, timestamp);
135
+ // Build headers
136
+ const headers = {
137
+ 'Accept': 'application/json',
138
+ 'X-Client-Id': clientId,
139
+ 'X-Vibe-Client-Id': clientId,
140
+ };
141
+ if (signature) {
142
+ headers['X-Vibe-Timestamp'] = String(timestamp);
143
+ headers['X-Vibe-Signature'] = signature;
144
+ }
145
+ try {
146
+ // 2 second timeout - fail closed
147
+ const controller = new AbortController();
148
+ const timeoutId = setTimeout(() => controller.abort(), 2000);
149
+ const response = await fetch(url.toString(), {
150
+ method: 'GET',
151
+ headers,
152
+ signal: controller.signal,
153
+ });
154
+ clearTimeout(timeoutId);
155
+ if (!response.ok) {
156
+ console.error('[RBAC] Vibe API error:', response.status, response.statusText);
157
+ return {
158
+ allowed: false,
159
+ reason: 'rbac_api_error',
160
+ redirect: '/error?code=rbac_error',
161
+ };
162
+ }
163
+ const result = await response.json();
164
+ // Cache the result
165
+ setCachedResult(cacheKey, result);
166
+ return result;
167
+ }
168
+ catch (error) {
169
+ // Fail closed on any error
170
+ if (error.name === 'AbortError') {
171
+ console.error('[RBAC] Vibe API timeout (2s exceeded)');
172
+ return {
173
+ allowed: false,
174
+ reason: 'rbac_timeout',
175
+ redirect: '/error?code=rbac_timeout',
176
+ };
177
+ }
178
+ console.error('[RBAC] Vibe API error:', error);
179
+ return {
180
+ allowed: false,
181
+ reason: 'rbac_service_unavailable',
182
+ redirect: '/error?code=rbac_unavailable',
183
+ };
184
+ }
185
+ }
186
+ /**
187
+ * Check if RBAC is enabled for this deployment.
188
+ */
189
+ function isRBACEnabled() {
190
+ return process.env.VIBE_RBAC_ENABLED === 'true';
191
+ }