@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,93 @@
1
+ 'use client';
2
+
3
+ import React from 'react';
4
+
5
+ export interface FooterProps {
6
+ /** Company or product name (default: 'PayEz') */
7
+ companyName?: string;
8
+ /** Start year for copyright range (shows "2024-2025" format if provided) */
9
+ startYear?: number;
10
+ /** Additional links to display */
11
+ links?: Array<{ label: string; href: string }>;
12
+ /** Additional CSS classes */
13
+ className?: string;
14
+ /** Variant style */
15
+ variant?: 'minimal' | 'standard';
16
+ }
17
+
18
+ /**
19
+ * A themeable footer component with dynamic copyright year.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * // Minimal footer
24
+ * <Footer />
25
+ *
26
+ * // With company name and start year
27
+ * <Footer companyName="Acme Inc" startYear={2020} />
28
+ *
29
+ * // With links
30
+ * <Footer
31
+ * links={[
32
+ * { label: 'Privacy', href: '/privacy' },
33
+ * { label: 'Terms', href: '/terms' }
34
+ * ]}
35
+ * />
36
+ * ```
37
+ */
38
+ export function Footer({
39
+ companyName = 'PayEz',
40
+ startYear,
41
+ links = [],
42
+ className = '',
43
+ variant = 'minimal'
44
+ }: FooterProps) {
45
+ const currentYear = new Date().getFullYear();
46
+ const yearDisplay = startYear && startYear < currentYear
47
+ ? `${startYear}-${currentYear}`
48
+ : `${currentYear}`;
49
+
50
+ const baseStyles = 'w-full py-4 text-sm';
51
+
52
+ const variantStyles = {
53
+ minimal: 'text-center text-gray-500 dark:text-gray-400',
54
+ standard: 'border-t border-gray-200 dark:border-gray-700 text-gray-500 dark:text-gray-400'
55
+ };
56
+
57
+ if (variant === 'minimal') {
58
+ return (
59
+ <footer className={`${baseStyles} ${variantStyles[variant]} ${className}`}>
60
+ <p>
61
+ &copy; {yearDisplay} {companyName}. All rights reserved.
62
+ </p>
63
+ </footer>
64
+ );
65
+ }
66
+
67
+ return (
68
+ <footer className={`${baseStyles} ${variantStyles[variant]} ${className}`}>
69
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
70
+ <div className="flex flex-col sm:flex-row justify-between items-center gap-4">
71
+ <p>
72
+ &copy; {yearDisplay} {companyName}. All rights reserved.
73
+ </p>
74
+ {links.length > 0 && (
75
+ <nav className="flex gap-4" aria-label="Footer links">
76
+ {links.map((link, index) => (
77
+ <a
78
+ key={`${index}-${link.label}`}
79
+ href={link.href}
80
+ className="hover:text-gray-700 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900 rounded transition-colors"
81
+ >
82
+ {link.label}
83
+ </a>
84
+ ))}
85
+ </nav>
86
+ )}
87
+ </div>
88
+ </div>
89
+ </footer>
90
+ );
91
+ }
92
+
93
+ export default Footer;
@@ -0,0 +1,57 @@
1
+ export const ENV_CONFIG = {
2
+ CLIENT_ID: process.env.CLIENT_ID,
3
+ INTERNAL_URL: process.env.IDP_URL,
4
+ IDP_CLIENT_ID: (() => { const raw = process.env.NEXT_PUBLIC_IDP_CLIENT_ID || process.env.IDP_CLIENT_ID; const n = raw ? parseInt(raw, 10) : undefined; return Number.isFinite(n as any) ? (n as number) : undefined; })(),
5
+ IDP_URL: process.env.IDP_URL,
6
+ API_URL: process.env.IDP_URL,
7
+ PAYEZ_CORE_BASE_URL: process.env.NEXT_PUBLIC_PAYEZ_CORE_BASE_URL,
8
+ SUPPORT_EMAIL: 'support@PayEz.net',
9
+ LOG_LEVEL: process.env.LOG_LEVEL || 'info',
10
+ LOG_CONSOLE: process.env.LOG_CONSOLE === 'true' || process.env.NODE_ENV === 'development',
11
+ GRAYLOG_HOST: process.env.GRAYLOG_HOST || '10.6.10.5',
12
+ GRAYLOG_PORT: parseInt(process.env.GRAYLOG_PORT || '12201'),
13
+
14
+ // Redis key prefix for multi-tenant session isolation
15
+ // Each application should have a unique prefix to prevent session conflicts
16
+ // Example: 'cryptaply:', 'website-membership:', 'myapp:'
17
+ // Leave empty ('') for backward compatibility
18
+ REDIS_KEY_PREFIX: process.env.REDIS_KEY_PREFIX || '',
19
+
20
+ // Redirect URLs - configurable per-tenant
21
+ // LOGOUT_REDIRECT_URL: Where to redirect after logout (default: '/')
22
+ // UNAUTHENTICATED_REDIRECT_URL: Where to redirect unauthenticated users from root (default: '/account-auth/login')
23
+ LOGOUT_REDIRECT_URL: process.env.LOGOUT_REDIRECT_URL || '/',
24
+ UNAUTHENTICATED_REDIRECT_URL: process.env.UNAUTHENTICATED_REDIRECT_URL || '/account-auth/login',
25
+ } as const;
26
+
27
+ export const API_ENDPOINTS = {
28
+ account: {
29
+ profile: '/api/account/profile',
30
+ updateProfile: '/api/account/profile',
31
+ maskedInfo: '/api/account/masked-info',
32
+ sendResetCode: '/api/account/send-reset-code',
33
+ verifyResetCode: '/api/account/verify-reset-code',
34
+ resetPassword: '/api/account/reset-password',
35
+ changePassword: '/api/account/change-password',
36
+ validatePassword: '/api/account/validate-password'
37
+ },
38
+ externalAuth: {
39
+ login: '/api/ExternalAuth/login',
40
+ refresh: '/api/ExternalAuth/refresh',
41
+ validate: '/api/ExternalAuth/validate',
42
+ verifyCode: '/api/ExternalAuth/verify-code',
43
+ revoke: '/api/ExternalAuth/revoke',
44
+ roles: (username: string) => `/api/ExternalAuth/roles/${username}`,
45
+ jwks: '/api/ExternalAuth/.well-known/jwks.json',
46
+ openidConfig: '/api/ExternalAuth/.well-known/openid-configuration',
47
+ passwordless: {
48
+ sms: { start: '/api/ExternalAuth/passwordless/sms/start', login: '/api/ExternalAuth/passwordless/sms/login', resend: '/api/ExternalAuth/passwordless/sms/resend' },
49
+ email: { start: '/api/ExternalAuth/passwordless/email/start', login: '/api/ExternalAuth/passwordless/email/login', resend: '/api/ExternalAuth/passwordless/email/resend' }
50
+ },
51
+ lead: { registration: '/api/ExternalAuth/lead/registration', verify: '/api/ExternalAuth/lead/verify' }
52
+ },
53
+ progressiveAuth: {
54
+ step1: '/api/ProgressiveAuth/step1', step2: '/api/ProgressiveAuth/step2', step3: '/api/ProgressiveAuth/step3', step4: '/api/ProgressiveAuth/step4', step5: '/api/ProgressiveAuth/step5', verifyEmail: '/api/ProgressiveAuth/verify-email'
55
+ },
56
+ azureAuth: { login: '/auth/azure/login', logout: '/auth/azure/logout' }
57
+ } as const;
@@ -0,0 +1,62 @@
1
+ import { getLoggingConfigSync, startConfigWatching, addConfigWatcher } from './logging-config';
2
+ import { LoggingConfig } from '../types/logging';
3
+ import { createVibeLogTransport } from './vibe-log-transport';
4
+
5
+ let loggingConfig: LoggingConfig = getLoggingConfigSync();
6
+ startConfigWatching();
7
+
8
+ const isEdgeRuntime = (): boolean => {
9
+ return typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
10
+ };
11
+ const isBrowser = (): boolean => typeof window !== 'undefined';
12
+
13
+ interface Logger { error: (message: string, meta?: any) => void; warn: (message: string, meta?: any) => void; info: (message: string, meta?: any) => void; http: (message: string, meta?: any) => void; debug: (message: string, meta?: any) => void; }
14
+
15
+ class EdgeLogger implements Logger {
16
+ private logLevel: string = loggingConfig.logLevel; private levelOrder: string[] = Object.keys(loggingConfig.levels);
17
+ private shouldLog(level: string): boolean { const currentLevelIndex = this.levelOrder.indexOf(this.logLevel); const messageLevelIndex = this.levelOrder.indexOf(level); return messageLevelIndex <= currentLevelIndex; }
18
+ private format(level: string, message: string, meta?: any) { const timestamp = new Date().toISOString(); const metaString = meta ? ` ${JSON.stringify(meta)}` : ''; return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaString}`; }
19
+ error(m: string, meta?: any) { if (this.shouldLog('error')) console.error(this.format('error', m, meta)); }
20
+ warn(m: string, meta?: any) { if (this.shouldLog('warn')) console.warn(this.format('warn', m, meta)); }
21
+ info(m: string, meta?: any) { if (this.shouldLog('info')) console.info(this.format('info', m, meta)); }
22
+ http(m: string, meta?: any) { if (this.shouldLog('http')) console.log(this.format('http', m, meta)); }
23
+ debug(m: string, meta?: any) { if (this.shouldLog('debug')) console.debug(this.format('debug', m, meta)); }
24
+ }
25
+
26
+ const createLogger = (): any => {
27
+ if (isEdgeRuntime()) return new EdgeLogger();
28
+ if (isBrowser()) return { error: (m: string, meta?: any) => console.error(m, meta), warn: (m: string, meta?: any) => console.warn(m, meta), info: (m: string, meta?: any) => console.info(m, meta), http: (m: string, meta?: any) => console.log(m, meta), debug: (m: string, meta?: any) => console.debug(m, meta) };
29
+ try {
30
+ const winston = require('winston');
31
+ const transports: any[] = [];
32
+ if (loggingConfig.console.enabled) {
33
+ transports.push(new winston.transports.Console({ format: winston.format.combine(winston.format.colorize({ all: true }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.printf(({ timestamp, level, message, ...meta }: any) => { const metaString = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : ''; return `[${timestamp}] ${level}: ${message}${metaString}`; })) }));
34
+ }
35
+ // Add Vibe log transport (sends warn/error to Redis for drain to Vibe)
36
+ const vibeTransport = createVibeLogTransport({ minLevel: 'warn' });
37
+ if (vibeTransport) {
38
+ transports.push(vibeTransport);
39
+ console.log('[LOGGER] Vibe Redis transport ENABLED - logs will buffer to Redis');
40
+ } else {
41
+ console.log('[LOGGER] Vibe Redis transport DISABLED - no REDIS_URL configured');
42
+ }
43
+ return winston.createLogger({ level: loggingConfig.logLevel, levels: loggingConfig.levels, format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json()), transports, exitOnError: false });
44
+ } catch (error) { console.warn('Failed to initialize Winston logger, falling back to EdgeLogger:', error); return new EdgeLogger(); }
45
+ };
46
+
47
+ let logger: any;
48
+ if (!globalThis.process?.browser) {
49
+ logger = createLogger();
50
+ addConfigWatcher((updatedConfig) => { loggingConfig = updatedConfig; if (logger && logger.level !== undefined) { logger.level = loggingConfig.logLevel; } });
51
+ } else { logger = console; }
52
+
53
+ export const log = { error: (m: string, meta?: any) => logger.error(m, meta), warn: (m: string, meta?: any) => logger.warn(m, meta), info: (m: string, meta?: any) => logger.info(m, meta), http: (m: string, meta?: any) => logger.http(m, meta), debug: (m: string, meta?: any) => logger.debug(m, meta) };
54
+ export { logger };
55
+ export const authLogger = { error: (m: string, meta?: any) => logger.error(`[AUTH] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[AUTH] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[AUTH] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[AUTH] ${m}`, meta) };
56
+ export const idpLogger = { error: (m: string, meta?: any) => logger.error(`[IDP] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[IDP] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[IDP] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[IDP] ${m}`, meta) };
57
+ export const apiLogger = { error: (m: string, meta?: any) => logger.error(`[API] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[API] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[API] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[API] ${m}`, meta) };
58
+ export const circuitBreakerLogger = { error: (m: string, meta?: any) => logger.error(`[CIRCUIT-BREAKER] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[CIRCUIT-BREAKER] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[CIRCUIT-BREAKER] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[CIRCUIT-BREAKER] ${m}`, meta) };
59
+ export const tokenLogger = { error: (m: string, meta?: any) => logger.error(`[TOKEN] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[TOKEN] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[TOKEN] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[TOKEN] ${m}`, meta) };
60
+ export const tokenSyncLogger = { error: (m: string, meta?: any) => logger.error(`[TOKEN-SYNC] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[TOKEN-SYNC] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[TOKEN-SYNC] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[TOKEN-SYNC] ${m}`, meta) };
61
+ export const tokenRefreshLogger = { error: (m: string, meta?: any) => logger.error(`[TOKEN-REFRESH] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[TOKEN-REFRESH] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[TOKEN-REFRESH] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[TOKEN-REFRESH] ${m}`, meta) };
62
+ export const redisLogger = { error: (m: string, meta?: any) => logger.error(`[REDIS] ${m}`, meta), warn: (m: string, meta?: any) => logger.warn(`[REDIS] ${m}`, meta), info: (m: string, meta?: any) => logger.info(`[REDIS] ${m}`, meta), debug: (m: string, meta?: any) => logger.debug(`[REDIS] ${m}`, meta) };
@@ -0,0 +1,82 @@
1
+ import { promises as fs } from 'fs';
2
+ import { watch, existsSync } from 'fs';
3
+ import { LoggingConfig, LogLevel } from '../types/logging';
4
+
5
+ const isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
6
+
7
+ class LoggingConfigManager {
8
+ private config: LoggingConfig | null = null;
9
+ private configPath: string;
10
+ private watchers: Set<(config: LoggingConfig) => void> = new Set();
11
+ private fileWatcher: ReturnType<typeof watch> | null = null;
12
+ private isEdgeRuntime: boolean;
13
+ private isBrowser: boolean;
14
+
15
+ constructor() {
16
+ this.isBrowser = typeof window !== 'undefined';
17
+ this.isEdgeRuntime = typeof (globalThis as any).EdgeRuntime !== 'undefined' || process.env.NEXT_RUNTIME === 'edge';
18
+ if (this.isEdgeRuntime || this.isBrowser) {
19
+ this.configPath = '/config/logging.json';
20
+ this.config = this.getDefaultConfig();
21
+ } else {
22
+ const cwd = process.cwd().replace(/\\/g, '/');
23
+ this.configPath = cwd + '/config/logging.json';
24
+ }
25
+ }
26
+
27
+ async loadConfig(): Promise<LoggingConfig> {
28
+ if (this.isEdgeRuntime || this.isBrowser) {
29
+ if (!this.config) { this.config = this.getDefaultConfig(); }
30
+ return this.config;
31
+ }
32
+ try {
33
+ const configContent = await fs.readFile(this.configPath, 'utf-8');
34
+ const rawConfig = JSON.parse(configContent);
35
+ const config = this.validateAndMergeConfig(rawConfig);
36
+ this.config = config; this.notifyWatchers(config); return config;
37
+ } catch (error) {
38
+ console.warn(`Failed to load logging config from ${this.configPath}:`, error);
39
+ return this.getDefaultConfig();
40
+ }
41
+ }
42
+
43
+ async getConfig(): Promise<LoggingConfig> { if (!this.config) { return await this.loadConfig(); } return this.config; }
44
+ getConfigSync(): LoggingConfig { return this.config || this.getDefaultConfig(); }
45
+
46
+ startWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { return; } try { if (!existsSync(this.configPath)) { console.warn(`Logging config file not found at ${this.configPath} — watch disabled`); return; } this.fileWatcher = watch(this.configPath, { persistent: false }, (eventType) => { if (eventType === 'change') { this.loadConfig().catch(console.error); } }); } catch (error) { console.warn('Failed to start watching logging config file:', error); } }
47
+ stopWatching(): void { if (this.isEdgeRuntime || this.isBrowser) { return; } if (this.fileWatcher) { this.fileWatcher.close(); this.fileWatcher = null; } }
48
+ addWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.add(callback); }
49
+ removeWatcher(callback: (config: LoggingConfig) => void): void { this.watchers.delete(callback); }
50
+ private notifyWatchers(config: LoggingConfig): void { this.watchers.forEach(cb => { try { cb(config); } catch (error) { console.error('Error in logging config watcher:', error); } }); }
51
+
52
+ private validateAndMergeConfig(rawConfig: any): LoggingConfig {
53
+ const defaults = this.getDefaultConfig();
54
+ const config: LoggingConfig = {
55
+ logLevel: this.validateLogLevel(rawConfig.logLevel) || this.validateLogLevel(process.env.LOG_LEVEL) || defaults.logLevel,
56
+ console: { enabled: rawConfig.console?.enabled ?? (process.env.LOG_CONSOLE === 'true' || process.env.NODE_ENV === 'development'), colors: rawConfig.console?.colors ?? defaults.console.colors },
57
+ graylog: { enabled: false, host: defaults.graylog.host, port: defaults.graylog.port, facility: defaults.graylog.facility, staticMeta: { ...defaults.graylog.staticMeta } },
58
+ components: { ...defaults.components, ...rawConfig.components },
59
+ levels: { ...defaults.levels, ...rawConfig.levels }
60
+ };
61
+ return config;
62
+ }
63
+ private validateLogLevel(level: any): LogLevel | null { const validLevels: LogLevel[] = ['error', 'warn', 'info', 'http', 'debug']; return validLevels.includes(level) ? level : null; }
64
+ private getHostname(): string { if (this.isEdgeRuntime) return 'edge-runtime'; if (this.isBrowser) return 'browser-client'; try { return require('os').hostname(); } catch { return 'unknown'; } }
65
+ private getDefaultConfig(): LoggingConfig {
66
+ return {
67
+ logLevel: 'info',
68
+ console: { enabled: process.env.NODE_ENV === 'development', colors: true },
69
+ graylog: { enabled: false, host: '127.0.0.1', port: 12201, facility: 'next-mvp', staticMeta: { service: 'next-mvp', application: 'next-mvp', version: '1.0.0', environment: process.env.NODE_ENV || 'development', hostname: this.getHostname(), instance: process.env.NEXT_INSTANCE_ID || 'unknown' } },
70
+ components: { auth: { enabled: true, prefix: '[AUTH]' }, idp: { enabled: true, prefix: '[IDP]' }, api: { enabled: true, prefix: '[API]' }, circuitBreaker: { enabled: true, prefix: '[CIRCUIT-BREAKER]' }, token: { enabled: true, prefix: '[TOKEN]' }, tokenSync: { enabled: true, prefix: '[TOKEN-SYNC]' }, tokenRefresh: { enabled: true, prefix: '[TOKEN-REFRESH]' }, redis: { enabled: true, prefix: '[REDIS]' } },
71
+ levels: { error: 0, warn: 1, info: 2, http: 3, debug: 4 }
72
+ };
73
+ }
74
+ }
75
+
76
+ export const loggingConfigManager = new LoggingConfigManager();
77
+ export const getLoggingConfig = () => loggingConfigManager.getConfig();
78
+ export const getLoggingConfigSync = () => loggingConfigManager.getConfigSync();
79
+ export const startConfigWatching = () => loggingConfigManager.startWatching();
80
+ export const stopConfigWatching = () => loggingConfigManager.stopWatching();
81
+ export const addConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.addWatcher(callback);
82
+ export const removeConfigWatcher = (callback: (config: LoggingConfig) => void) => loggingConfigManager.removeWatcher(callback);
@@ -0,0 +1,19 @@
1
+ export interface UnauthenticatedRouteConfig { pattern: string; description: string; allowDuringCircuitBreakerOpen?: boolean; requiresRateLimit?: boolean; }
2
+ export const UNAUTHENTICATED_ROUTES: UnauthenticatedRouteConfig[] = [
3
+ { pattern: '/account-auth/*', description: 'All authentication pages', allowDuringCircuitBreakerOpen: true },
4
+ { pattern: '/account-auth/login', description: 'Login page', allowDuringCircuitBreakerOpen: true },
5
+ { pattern: '/account-auth/verify-code', description: '2FA page', allowDuringCircuitBreakerOpen: true },
6
+ { pattern: '/api/auth/*', description: 'Auth API endpoints', allowDuringCircuitBreakerOpen: true, requiresRateLimit: true },
7
+ { pattern: '/api/session/refresh-viability', description: 'Refresh viability check', allowDuringCircuitBreakerOpen: true },
8
+ { pattern: '/landing', description: 'Public landing', allowDuringCircuitBreakerOpen: true },
9
+ { pattern: '/service-unavailable', description: 'Service unavailable', allowDuringCircuitBreakerOpen: true },
10
+ { pattern: '/favicon.ico', description: 'Favicon', allowDuringCircuitBreakerOpen: true },
11
+ { pattern: '/robots.txt', description: 'Robots.txt', allowDuringCircuitBreakerOpen: true },
12
+ { pattern: '/sitemap.xml', description: 'Sitemap', allowDuringCircuitBreakerOpen: true },
13
+ { pattern: '/_next/*', description: 'Next.js assets', allowDuringCircuitBreakerOpen: true },
14
+ { pattern: '/public/*', description: 'Public assets', allowDuringCircuitBreakerOpen: true }
15
+ ];
16
+ export function isUnauthenticatedRoute(pathname: string): boolean { return UNAUTHENTICATED_ROUTES.some(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); }
17
+ export function isAllowedDuringCircuitBreakerOpen(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.allowDuringCircuitBreakerOpen === true; }
18
+ export function requiresRateLimit(pathname: string): boolean { const route = UNAUTHENTICATED_ROUTES.find(route => route.pattern.endsWith('*') ? pathname.startsWith(route.pattern.slice(0, -1)) : pathname === route.pattern); return route?.requiresRateLimit === true; }
19
+ export default { UNAUTHENTICATED_ROUTES, isUnauthenticatedRoute, isAllowedDuringCircuitBreakerOpen, requiresRateLimit };
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Vibe Log Transport for Winston
3
+ *
4
+ * Buffers log entries to Redis for async processing by Vibe log drain.
5
+ * This avoids the "log database errors to database" chicken-and-egg problem.
6
+ *
7
+ * Features:
8
+ * - Async batch writing (doesn't block main thread)
9
+ * - Configurable minimum log level
10
+ * - Redis buffering with 1-week TTL
11
+ * - Graceful degradation on failure
12
+ */
13
+
14
+ import Transport from 'winston-transport';
15
+ import { getRedis } from '../lib/redis';
16
+
17
+ /** Redis key for pending log entries */
18
+ const REDIS_LOG_KEY = 'vibe:logs:pending';
19
+ /** TTL in seconds: 1 week */
20
+ const REDIS_LOG_TTL = 7 * 24 * 60 * 60;
21
+
22
+ export interface VibeLogTransportOptions extends Transport.TransportStreamOptions {
23
+ /** Redis URL (optional, uses REDIS_URL env var by default) */
24
+ redisUrl?: string;
25
+ /** Vibe client ID (for log metadata) */
26
+ vibeClientId?: string;
27
+ /** App slug for identification */
28
+ appSlug?: string;
29
+ /** Minimum level to send to Vibe (default: 'warn') */
30
+ minLevel?: string;
31
+ /** Batch size before flush (default: 10) */
32
+ batchSize?: number;
33
+ /** Flush interval in ms (default: 5000) */
34
+ flushInterval?: number;
35
+ /** Enable/disable the transport (default: true if Redis available) */
36
+ enabled?: boolean;
37
+ }
38
+
39
+ interface LogEntry {
40
+ level: string;
41
+ message: string;
42
+ timestamp: string;
43
+ category?: string;
44
+ meta?: Record<string, any>;
45
+ }
46
+
47
+ const LEVEL_ORDER: Record<string, number> = {
48
+ error: 0,
49
+ warn: 1,
50
+ info: 2,
51
+ http: 3,
52
+ debug: 4,
53
+ };
54
+
55
+ /**
56
+ * Winston transport that buffers logs to Redis for Vibe drain processing
57
+ */
58
+ export class VibeLogTransport extends Transport {
59
+ private vibeClientId: string;
60
+ private appSlug: string;
61
+ private minLevelNum: number;
62
+ private batchSize: number;
63
+ private flushInterval: number;
64
+ private enabled: boolean;
65
+ private redisAvailable: boolean = false;
66
+
67
+ private batch: LogEntry[] = [];
68
+ private flushTimer: NodeJS.Timeout | null = null;
69
+ private isFlushing = false;
70
+
71
+ constructor(opts: VibeLogTransportOptions = {}) {
72
+ super(opts);
73
+
74
+ this.vibeClientId = opts.vibeClientId || process.env.VIBE_CLIENT_ID || '';
75
+ this.appSlug = opts.appSlug || process.env.APP_SLUG || process.env.CLIENT_ID || 'mvp-app';
76
+ this.minLevelNum = LEVEL_ORDER[opts.minLevel || 'warn'] ?? 1;
77
+ this.batchSize = opts.batchSize || 10;
78
+ this.flushInterval = opts.flushInterval || 5000;
79
+
80
+ // Enable if Redis URL is configured
81
+ const redisUrl = opts.redisUrl || process.env.REDIS_URL || '';
82
+ this.enabled = opts.enabled !== false && !!redisUrl;
83
+ this.redisAvailable = !!redisUrl;
84
+
85
+ if (this.enabled) {
86
+ this.startFlushTimer();
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Winston transport log method
92
+ */
93
+ log(info: any, callback: () => void): void {
94
+ setImmediate(() => this.emit('logged', info));
95
+
96
+ if (!this.enabled) {
97
+ callback();
98
+ return;
99
+ }
100
+
101
+ const level = info.level?.replace(/\u001b\[\d+m/g, '') || 'info'; // Strip ANSI codes
102
+ const levelNum = LEVEL_ORDER[level] ?? 2;
103
+
104
+ // Only batch if at or above minimum level
105
+ if (levelNum <= this.minLevelNum) {
106
+ const entry: LogEntry = {
107
+ level,
108
+ message: info.message || '',
109
+ timestamp: info.timestamp || new Date().toISOString(),
110
+ category: this.extractCategory(info.message),
111
+ meta: this.extractMeta(info),
112
+ };
113
+
114
+ this.batch.push(entry);
115
+
116
+ // Flush immediately if batch is full or if error/fatal
117
+ if (this.batch.length >= this.batchSize || level === 'error') {
118
+ this.flush().catch(() => {}); // Ignore flush errors
119
+ }
120
+ }
121
+
122
+ callback();
123
+ }
124
+
125
+ /**
126
+ * Extract category from message prefix like [AUTH], [IDP], etc.
127
+ */
128
+ private extractCategory(message: string): string {
129
+ const match = message.match(/^\[([A-Z-]+)\]/);
130
+ return match ? match[1].toLowerCase() : 'app';
131
+ }
132
+
133
+ /**
134
+ * Extract metadata from winston info object
135
+ */
136
+ private extractMeta(info: any): Record<string, any> {
137
+ const { level, message, timestamp, ...rest } = info;
138
+ return Object.keys(rest).length > 0 ? rest : {};
139
+ }
140
+
141
+ /**
142
+ * Start the periodic flush timer
143
+ */
144
+ private startFlushTimer(): void {
145
+ if (this.flushTimer) return;
146
+
147
+ this.flushTimer = setInterval(() => {
148
+ if (this.batch.length > 0) {
149
+ this.flush().catch(() => {});
150
+ }
151
+ }, this.flushInterval);
152
+
153
+ // Don't prevent process exit
154
+ if (this.flushTimer.unref) {
155
+ this.flushTimer.unref();
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Flush batch to Vibe
161
+ */
162
+ async flush(): Promise<void> {
163
+ if (this.isFlushing || this.batch.length === 0) return;
164
+
165
+ this.isFlushing = true;
166
+ const entries = [...this.batch];
167
+ this.batch = [];
168
+
169
+ try {
170
+ await this.sendToVibe(entries);
171
+ } catch (err) {
172
+ // On failure, put entries back (up to limit to prevent memory issues)
173
+ if (this.batch.length < 100) {
174
+ this.batch = [...entries, ...this.batch].slice(0, 100);
175
+ }
176
+ // Log to console as fallback
177
+ console.error('[VibeLogTransport] Failed to flush logs:', err);
178
+ } finally {
179
+ this.isFlushing = false;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Push log entries to Redis for async drain processing
185
+ */
186
+ private async sendToVibe(entries: LogEntry[]): Promise<void> {
187
+ if (entries.length === 0) return;
188
+
189
+ const redis = getRedis();
190
+
191
+ // Format entries for the drain to process
192
+ const logRecords = entries.map(e => JSON.stringify({
193
+ level: e.level,
194
+ message: e.message,
195
+ timestamp: e.timestamp,
196
+ source: 'next-mvp',
197
+ app_slug: this.appSlug,
198
+ vibe_client_id: this.vibeClientId,
199
+ category: e.category,
200
+ error_code: e.meta?.errorCode || e.meta?.error_code,
201
+ stack: e.meta?.stack,
202
+ request_id: e.meta?.requestId || e.meta?.request_id,
203
+ user_id: e.meta?.userId || e.meta?.user_id,
204
+ path: e.meta?.path,
205
+ method: e.meta?.method,
206
+ status_code: e.meta?.statusCode || e.meta?.status_code,
207
+ duration_ms: e.meta?.durationMs || e.meta?.duration_ms,
208
+ meta: e.meta,
209
+ queued_at: new Date().toISOString(),
210
+ }));
211
+
212
+ // LPUSH all entries (newest first, drain will RPOP for FIFO)
213
+ await redis.lpush(REDIS_LOG_KEY, ...logRecords);
214
+
215
+ // Reset TTL on each write (1 week from last activity)
216
+ await redis.expire(REDIS_LOG_KEY, REDIS_LOG_TTL);
217
+ }
218
+
219
+ /**
220
+ * Close transport and flush remaining logs
221
+ */
222
+ close(): void {
223
+ if (this.flushTimer) {
224
+ clearInterval(this.flushTimer);
225
+ this.flushTimer = null;
226
+ }
227
+
228
+ // Final flush (best effort)
229
+ if (this.batch.length > 0) {
230
+ this.flush().catch(() => {});
231
+ }
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Create a configured VibeLogTransport instance
237
+ * Returns null if Redis is not configured (REDIS_URL env var)
238
+ */
239
+ export function createVibeLogTransport(opts?: VibeLogTransportOptions): VibeLogTransport | null {
240
+ const transport = new VibeLogTransport(opts);
241
+
242
+ // Return null if transport is disabled (no Redis)
243
+ if (!transport['enabled']) {
244
+ return null;
245
+ }
246
+
247
+ return transport;
248
+ }
249
+
250
+ export default VibeLogTransport;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Internal API URL Utility for Edge Runtime
3
+ *
4
+ * INTERNAL_API_URL is REQUIRED. This is the URL for THIS application calling ITSELF.
5
+ * Used for middleware to call its own API routes (e.g., /api/session/viability).
6
+ *
7
+ * WHY HTTP IS REQUIRED (not optional):
8
+ * - This is the app calling its OWN backend within the same pod/container
9
+ * - NextAuth cookies are encrypted based on request protocol
10
+ * - TLS is terminated at ingress, so the pod receives HTTP internally
11
+ * - Using HTTPS here causes cookie decryption failures
12
+ * - This is NOT about "K8s internal traffic doesn't need TLS" - it's about
13
+ * protocol consistency for cookie encryption
14
+ *
15
+ * This is NOT for calling the IDP - use IDP_URL for that.
16
+ *
17
+ * For local dev, set INTERNAL_API_URL=http://localhost:3000 (or your dev port).
18
+ *
19
+ * @module edge/internal-api-url
20
+ * @version 3.0.0
21
+ */
22
+
23
+ import { NextRequest } from 'next/server';
24
+
25
+ /**
26
+ * Get the internal API base URL for middleware to call its own API routes.
27
+ *
28
+ * THROWS if INTERNAL_API_URL is not set. No fallbacks.
29
+ *
30
+ * @param request - The Next.js request object (unused, kept for API compatibility)
31
+ * @returns Base URL string for constructing internal API calls
32
+ * @throws Error if INTERNAL_API_URL environment variable is not set
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { getInternalApiUrl } from '@payez/next-mvp/edge';
37
+ *
38
+ * export async function middleware(request: NextRequest) {
39
+ * const baseUrl = getInternalApiUrl(request);
40
+ * const apiUrl = new URL('/api/session/check', baseUrl);
41
+ *
42
+ * const response = await fetch(apiUrl, {
43
+ * headers: {
44
+ * 'Cookie': request.headers.get('cookie') || ''
45
+ * }
46
+ * });
47
+ * }
48
+ * ```
49
+ *
50
+ * @environment INTERNAL_API_URL - REQUIRED. URL for this app to call ITSELF.
51
+ * MUST be HTTP (not HTTPS) - see module docs for why.
52
+ * K8s: http://myapp.namespace.svc.cluster.local:80
53
+ * Local: http://localhost:3000
54
+ */
55
+ export function getInternalApiUrl(request: NextRequest): string {
56
+ const internalUrl = process.env.INTERNAL_API_URL;
57
+ if (!internalUrl) {
58
+ throw new Error(
59
+ '[INTERNAL_API_URL] FATAL: INTERNAL_API_URL environment variable is REQUIRED. ' +
60
+ 'This is for the app to call ITSELF. MUST be HTTP (not HTTPS). ' +
61
+ 'Set to http://myapp.namespace.svc.cluster.local:80 (K8s) or http://localhost:3000 (local).'
62
+ );
63
+ }
64
+ return internalUrl;
65
+ }