@jmruthers/pace-core 0.5.135 → 0.5.137

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 (544) hide show
  1. package/dist/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
  2. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
  4. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  5. package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
  6. package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
  7. package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
  8. package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
  9. package/dist/chunk-22WKWKRX.js.map +1 -0
  10. package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
  11. package/dist/chunk-4C7EXCAR.js.map +1 -0
  12. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  13. package/dist/chunk-56XJ3TU6.js.map +1 -0
  14. package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
  15. package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
  16. package/dist/chunk-7QCC6MCP.js.map +1 -0
  17. package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
  18. package/dist/chunk-ANBQRTPX.js.map +1 -0
  19. package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
  20. package/dist/chunk-BCIBECNB.js.map +1 -0
  21. package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
  22. package/dist/chunk-BESYRHQM.js.map +1 -0
  23. package/dist/chunk-BJPBT3CU.js +21 -0
  24. package/dist/chunk-BJPBT3CU.js.map +1 -0
  25. package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
  26. package/dist/chunk-BLCXZEYF.js.map +1 -0
  27. package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  28. package/dist/chunk-BVYWGZVV.js.map +1 -0
  29. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  30. package/dist/chunk-ERISIBYU.js.map +1 -0
  31. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  32. package/dist/chunk-FMUCXFII.js.map +1 -0
  33. package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
  34. package/dist/chunk-HAWZXGR2.js.map +1 -0
  35. package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
  36. package/dist/chunk-JISYG63F.js +70 -0
  37. package/dist/chunk-JISYG63F.js.map +1 -0
  38. package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
  39. package/dist/chunk-KYRHUBIU.js.map +1 -0
  40. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  41. package/dist/chunk-LS353YLY.js.map +1 -0
  42. package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
  43. package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
  44. package/dist/chunk-OWAG3GSU.js +58 -0
  45. package/dist/chunk-OWAG3GSU.js.map +1 -0
  46. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  47. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  48. package/dist/chunk-S5OFRT4M.js +94 -0
  49. package/dist/chunk-S5OFRT4M.js.map +1 -0
  50. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  51. package/dist/chunk-SBVILCCA.js.map +1 -0
  52. package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
  53. package/dist/chunk-T6JN6LH6.js.map +1 -0
  54. package/dist/chunk-XDNLUEXI.js +138 -0
  55. package/dist/chunk-XDNLUEXI.js.map +1 -0
  56. package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
  57. package/dist/chunk-YCWDTTUK.js.map +1 -0
  58. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  59. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  60. package/dist/components.d.ts +7 -287
  61. package/dist/components.js +27 -157
  62. package/dist/components.js.map +1 -1
  63. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  64. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  65. package/dist/hooks.d.ts +3 -3
  66. package/dist/hooks.js +21 -16
  67. package/dist/hooks.js.map +1 -1
  68. package/dist/index.d.ts +101 -9
  69. package/dist/index.js +44 -31
  70. package/dist/index.js.map +1 -1
  71. package/dist/providers.d.ts +1 -1
  72. package/dist/providers.js +4 -4
  73. package/dist/rbac/index.js +12 -12
  74. package/dist/schema-DTDZQe2u.d.ts +28 -0
  75. package/dist/styles/index.js +2 -1
  76. package/dist/theming/runtime.d.ts +2 -19
  77. package/dist/theming/runtime.js +2 -1
  78. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  79. package/dist/types.d.ts +153 -4
  80. package/dist/types.js +51 -16
  81. package/dist/types.js.map +1 -1
  82. package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
  83. package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
  84. package/dist/utils.d.ts +221 -173
  85. package/dist/utils.js +185 -225
  86. package/dist/utils.js.map +1 -1
  87. package/dist/validation.d.ts +24 -115
  88. package/dist/validation.js +19 -474
  89. package/dist/validation.js.map +1 -1
  90. package/docs/api/classes/ColumnFactory.md +1 -1
  91. package/docs/api/classes/ErrorBoundary.md +6 -6
  92. package/docs/api/classes/InvalidScopeError.md +1 -1
  93. package/docs/api/classes/MissingUserContextError.md +1 -1
  94. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  95. package/docs/api/classes/PermissionDeniedError.md +1 -1
  96. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  97. package/docs/api/classes/RBACAuditManager.md +6 -6
  98. package/docs/api/classes/RBACCache.md +1 -1
  99. package/docs/api/classes/RBACEngine.md +7 -7
  100. package/docs/api/classes/RBACError.md +1 -1
  101. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  102. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  103. package/docs/api/classes/StorageUtils.md +1 -1
  104. package/docs/api/enums/FileCategory.md +1 -1
  105. package/docs/api/interfaces/AggregateConfig.md +4 -4
  106. package/docs/api/interfaces/BadgeProps.md +27 -0
  107. package/docs/api/interfaces/ButtonProps.md +1 -1
  108. package/docs/api/interfaces/CardProps.md +1 -1
  109. package/docs/api/interfaces/ColorPalette.md +1 -1
  110. package/docs/api/interfaces/ColorShade.md +29 -4
  111. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  112. package/docs/api/interfaces/DataRecord.md +1 -1
  113. package/docs/api/interfaces/DataTableAction.md +18 -18
  114. package/docs/api/interfaces/DataTableColumn.md +61 -1
  115. package/docs/api/interfaces/DataTableProps.md +1 -1
  116. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  117. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  118. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
  119. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  120. package/docs/api/interfaces/EventLogoProps.md +152 -0
  121. package/docs/api/interfaces/ExportColumn.md +1 -1
  122. package/docs/api/interfaces/ExportOptions.md +8 -8
  123. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  124. package/docs/api/interfaces/FileMetadata.md +1 -1
  125. package/docs/api/interfaces/FileReference.md +1 -1
  126. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  127. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  128. package/docs/api/interfaces/FileUploadProps.md +1 -1
  129. package/docs/api/interfaces/FooterProps.md +1 -1
  130. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  131. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  132. package/docs/api/interfaces/InputProps.md +1 -1
  133. package/docs/api/interfaces/LabelProps.md +1 -1
  134. package/docs/api/interfaces/LoginFormProps.md +1 -1
  135. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  136. package/docs/api/interfaces/NavigationContextType.md +9 -9
  137. package/docs/api/interfaces/NavigationGuardProps.md +10 -10
  138. package/docs/api/interfaces/NavigationItem.md +1 -1
  139. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  140. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  141. package/docs/api/interfaces/Organisation.md +1 -1
  142. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  143. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  144. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  145. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  146. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  147. package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
  148. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  149. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  150. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  151. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  152. package/docs/api/interfaces/PaletteData.md +4 -4
  153. package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
  154. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  155. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  156. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  157. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  158. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  159. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  160. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  161. package/docs/api/interfaces/RBACConfig.md +1 -1
  162. package/docs/api/interfaces/RBACLogger.md +1 -1
  163. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  164. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  165. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  166. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  167. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  168. package/docs/api/interfaces/RouteConfig.md +10 -10
  169. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  170. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  171. package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
  172. package/docs/api/interfaces/StorageConfig.md +1 -1
  173. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  174. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  175. package/docs/api/interfaces/StorageListOptions.md +1 -1
  176. package/docs/api/interfaces/StorageListResult.md +1 -1
  177. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  178. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  179. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  180. package/docs/api/interfaces/StyleImport.md +1 -1
  181. package/docs/api/interfaces/SwitchProps.md +1 -1
  182. package/docs/api/interfaces/ToastActionElement.md +1 -1
  183. package/docs/api/interfaces/ToastProps.md +1 -1
  184. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  185. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  186. package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
  187. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  188. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  189. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  190. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  191. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
  192. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  193. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  194. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  195. package/docs/api/interfaces/UserEventAccess.md +11 -11
  196. package/docs/api/interfaces/UserMenuProps.md +1 -1
  197. package/docs/api/interfaces/UserProfile.md +1 -1
  198. package/docs/api/modules.md +591 -220
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -3
  201. package/docs/implementation-guides/data-tables.md +277 -13
  202. package/docs/implementation-guides/forms.md +1 -16
  203. package/docs/implementation-guides/permission-enforcement.md +8 -2
  204. package/docs/styles/README.md +0 -2
  205. package/examples/README.md +30 -14
  206. package/examples/STRUCTURE.md +125 -0
  207. package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
  208. package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
  209. package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
  210. package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
  211. package/examples/components 2/DataTable/index.ts +13 -0
  212. package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
  213. package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
  214. package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
  215. package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
  216. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
  217. package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
  218. package/examples/components 2/Dialog/index.ts +15 -0
  219. package/examples/components 2/index.ts +11 -0
  220. package/examples/features/index.ts +12 -0
  221. package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
  222. package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
  223. package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
  224. package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
  225. package/examples/features/public-pages/index.ts +14 -0
  226. package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
  227. package/examples/features/rbac/EventBasedApp.tsx +239 -0
  228. package/examples/features/rbac/PermissionExample.tsx +151 -0
  229. package/examples/features/rbac/index.ts +13 -0
  230. package/examples/index.ts +11 -3
  231. package/package.json +30 -19
  232. package/src/__tests__/TEST_STANDARD.md +92 -0
  233. package/src/components/Alert/Alert.tsx +1 -1
  234. package/src/components/Avatar/Avatar.tsx +1 -1
  235. package/src/components/Badge/Badge.test.tsx +314 -0
  236. package/src/components/Badge/Badge.tsx +304 -0
  237. package/src/components/Badge/index.ts +3 -0
  238. package/src/components/Button/Button.tsx +1 -1
  239. package/src/components/Card/Card.tsx +1 -1
  240. package/src/components/Checkbox/Checkbox.tsx +1 -1
  241. package/src/components/DataTable/DataTable.test.tsx +1 -1
  242. package/src/components/DataTable/DataTable.tsx +1 -30
  243. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  244. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
  245. package/src/components/DataTable/__tests__/styles.test.ts +3 -3
  246. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  247. package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
  248. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  249. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  250. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  252. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  253. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  254. package/src/components/DataTable/components/FilterRow.tsx +9 -3
  255. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  256. package/src/components/DataTable/components/PaginationControls.tsx +2 -1
  257. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  258. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  259. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
  260. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  261. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
  262. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  263. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  264. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
  265. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  266. package/src/components/DataTable/core/ActionManager.ts +235 -0
  267. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  268. package/src/components/DataTable/core/DataManager.ts +188 -0
  269. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  270. package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
  271. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  272. package/src/components/DataTable/core/StateManager.ts +311 -0
  273. package/src/components/DataTable/core/interfaces.ts +338 -0
  274. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  275. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  276. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  277. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  278. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  280. package/src/components/DataTable/index.ts +4 -0
  281. package/src/components/DataTable/styles.ts +28 -7
  282. package/src/components/DataTable/types.ts +13 -0
  283. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
  284. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  285. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  286. package/src/components/DataTable/utils/columnUtils.ts +40 -0
  287. package/src/components/DataTable/utils/debugTools.ts +609 -0
  288. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  289. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  290. package/src/components/DataTable/utils/index.ts +2 -0
  291. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  292. package/src/components/Dialog/Dialog.tsx +2 -2
  293. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
  294. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  295. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  296. package/src/components/EventSelector/EventSelector.tsx +3 -2
  297. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  298. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  299. package/src/components/FileUpload/FileUpload.tsx +2 -2
  300. package/src/components/Footer/Footer.test.tsx +1 -1
  301. package/src/components/Footer/Footer.tsx +1 -1
  302. package/src/components/Form/Form.test.tsx +5 -510
  303. package/src/components/Form/Form.tsx +1 -1
  304. package/src/components/Form/FormField.tsx +1 -1
  305. package/src/components/Form/index.ts +0 -12
  306. package/src/components/Header/Header.tsx +1 -1
  307. package/src/components/Input/Input.tsx +1 -1
  308. package/src/components/Label/Label.tsx +1 -1
  309. package/src/components/LoginForm/LoginForm.test.tsx +1 -1
  310. package/src/components/LoginForm/LoginForm.tsx +1 -1
  311. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  312. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  313. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  314. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  315. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  316. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
  317. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  318. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  319. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  320. package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
  321. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  322. package/src/components/PasswordReset/index.ts +0 -2
  323. package/src/components/Progress/Progress.tsx +1 -1
  324. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  325. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  326. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  327. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  328. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  329. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  330. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  331. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  332. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  333. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
  334. package/src/components/PublicLayout/index.ts +4 -2
  335. package/src/components/Select/Select.test.tsx +1 -1
  336. package/src/components/Select/Select.tsx +21 -9
  337. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  338. package/src/components/SessionRestorationLoader/index.ts +3 -0
  339. package/src/components/Switch/Switch.tsx +1 -1
  340. package/src/components/Table/Table.tsx +1 -1
  341. package/src/components/Table/__tests__/Table.test.tsx +1 -1
  342. package/src/components/Toast/Toast.tsx +1 -1
  343. package/src/components/Tooltip/Tooltip.tsx +1 -1
  344. package/src/components/index.ts +7 -10
  345. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  346. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  347. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  348. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  349. package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
  350. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  351. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  352. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  353. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  354. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  355. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  356. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  357. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  358. package/src/hooks/public/usePublicEvent.ts +7 -6
  359. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  360. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  361. package/src/hooks/useComponentPerformance.ts +4 -1
  362. package/src/hooks/useDataTablePerformance.ts +4 -3
  363. package/src/hooks/useEventTheme.test.ts +18 -5
  364. package/src/hooks/useEventTheme.ts +4 -1
  365. package/src/hooks/useEvents.ts +2 -0
  366. package/src/hooks/useFileDisplay.ts +9 -8
  367. package/src/hooks/useFileReference.ts +4 -1
  368. package/src/hooks/useFileUrl.ts +4 -1
  369. package/src/hooks/useInactivityTracker.ts +5 -4
  370. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  371. package/src/hooks/useOrganisationSecurity.ts +8 -7
  372. package/src/hooks/usePerformanceMonitor.ts +6 -3
  373. package/src/hooks/usePermissionCache.ts +13 -6
  374. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  375. package/src/hooks/useSecureDataAccess.ts +9 -8
  376. package/src/hooks/useSessionRestoration.ts +4 -1
  377. package/src/hooks/useStorage.ts +4 -1
  378. package/src/index.ts +20 -7
  379. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  380. package/src/providers/services/EventServiceProvider.tsx +2 -1
  381. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  382. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  383. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  384. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  385. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  386. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  387. package/src/rbac/api.ts +5 -2
  388. package/src/rbac/audit-enhanced.ts +6 -6
  389. package/src/rbac/audit.test.ts +60 -38
  390. package/src/rbac/audit.ts +8 -8
  391. package/src/rbac/cache-invalidation.ts +7 -4
  392. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  393. package/src/rbac/components/NavigationGuard.tsx +7 -3
  394. package/src/rbac/components/NavigationProvider.tsx +6 -3
  395. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  396. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  397. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  398. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  399. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  400. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  401. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  402. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  403. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  404. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  405. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  406. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  407. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  408. package/src/rbac/engine.ts +15 -7
  409. package/src/rbac/hooks/usePermissions.ts +7 -3
  410. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  411. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  412. package/src/rbac/permissions.ts +5 -2
  413. package/src/rbac/security.test.ts +27 -16
  414. package/src/rbac/security.ts +5 -4
  415. package/src/services/AuthService.ts +22 -21
  416. package/src/services/EventService.ts +12 -12
  417. package/src/services/InactivityService.ts +5 -4
  418. package/src/services/OrganisationService.ts +26 -25
  419. package/src/services/__tests__/AuthService.test.ts +51 -19
  420. package/src/services/__tests__/EventService.test.ts +37 -5
  421. package/src/services/__tests__/InactivityService.test.ts +38 -4
  422. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  423. package/src/services/base/BaseService.ts +3 -1
  424. package/src/styles/core.css +3 -0
  425. package/src/theming/__tests__/runtime.test.ts +21 -12
  426. package/src/theming/parseEventColours.ts +5 -19
  427. package/src/theming/runtime.ts +8 -4
  428. package/src/types/validation.ts +2 -29
  429. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  430. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  431. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  432. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  433. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  434. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  435. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  436. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  437. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  438. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  439. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  440. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  441. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  442. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  443. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  444. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  445. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  446. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  447. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  448. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  449. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  450. package/src/utils/__tests__/security.unit.test.ts +40 -18
  451. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  452. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  453. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  454. package/src/utils/app/appConfig.ts +47 -0
  455. package/src/utils/app/appIdResolver.test.ts +497 -0
  456. package/src/utils/app/appIdResolver.ts +133 -0
  457. package/src/utils/app/appNameResolver.simple.test.ts +212 -0
  458. package/src/utils/app/appNameResolver.test.ts +121 -0
  459. package/src/utils/app/appNameResolver.ts +195 -0
  460. package/src/utils/audit/audit.ts +127 -0
  461. package/src/utils/context/organisationContext.test.ts +322 -0
  462. package/src/utils/context/organisationContext.ts +156 -0
  463. package/src/utils/context/sessionTracking.ts +125 -0
  464. package/src/utils/core/cn.ts +7 -0
  465. package/src/utils/core/debugLogger.ts +67 -0
  466. package/src/utils/core/logger.ts +181 -0
  467. package/src/utils/device/deviceFingerprint.ts +215 -0
  468. package/src/utils/dynamic/dynamicUtils.ts +105 -0
  469. package/src/utils/dynamic/lazyLoad.tsx +44 -0
  470. package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
  471. package/src/utils/file-reference/index.ts +501 -0
  472. package/src/utils/formatting/formatDate.test.ts +237 -0
  473. package/src/utils/formatting/formatting.ts +133 -0
  474. package/src/utils/index.ts +39 -54
  475. package/src/utils/performance/bundleAnalysis.ts +129 -0
  476. package/src/utils/performance/performanceBenchmark.ts +64 -0
  477. package/src/utils/performance/performanceBudgets.ts +110 -0
  478. package/src/utils/permissions/permissionTypes.ts +37 -0
  479. package/src/utils/permissions/permissionUtils.test.ts +393 -0
  480. package/src/utils/permissions/permissionUtils.ts +34 -0
  481. package/src/utils/security/auth-utils.ts +96 -0
  482. package/src/utils/security/secureDataAccess.test.ts +711 -0
  483. package/src/utils/security/secureDataAccess.ts +377 -0
  484. package/src/utils/security/secureErrors.ts +82 -0
  485. package/src/utils/security/secureStorage.ts +244 -0
  486. package/src/utils/security/security.ts +159 -0
  487. package/src/utils/security/securityMonitor.ts +45 -0
  488. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  489. package/src/utils/storage/helpers.ts +15 -8
  490. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
  491. package/src/{validation → utils/validation}/csrf.ts +1 -1
  492. package/src/utils/validation/htmlSanitization.ts +184 -0
  493. package/src/utils/validation/index.ts +79 -0
  494. package/src/utils/validation/sanitization.ts +333 -0
  495. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  496. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  497. package/src/utils/validation/validation.ts +111 -0
  498. package/src/utils/validation/validationUtils.ts +123 -0
  499. package/src/validation/index.ts +3 -34
  500. package/dist/chunk-24MKLB7U.js +0 -81
  501. package/dist/chunk-24MKLB7U.js.map +0 -1
  502. package/dist/chunk-3CG5L6RN.js.map +0 -1
  503. package/dist/chunk-3DBFLLLU.js.map +0 -1
  504. package/dist/chunk-5F3NDPJV.js.map +0 -1
  505. package/dist/chunk-66C4BSAY.js.map +0 -1
  506. package/dist/chunk-BDZUMRBD.js +0 -87
  507. package/dist/chunk-BDZUMRBD.js.map +0 -1
  508. package/dist/chunk-BYXRHAIF.js.map +0 -1
  509. package/dist/chunk-CDQ3PX7L.js +0 -18
  510. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  511. package/dist/chunk-CQZU6TFE.js.map +0 -1
  512. package/dist/chunk-F64FFPOZ.js.map +0 -1
  513. package/dist/chunk-GEVIB2UB.js.map +0 -1
  514. package/dist/chunk-GKHF54DI.js.map +0 -1
  515. package/dist/chunk-GVDR7WNV.js.map +0 -1
  516. package/dist/chunk-HMNOSGVA.js.map +0 -1
  517. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  518. package/dist/chunk-M6DDYFUD.js.map +0 -1
  519. package/dist/chunk-O3NWNXDY.js.map +0 -1
  520. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  521. package/dist/chunk-UJI6WSMD.js.map +0 -1
  522. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  523. package/dist/chunk-WP5I5GLN.js.map +0 -1
  524. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  525. package/dist/validation-DnhrNMju.d.ts +0 -159
  526. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  527. package/src/validation/__tests__/common.unit.test.ts +0 -101
  528. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  529. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  530. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  531. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  532. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  533. package/src/validation/__tests__/user.unit.test.ts +0 -440
  534. package/src/validation/sanitization.ts +0 -96
  535. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
  536. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
  537. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  538. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  539. /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
  540. /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
  541. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  542. /package/src/{validation → utils/validation}/common.ts +0 -0
  543. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  544. /package/src/{validation → utils/validation}/user.ts +0 -0
@@ -193,7 +193,7 @@
193
193
 
194
194
  import * as React from "react";
195
195
  import { Menu, ChevronDown } from "lucide-react";
196
- import { cn } from "../../utils/cn";
196
+ import { cn } from "../../utils/core/cn";
197
197
  import { NavigationMenuProps, NavigationItem } from "./types";
198
198
  import { Button } from "../Button";
199
199
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../Select";
@@ -202,6 +202,7 @@ import { useRBAC } from "../../rbac/hooks/useRBAC";
202
202
  import { useResolvedScope } from "../../rbac/hooks";
203
203
  import { usePermissions } from "../../rbac/hooks/usePermissions";
204
204
  import type { Permission, AccessLevel as RBACAccessLevel } from "../../rbac/types";
205
+ import { logger } from "../../utils/core/logger";
205
206
 
206
207
  /**
207
208
  * Unified NavigationMenu component that supports both dropdown and hierarchical navigation modes.
@@ -424,7 +425,7 @@ export const NavigationMenu = React.forwardRef<
424
425
  authContext = useUnifiedAuth();
425
426
  } catch (error) {
426
427
  // NavigationMenu is being used outside of UnifiedAuthProvider
427
- console.warn('[NavigationMenu] useUnifiedAuth not available, running in unauthenticated mode');
428
+ logger.warn('NavigationMenu', 'useUnifiedAuth not available, running in unauthenticated mode');
428
429
  }
429
430
 
430
431
  // Get RBAC context for permission and role checks
@@ -433,7 +434,7 @@ export const NavigationMenu = React.forwardRef<
433
434
  rbacContext = useRBAC();
434
435
  } catch (error) {
435
436
  // RBAC not available - permission filtering will be disabled
436
- console.warn('[NavigationMenu] useRBAC not available, permission filtering disabled');
437
+ logger.warn('NavigationMenu', 'useRBAC not available, permission filtering disabled');
437
438
  }
438
439
 
439
440
  // Get resolved scope for permission checks
@@ -524,7 +525,7 @@ export const NavigationMenu = React.forwardRef<
524
525
  // If there's an error or empty permission map after loading, show nothing
525
526
  // Security: Better to show nothing than risk showing unauthorized items
526
527
  if (permissionsError || !permissionMap || Object.keys(permissionMap).length === 0) {
527
- console.warn('[NavigationMenu] Permission map is empty or has error - showing no items for security', {
528
+ logger.warn('NavigationMenu', 'Permission map is empty or has error - showing no items for security', {
528
529
  permissionsError: permissionsError?.message,
529
530
  permissionMapSize: permissionMap ? Object.keys(permissionMap).length : 0
530
531
  });
@@ -643,7 +644,7 @@ export const NavigationMenu = React.forwardRef<
643
644
 
644
645
  if (!finalHasPermission) {
645
646
  if (auditLog) {
646
- console.log(`[NavigationMenu] Filtering out navigation item "${item.label}" - no page permission:`, {
647
+ logger.debug('NavigationMenu', `Filtering out navigation item "${item.label}" - no page permission:`, {
647
648
  itemId: item.id,
648
649
  href: item.href,
649
650
  pageId,
@@ -716,7 +717,7 @@ export const NavigationMenu = React.forwardRef<
716
717
  // Log navigation access attempts for debugging
717
718
  React.useEffect(() => {
718
719
  if (auditLog && authContext) {
719
- console.log('[NavigationMenu] Navigation access attempt:', {
720
+ logger.debug('NavigationMenu', 'Navigation access attempt:', {
720
721
  itemId: 'navigation-menu',
721
722
  label: 'Navigation Menu',
722
723
  href: currentPath,
@@ -766,7 +767,7 @@ export const NavigationMenu = React.forwardRef<
766
767
  // NEW: Phase 2 - Enhanced Security Features
767
768
  // Log navigation access attempt for audit
768
769
  if (auditLog) {
769
- console.log(`[NavigationMenu] Navigation access attempt:`, {
770
+ logger.debug('NavigationMenu', 'Navigation access attempt:', {
770
771
  itemId: item.id,
771
772
  label: item.label,
772
773
  href: item.href,
@@ -842,7 +843,7 @@ export const NavigationMenu = React.forwardRef<
842
843
  }
843
844
 
844
845
  if (strictMode) {
845
- console.error(`[NavigationMenu] STRICT MODE VIOLATION: User attempted to access protected navigation item without permission`, {
846
+ logger.error('NavigationMenu', 'STRICT MODE VIOLATION: User attempted to access protected navigation item without permission', {
846
847
  itemId: item.id,
847
848
  label: item.label,
848
849
  href: item.href,
@@ -61,6 +61,7 @@ import { LoadingSpinner } from '../LoadingSpinner/LoadingSpinner';
61
61
  import { RefreshCw, AlertCircle, Building2, Shield } from 'lucide-react';
62
62
  import { useOrganisations } from '../../providers/OrganisationProvider';
63
63
  import type { Organisation } from '../../types/organisation';
64
+ import { logger } from '../../utils/core/logger';
64
65
 
65
66
  export interface OrganisationSelectorProps {
66
67
  /** Placeholder text for the dropdown */
@@ -137,9 +138,9 @@ export function OrganisationSelector({
137
138
  onOrganisationChange(newOrganisation);
138
139
  }
139
140
 
140
- console.log("[OrganisationSelector] Successfully switched to organisation:", orgId);
141
+ logger.debug('OrganisationSelector', 'Successfully switched to organisation:', orgId);
141
142
  } catch (error) {
142
- console.error("[OrganisationSelector] Failed to switch organisation:", error);
143
+ logger.error('OrganisationSelector', 'Failed to switch organisation:', error);
143
144
  setSwitchError(error instanceof Error ? error.message : 'Failed to switch organisation');
144
145
  } finally {
145
146
  setIsLoading(false);
@@ -159,7 +160,7 @@ export function OrganisationSelector({
159
160
  try {
160
161
  await refreshOrganisations();
161
162
  } catch (error) {
162
- console.error("[OrganisationSelector] Failed to refresh organisations:", error);
163
+ logger.error('OrganisationSelector', 'Failed to refresh organisations:', error);
163
164
  setSwitchError('Failed to refresh organisations');
164
165
  } finally {
165
166
  setIsLoading(false);
@@ -105,8 +105,9 @@ import { useEvents } from '../../hooks/useEvents';
105
105
  import { useEventTheme } from '../../hooks/useEventTheme';
106
106
  import { useCan, useResolvedScope } from '../../rbac/hooks';
107
107
  import { createScopeFromEvent } from '../../rbac/utils/eventContext';
108
- import { getCurrentAppName } from '../../utils/appNameResolver';
108
+ import { getCurrentAppName } from '../../utils/app/appNameResolver';
109
109
  import { isSuperAdmin } from '../../rbac/api';
110
+ import { logger } from '../../utils/core/logger';
110
111
  import type { Permission, Scope } from '../../rbac/types';
111
112
 
112
113
  // Stable empty objects to prevent infinite loops
@@ -465,7 +466,7 @@ export function PaceAppLayout({
465
466
  const superAdminStatus = await isSuperAdmin(user.id);
466
467
  setIsSuperAdminUser(superAdminStatus);
467
468
  } catch (error) {
468
- console.error('[PaceAppLayout] Error checking super admin status:', error);
469
+ logger.error('PaceAppLayout', 'Error checking super admin status', { userId: user?.id, error });
469
470
  setIsSuperAdminUser(false);
470
471
  } finally {
471
472
  setIsCheckingSuperAdmin(false);
@@ -506,7 +507,7 @@ export function PaceAppLayout({
506
507
  // NEW: Phase 1 - Enhanced Security Features
507
508
  // Handle strict mode violations - skip for super admins
508
509
  if (strictMode && !isSuperAdminUser && !can) {
509
- console.error(`[PaceAppLayout] STRICT MODE VIOLATION: User attempted to access protected page without permission`, {
510
+ logger.error('PaceAppLayout', 'STRICT MODE VIOLATION: User attempted to access protected page without permission', {
510
511
  pageName: currentPageId,
511
512
  operation: currentRoutePermission,
512
513
  userId: user?.id,
@@ -626,7 +627,7 @@ export function PaceAppLayout({
626
627
  } catch (error) {
627
628
  // On error, fall back to showing all items (graceful degradation)
628
629
  // This prevents navigation from being empty if permission checks fail
629
- console.error('[PaceAppLayout] Failed to load permission map for navigation filtering:', error);
630
+ logger.error('PaceAppLayout', 'Failed to load permission map for navigation filtering', { userId: user?.id, error });
630
631
  if (isMounted) {
631
632
  setFilteredMenuItems(baseMenuItems);
632
633
  }
@@ -654,7 +655,7 @@ export function PaceAppLayout({
654
655
  if (!currentRoute) {
655
656
  // Route not found in configuration
656
657
  if (strictMode) {
657
- console.error(`[PaceAppLayout] STRICT MODE VIOLATION: Route not found in configuration`, {
658
+ logger.error('PaceAppLayout', 'STRICT MODE VIOLATION: Route not found in configuration', {
658
659
  route: currentPath,
659
660
  userId: user?.id,
660
661
  timestamp: new Date().toISOString()
@@ -685,7 +686,7 @@ export function PaceAppLayout({
685
686
  if (!isMounted) return;
686
687
  hasAccess = hasPagePermission;
687
688
  } catch (error) {
688
- console.error('[PaceAppLayout] Failed to check page permission:', error);
689
+ logger.error('PaceAppLayout', 'Failed to check page permission', { route: currentPath, pageId: currentRoute.pageId, error });
689
690
  if (!isMounted) return;
690
691
  hasAccess = false;
691
692
  }
@@ -709,7 +710,7 @@ export function PaceAppLayout({
709
710
  }
710
711
 
711
712
  if (strictMode) {
712
- console.error(`[PaceAppLayout] STRICT MODE VIOLATION: User attempted to access protected route without permission`, {
713
+ logger.error('PaceAppLayout', 'STRICT MODE VIOLATION: User attempted to access protected route without permission', {
713
714
  route: currentPath,
714
715
  userId: user?.id,
715
716
  permissions: currentRoute.permissions,
@@ -745,15 +746,16 @@ export function PaceAppLayout({
745
746
  const result = await updatePassword(newPassword);
746
747
  if (result?.error) {
747
748
  // The form will display the error message
748
- console.error('Failed to change password:', result.error.message);
749
+ logger.error('PaceAppLayout', 'Failed to change password', { error: result.error.message });
749
750
  }
750
751
  // The form will handle closing the modal on success
751
752
  return result || { error: null };
752
753
  };
753
754
 
754
755
  // Show loading state while checking permissions or super admin status
755
- // But don't show loading if we already have a permission error (prioritize error display)
756
- if (enforcePermissions && (isCheckingSuperAdmin || isCheckingPermission) && !permissionError) {
756
+ // Keep loading active until BOTH checks complete to prevent exposing protected content
757
+ // This ensures we don't render the main layout when permission check failed but super admin check is pending
758
+ if (enforcePermissions && (isCheckingSuperAdmin || isCheckingPermission)) {
757
759
  return (
758
760
  <div className="flex items-center justify-center min-h-screen">
759
761
  <div className="text-center">
@@ -764,9 +766,9 @@ export function PaceAppLayout({
764
766
  );
765
767
  }
766
768
 
767
- // Show permission error (check this after loading state, but only if super admin check is complete)
769
+ // Show permission error (only after BOTH checks are complete)
768
770
  // Super admins bypass all permission checks, so don't show errors for them
769
- if (enforcePermissions && permissionError && !isCheckingSuperAdmin && !isSuperAdminUser) {
771
+ if (enforcePermissions && permissionError && !isSuperAdminUser) {
770
772
  return (
771
773
  <div className="flex items-center justify-center min-h-screen">
772
774
  <div className="text-center">
@@ -102,14 +102,6 @@ const mockIsSuperAdmin = vi.fn().mockResolvedValue(false);
102
102
 
103
103
  vi.mock('../../../rbac/api', () => ({
104
104
  isPermitted: vi.fn().mockImplementation((input) => {
105
- console.log('[PaceAppLayout] Page access attempt:', {
106
- pageName: input.pageId || 'unknown',
107
- operation: input.permission,
108
- userId: input.userId,
109
- allowed: true,
110
- strictMode: true,
111
- timestamp: new Date().toISOString()
112
- });
113
105
  return Promise.resolve(true);
114
106
  }),
115
107
  getPermissionMap: vi.fn().mockResolvedValue({}),
@@ -288,14 +280,6 @@ describe('PaceAppLayout Integration', () => {
288
280
 
289
281
  // Reset mockIsPermitted to default implementation
290
282
  mockIsPermitted.mockImplementation((input) => {
291
- console.log('[PaceAppLayout] Page access attempt:', {
292
- pageName: input.pageId || 'unknown',
293
- operation: input.permission,
294
- userId: input.userId,
295
- allowed: true,
296
- strictMode: true,
297
- timestamp: new Date().toISOString()
298
- });
299
283
  return Promise.resolve(true);
300
284
  });
301
285
 
@@ -216,6 +216,9 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
216
216
  );
217
217
 
218
218
  // Performance thresholds
219
+ // NOTE: These thresholds are used for smoke tests to detect significant regressions.
220
+ // They are intentionally generous to avoid flakiness in CI/coverage environments.
221
+ // For more reliable performance testing, prefer behavioral assertions (waitFor) over timing.
219
222
  const PERFORMANCE_THRESHOLDS = {
220
223
  RENDER_TIME: 200, // ms - Increased due to migration changes requiring more complex organization loading
221
224
  PERMISSION_CHECK_TIME: 110, // ms - Increased to account for timing variations
@@ -223,6 +226,9 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
223
226
  RE_RENDER_COUNT: 3
224
227
  };
225
228
 
229
+ // Skip performance timing tests in coverage mode (they're unreliable under instrumentation)
230
+ const shouldSkipTimingTests = process.env.COVERAGE === 'true' || process.env.VITEST_COVERAGE;
231
+
226
232
  const originalPerformanceMemory = (performance as any).memory;
227
233
 
228
234
  describe('PaceAppLayout Performance', () => {
@@ -336,7 +342,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
336
342
  });
337
343
 
338
344
  // Since we're only measuring after mount, the time should be very small
339
- expect(permissionCheckTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
345
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
346
+ if (!shouldSkipTimingTests) {
347
+ expect(permissionCheckTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
348
+ } else {
349
+ // In coverage mode, just verify the component rendered successfully
350
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
351
+ }
340
352
  }, { timeout: 6000 });
341
353
 
342
354
  it('handles multiple permission checks efficiently', async () => {
@@ -381,7 +393,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
381
393
  });
382
394
 
383
395
  // Since we're only measuring after mount, the time should be very small
384
- expect(permissionCheckTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
396
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
397
+ if (!shouldSkipTimingTests) {
398
+ expect(permissionCheckTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
399
+ } else {
400
+ // In coverage mode, just verify the component rendered successfully
401
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
402
+ }
385
403
  }, { timeout: 6000 });
386
404
 
387
405
  it('handles permission check errors efficiently', async () => {
@@ -427,7 +445,12 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
427
445
  const memoryIncrease = finalMemory - initialMemory;
428
446
 
429
447
  if (initialMemory > 0 && finalMemory > 0) {
430
- expect(memoryIncrease).toBeLessThan(PERFORMANCE_THRESHOLDS.MEMORY_USAGE_INCREASE);
448
+ // Skip memory assertions in coverage mode (unreliable under instrumentation)
449
+ if (!shouldSkipTimingTests) {
450
+ expect(memoryIncrease).toBeLessThan(PERFORMANCE_THRESHOLDS.MEMORY_USAGE_INCREASE);
451
+ }
452
+ // Always verify component still renders correctly (behavioral check)
453
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
431
454
  }
432
455
  });
433
456
 
@@ -450,7 +473,12 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
450
473
  const memoryIncrease = finalMemory - initialMemory;
451
474
 
452
475
  if (initialMemory > 0 && finalMemory > 0) {
453
- expect(memoryIncrease).toBeLessThan(PERFORMANCE_THRESHOLDS.MEMORY_USAGE_INCREASE);
476
+ // Skip memory assertions in coverage mode (unreliable under instrumentation)
477
+ if (!shouldSkipTimingTests) {
478
+ expect(memoryIncrease).toBeLessThan(PERFORMANCE_THRESHOLDS.MEMORY_USAGE_INCREASE);
479
+ }
480
+ // Always verify component still renders correctly (behavioral check)
481
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
454
482
  }
455
483
  });
456
484
  });
@@ -482,7 +510,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
482
510
  const totalTime = endTime - startTime;
483
511
  const averageTime = totalTime / PERFORMANCE_THRESHOLDS.RE_RENDER_COUNT;
484
512
 
485
- expect(averageTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME);
513
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
514
+ if (!shouldSkipTimingTests) {
515
+ expect(averageTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME);
516
+ } else {
517
+ // In coverage mode, verify component renders successfully (behavioral check)
518
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
519
+ }
486
520
  });
487
521
 
488
522
  it('handles permission enforcement toggles efficiently', async () => {
@@ -529,7 +563,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
529
563
  return tick;
530
564
  });
531
565
 
532
- expect(totalTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
566
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
567
+ if (!shouldSkipTimingTests) {
568
+ expect(totalTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
569
+ } else {
570
+ // In coverage mode, verify component rendered successfully (behavioral check)
571
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
572
+ }
533
573
  });
534
574
  });
535
575
 
@@ -554,7 +594,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
554
594
  const endTime = performance.now();
555
595
  const renderTime = endTime - startTime;
556
596
 
557
- expect(renderTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME);
597
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
598
+ if (!shouldSkipTimingTests) {
599
+ expect(renderTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME);
600
+ } else {
601
+ // In coverage mode, verify component renders successfully (behavioral check)
602
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
603
+ }
558
604
 
559
605
  // Rapidly click navigation buttons
560
606
  // If not, this test will fail.
@@ -642,7 +688,14 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
642
688
  return tick;
643
689
  });
644
690
 
645
- expect(authTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
691
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
692
+ if (!shouldSkipTimingTests) {
693
+ expect(authTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
694
+ } else {
695
+ // In coverage mode, verify actions completed successfully (behavioral check)
696
+ expect(mockSignOut).toHaveBeenCalled();
697
+ expect(mockUpdatePassword).toHaveBeenCalledWith('newpassword123');
698
+ }
646
699
  expect(mockSignOut).toHaveBeenCalled();
647
700
  expect(mockUpdatePassword).toHaveBeenCalledWith('newpassword123');
648
701
  });
@@ -692,7 +745,14 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
692
745
  return tick;
693
746
  });
694
747
 
695
- expect(authTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
748
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
749
+ if (!shouldSkipTimingTests) {
750
+ expect(authTime).toBeLessThan(PERFORMANCE_THRESHOLDS.PERMISSION_CHECK_TIME);
751
+ } else {
752
+ // In coverage mode, verify actions completed successfully (behavioral check)
753
+ expect(mockSignOut).toHaveBeenCalled();
754
+ expect(mockUpdatePassword).toHaveBeenCalledWith('newpassword123');
755
+ }
696
756
  });
697
757
  });
698
758
 
@@ -760,7 +820,13 @@ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
760
820
 
761
821
  // Performance threshold adjusted - render time includes async operations and filtering
762
822
  // Since enforcePermissions is false, permission checks are minimal, but navigation filtering may be async
763
- expect(renderTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME * 3); // Allow more time for complex config
823
+ // Skip timing assertion in coverage mode (unreliable under instrumentation)
824
+ if (!shouldSkipTimingTests) {
825
+ expect(renderTime).toBeLessThan(PERFORMANCE_THRESHOLDS.RENDER_TIME * 3); // Allow more time for complex config
826
+ } else {
827
+ // In coverage mode, verify component renders successfully (behavioral check)
828
+ expect(screen.getByTestId('mock-header')).toBeInTheDocument();
829
+ }
764
830
  }, { timeout: 3000 });
765
831
  });
766
832
  });
@@ -655,7 +655,6 @@ describe('PaceAppLayout Security', () => {
655
655
  // Simulate a component that might try to execute malicious code
656
656
  React.useEffect(() => {
657
657
  // This would be dangerous in a real scenario
658
- console.log('Component mounted');
659
658
  }, []);
660
659
 
661
660
  return <div data-testid="malicious-component">Malicious Component</div>;
@@ -99,14 +99,6 @@ vi.mock('../../../hooks/useEventTheme', () => ({
99
99
 
100
100
  // Mock the new RBAC system
101
101
  const mockIsPermitted = vi.fn().mockImplementation((input) => {
102
- console.log('[PaceAppLayout] Page access attempt:', {
103
- pageName: input.pageId || 'unknown',
104
- operation: input.permission,
105
- userId: input.userId,
106
- allowed: true,
107
- strictMode: true,
108
- timestamp: new Date().toISOString()
109
- });
110
102
  return Promise.resolve(true);
111
103
  });
112
104
 
@@ -902,7 +894,6 @@ describe('PaceAppLayout Component', () => {
902
894
  it('filters navigation when filterNavigationByPermissions is true', async () => {
903
895
  // Mock checkPermission to return false for some items
904
896
  mockIsPermitted.mockImplementation((input) => {
905
- console.log('[TEST] mockIsPermitted called with:', input);
906
897
  if (input.pageId === 'dashboard') return Promise.resolve(false);
907
898
  return Promise.resolve(true);
908
899
  });
@@ -9,6 +9,7 @@ import userEvent from '@testing-library/user-event';
9
9
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
10
10
  import { PaceLoginPage } from './PaceLoginPage';
11
11
  import { renderWithProviders } from '../../__tests__/helpers/test-utils';
12
+ import { Logger, LogLevel } from '../../utils/core/logger';
12
13
 
13
14
  // Mock React Router
14
15
  const mockNavigate = vi.fn();
@@ -83,9 +84,29 @@ import { isSuperAdmin } from '../../rbac/api';
83
84
  const originalConsoleError = console.error;
84
85
 
85
86
  describe('PaceLoginPage Component', () => {
86
- afterEach(() => {
87
+ let originalMode: string | undefined;
88
+
89
+ beforeEach(() => {
90
+ // Ensure logger is enabled by setting MODE to development
91
+ originalMode = import.meta.env.MODE;
92
+ (import.meta.env as any).MODE = 'development';
93
+
94
+ // Configure logger to ensure it logs in test environment
95
+ Logger.configure({
96
+ level: LogLevel.DEBUG,
97
+ includeTimestamp: false,
98
+ includeComponent: true,
99
+ });
100
+ });
101
+
102
+ afterEach(() => {
87
103
  // Restore console methods
88
104
  console.error = originalConsoleError;
105
+
106
+ // Restore original mode
107
+ if (originalMode !== undefined) {
108
+ (import.meta.env as any).MODE = originalMode;
109
+ }
89
110
  });
90
111
 
91
112
  // Basic rendering tests
@@ -330,7 +351,11 @@ describe('PaceLoginPage Component', () => {
330
351
  await user.click(submitButton);
331
352
 
332
353
  await waitFor(() => {
333
- expect(console.error).toHaveBeenCalledWith('Navigation error after sign-in:', expect.any(Error));
354
+ // Logger.error formats the message with component name and log level
355
+ expect(console.error).toHaveBeenCalledWith(
356
+ expect.stringContaining('[PaceLoginPage] Navigation error after sign-in:'),
357
+ expect.any(Error)
358
+ );
334
359
  });
335
360
  });
336
361
 
@@ -387,6 +412,9 @@ describe('PaceLoginPage Component', () => {
387
412
  const user = userEvent.setup();
388
413
  mockAuthContext.signIn.mockRejectedValue(new Error('Network error'));
389
414
 
415
+ // Mock console.error to catch the error
416
+ console.error = vi.fn();
417
+
390
418
  renderWithProviders(<PaceLoginPage appName="Test App" />);
391
419
 
392
420
  const emailInput = screen.getByLabelText('Email');
@@ -398,7 +426,11 @@ describe('PaceLoginPage Component', () => {
398
426
  await user.click(submitButton);
399
427
 
400
428
  await waitFor(() => {
401
- expect(console.error).toHaveBeenCalledWith('Login error:', expect.any(Error));
429
+ // Logger.error formats the message with component name and log level
430
+ expect(console.error).toHaveBeenCalledWith(
431
+ expect.stringContaining('[PaceLoginPage] Login error:'),
432
+ expect.any(Error)
433
+ );
402
434
  });
403
435
  });
404
436
  });
@@ -129,6 +129,7 @@ import { LoginForm } from '../LoginForm';
129
129
  import { Button, Input, Label } from '..';
130
130
  import { clearPalette } from '../../theming/runtime';
131
131
  import { EventServiceContext } from '../../providers/services/EventServiceProvider';
132
+ import { logger } from '../../utils/core/logger';
132
133
 
133
134
  export interface PaceLoginPageProps {
134
135
  /** The name of the application to be displayed on the login form. */
@@ -165,7 +166,7 @@ export interface PaceLoginPageProps {
165
166
  */
166
167
  export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
167
168
  appName = 'Pace',
168
- onSuccessRedirectPath = '/',
169
+ onSuccessRedirectPath = '/user-dashboard',
169
170
  requireAppAccess = false
170
171
  }) => {
171
172
  const { signIn, isAuthenticated, isLoading, authError, user, supabase } = useUnifiedAuth();
@@ -207,7 +208,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
207
208
  }
208
209
  } catch (error) {
209
210
  // Service may not be available yet or events not loaded - that's okay
210
- console.debug('[PaceLoginPage] Could not restore persisted event (service may not be ready):', error);
211
+ logger.debug('PaceLoginPage', 'Could not restore persisted event (service may not be ready):', error);
211
212
  }
212
213
  };
213
214
 
@@ -231,13 +232,13 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
231
232
 
232
233
  try {
233
234
  const userId = user.id;
234
- console.log('[PaceLoginPage] Checking app access using RBAC:', { appName, userId });
235
+ logger.debug('PaceLoginPage', 'Checking app access using RBAC:', { appName, userId });
235
236
 
236
237
  // Step 1: Check if user is super admin (they have unrestricted access)
237
238
  const superAdminCheck = await isSuperAdmin(userId);
238
239
 
239
240
  if (superAdminCheck) {
240
- console.log('[PaceLoginPage] User is super admin, granting access');
241
+ logger.debug('PaceLoginPage', 'User is super admin, granting access');
241
242
  setIsCheckingAccess(false);
242
243
  navigate(onSuccessRedirectPath, { replace: true });
243
244
  return;
@@ -252,7 +253,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
252
253
  .single();
253
254
 
254
255
  if (appError || !appData) {
255
- console.error('[PaceLoginPage] App not found:', appName, appError);
256
+ logger.error('PaceLoginPage', 'App not found:', { appName, error: appError });
256
257
  setAccessError(`Application "${appName}" is not configured. Please contact your administrator.`);
257
258
  setIsCheckingAccess(false);
258
259
  return;
@@ -265,7 +266,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
265
266
  .eq('app_id', appData.id);
266
267
 
267
268
  if (pagesError || !pagesData || pagesData.length === 0) {
268
- console.log('[PaceLoginPage] No pages configured for app:', appName);
269
+ logger.debug('PaceLoginPage', 'No pages configured for app:', appName);
269
270
  setAccessError(`You do not have permission to access ${appName}. This application is currently unavailable. Please contact your administrator if you believe you should have access.`);
270
271
  setIsCheckingAccess(false);
271
272
  return;
@@ -282,7 +283,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
282
283
  .single();
283
284
 
284
285
  if (!orgData) {
285
- console.log('[PaceLoginPage] User has no organisation access');
286
+ logger.debug('PaceLoginPage', 'User has no organisation access');
286
287
  setAccessError(`You do not have permission to access ${appName}. You are not assigned to any organisation. Please contact your administrator.`);
287
288
  setIsCheckingAccess(false);
288
289
  return;
@@ -302,7 +303,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
302
303
  p_page_id: page.page_name // Page name to resolve to UUID
303
304
  });
304
305
 
305
- console.log('[PaceLoginPage] Permission check for page:', page.page_name, { hasPermission, error: permError });
306
+ logger.debug('PaceLoginPage', 'Permission check for page:', { pageName: page.page_name, hasPermission, error: permError });
306
307
 
307
308
  if (!permError && hasPermission === true) {
308
309
  hasAnyAccess = true;
@@ -311,18 +312,18 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
311
312
  }
312
313
 
313
314
  if (hasAnyAccess) {
314
- console.log('[PaceLoginPage] User has access to app');
315
+ logger.debug('PaceLoginPage', 'User has access to app');
315
316
  setIsCheckingAccess(false);
316
317
  navigate(onSuccessRedirectPath, { replace: true });
317
318
  return;
318
319
  }
319
320
 
320
321
  // No access - deny
321
- console.log('[PaceLoginPage] Access denied - no permissions');
322
+ logger.debug('PaceLoginPage', 'Access denied - no permissions');
322
323
  setAccessError(`You do not have permission to access ${appName}. This application is restricted to authorized users only. Please contact your administrator if you believe you should have access.`);
323
324
  setIsCheckingAccess(false);
324
325
  } catch (error) {
325
- console.error('[PaceLoginPage] Error checking app access:', error);
326
+ logger.error('PaceLoginPage', 'Error checking app access:', error);
326
327
  setAccessError('An error occurred while checking your permissions. Please try again or contact support.');
327
328
  setIsCheckingAccess(false);
328
329
  }
@@ -349,7 +350,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
349
350
  try {
350
351
  navigate(onSuccessRedirectPath, { replace: true });
351
352
  } catch (navError) {
352
- console.error('Navigation error after sign-in:', navError);
353
+ logger.error('PaceLoginPage', 'Navigation error after sign-in:', navError);
353
354
  }
354
355
  }
355
356
  } finally {
@@ -371,7 +372,7 @@ export const PaceLoginPage: React.FC<PaceLoginPageProps> = ({
371
372
  isLoading={isSigningIn}
372
373
  onError={(error) => {
373
374
  // LoginForm will handle display of the error
374
- console.error('Login error:', error);
375
+ logger.error('PaceLoginPage', 'Login error:', error);
375
376
  }}
376
377
  />
377
378
  {(() => {
@@ -101,7 +101,7 @@ import React, { useState } from 'react';
101
101
  import { Button } from '../Button/Button';
102
102
  import { Input } from '../Input/Input';
103
103
  import { Label } from '../Label';
104
- import { cn } from '../../utils/cn';
104
+ import { cn } from '../../utils/core/cn';
105
105
 
106
106
  export interface PasswordChangeFormValues {
107
107
  newPassword: string;
@@ -1,4 +1,2 @@
1
- export { PasswordResetForm } from './PasswordResetForm';
2
- export type { PasswordResetFormProps } from './PasswordResetForm';
3
1
  export { PasswordChangeForm } from './PasswordChangeForm';
4
2
  export type { PasswordChangeFormProps, PasswordChangeFormValues } from './PasswordChangeForm';
@@ -62,7 +62,7 @@
62
62
 
63
63
  import * as React from 'react';
64
64
  import * as ProgressPrimitive from '@radix-ui/react-progress';
65
- import { cn } from '../../utils/cn';
65
+ import { cn } from '../../utils/core/cn';
66
66
 
67
67
  /**
68
68
  * Props for the Progress component