@jmruthers/pace-core 0.5.134 → 0.5.136

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 (522) hide show
  1. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  2. package/dist/{DataTable-A36PJG6N.js → DataTable-CYOHOX3O.js} +25 -13
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-801uofbR.d.ts} +51 -135
  4. package/dist/UnifiedAuthProvider-5E5TUNMS.js +17 -0
  5. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  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-CTJRBUX2.js → chunk-2TWNJ46Y.js} +2 -2
  9. package/dist/{chunk-UJI6WSMD.js → chunk-444EZN6N.js} +3 -3
  10. package/dist/chunk-444EZN6N.js.map +1 -0
  11. package/dist/{chunk-3CG5L6RN.js → chunk-4MT5BGGL.js} +90 -73
  12. package/dist/chunk-4MT5BGGL.js.map +1 -0
  13. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  14. package/dist/chunk-56XJ3TU6.js.map +1 -0
  15. package/dist/chunk-5DPZ5EAT.js +60 -0
  16. package/dist/chunk-5DPZ5EAT.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-APIBCTL2.js +670 -0
  20. package/dist/chunk-APIBCTL2.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-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  24. package/dist/chunk-BVYWGZVV.js.map +1 -0
  25. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  26. package/dist/chunk-ERISIBYU.js.map +1 -0
  27. package/dist/{chunk-CQZU6TFE.js → chunk-FHWWBIHA.js} +100 -62
  28. package/dist/chunk-FHWWBIHA.js.map +1 -0
  29. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  30. package/dist/chunk-FMUCXFII.js.map +1 -0
  31. package/dist/{chunk-GVDR7WNV.js → chunk-HJGGOMQ6.js} +194 -518
  32. package/dist/chunk-HJGGOMQ6.js.map +1 -0
  33. package/dist/{chunk-BDZUMRBD.js → chunk-K2WWTH7O.js} +13 -6
  34. package/dist/chunk-K2WWTH7O.js.map +1 -0
  35. package/dist/{chunk-BYXRHAIF.js → chunk-L6PGMCMD.js} +23 -14
  36. package/dist/chunk-L6PGMCMD.js.map +1 -0
  37. package/dist/chunk-LMC26NLJ.js +84 -0
  38. package/dist/chunk-LMC26NLJ.js.map +1 -0
  39. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  40. package/dist/chunk-LS353YLY.js.map +1 -0
  41. package/dist/{chunk-ZYZCRSBD.js → chunk-LTV3XIJJ.js} +16 -11
  42. package/dist/chunk-LTV3XIJJ.js.map +1 -0
  43. package/dist/{chunk-HMNOSGVA.js → chunk-NOHEVYVX.js} +377 -666
  44. package/dist/chunk-NOHEVYVX.js.map +1 -0
  45. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  46. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  47. package/dist/chunk-S5OFRT4M.js +94 -0
  48. package/dist/chunk-S5OFRT4M.js.map +1 -0
  49. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  50. package/dist/chunk-SBVILCCA.js.map +1 -0
  51. package/dist/{chunk-TGIY2AR2.js → chunk-SL2YQDR6.js} +4 -3
  52. package/dist/{chunk-TGIY2AR2.js.map → chunk-SL2YQDR6.js.map} +1 -1
  53. package/dist/{chunk-VZ5OR6HD.js → chunk-TVYPTYOY.js} +55 -179
  54. package/dist/chunk-TVYPTYOY.js.map +1 -0
  55. package/dist/{chunk-ZV77RZMU.js → chunk-XARJS7CD.js} +2 -2
  56. package/dist/chunk-XDNLUEXI.js +138 -0
  57. package/dist/chunk-XDNLUEXI.js.map +1 -0
  58. package/dist/{chunk-F64FFPOZ.js → chunk-YLKIDTUK.js} +26 -20
  59. package/dist/chunk-YLKIDTUK.js.map +1 -0
  60. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  61. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  62. package/dist/components.d.ts +7 -287
  63. package/dist/components.js +26 -157
  64. package/dist/components.js.map +1 -1
  65. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  66. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  67. package/dist/hooks.d.ts +3 -3
  68. package/dist/hooks.js +22 -16
  69. package/dist/hooks.js.map +1 -1
  70. package/dist/index.d.ts +219 -9
  71. package/dist/index.js +49 -31
  72. package/dist/index.js.map +1 -1
  73. package/dist/providers.d.ts +1 -1
  74. package/dist/providers.js +5 -4
  75. package/dist/rbac/index.js +13 -12
  76. package/dist/styles/index.js +2 -1
  77. package/dist/theming/runtime.d.ts +2 -19
  78. package/dist/theming/runtime.js +2 -1
  79. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  80. package/dist/types.d.ts +2 -2
  81. package/dist/types.js +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 +195 -232
  85. package/dist/utils.js +173 -331
  86. package/dist/utils.js.map +1 -1
  87. package/dist/{validation-DnhrNMju.d.ts → validation-8npbysjg.d.ts} +26 -8
  88. package/dist/validation.d.ts +261 -10
  89. package/dist/validation.js +82 -440
  90. package/dist/validation.js.map +1 -1
  91. package/docs/api/classes/ColumnFactory.md +1 -1
  92. package/docs/api/classes/ErrorBoundary.md +6 -6
  93. package/docs/api/classes/InvalidScopeError.md +1 -1
  94. package/docs/api/classes/MissingUserContextError.md +1 -1
  95. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  96. package/docs/api/classes/PermissionDeniedError.md +1 -1
  97. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  98. package/docs/api/classes/RBACAuditManager.md +6 -6
  99. package/docs/api/classes/RBACCache.md +1 -1
  100. package/docs/api/classes/RBACEngine.md +7 -7
  101. package/docs/api/classes/RBACError.md +1 -1
  102. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  103. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  104. package/docs/api/classes/StorageUtils.md +1 -1
  105. package/docs/api/enums/FileCategory.md +1 -1
  106. package/docs/api/interfaces/AggregateConfig.md +4 -4
  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 +3 -3
  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 +90 -0
  122. package/docs/api/interfaces/ExportOptions.md +126 -0
  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 +648 -212
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -2
  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/examples/README.md +30 -14
  205. package/examples/STRUCTURE.md +125 -0
  206. package/examples/components/DataTable/HierarchicalActionsExample.tsx +421 -0
  207. package/examples/components/DataTable/HierarchicalExample.tsx +475 -0
  208. package/examples/components/DataTable/InitialPageSizeExample.tsx +177 -0
  209. package/examples/components/DataTable/PerformanceExample.tsx +506 -0
  210. package/examples/components/DataTable/index.ts +13 -0
  211. package/examples/components/Dialog/BasicHtmlTest.tsx +55 -0
  212. package/examples/components/Dialog/DebugHtmlExample.tsx +68 -0
  213. package/examples/components/Dialog/HtmlDialogExample.tsx +202 -0
  214. package/examples/components/Dialog/ScrollableDialogExample.tsx +290 -0
  215. package/examples/components/Dialog/SimpleHtmlTest.tsx +61 -0
  216. package/examples/components/Dialog/SmartDialogExample.tsx +322 -0
  217. package/examples/components/Dialog/index.ts +15 -0
  218. package/examples/components/index.ts +11 -0
  219. package/examples/features/index.ts +12 -0
  220. package/examples/{public-pages → features/public-pages}/CorrectPublicPageImplementation.tsx +1 -1
  221. package/examples/{public-pages → features/public-pages}/PublicEventPage.tsx +1 -1
  222. package/examples/{public-pages → features/public-pages}/PublicPageApp.tsx +1 -1
  223. package/examples/{public-pages → features/public-pages}/PublicPageUsageExample.tsx +1 -1
  224. package/examples/index.ts +11 -3
  225. package/package.json +30 -10
  226. package/src/components/Alert/Alert.tsx +1 -1
  227. package/src/components/Avatar/Avatar.tsx +1 -1
  228. package/src/components/Button/Button.tsx +1 -1
  229. package/src/components/Card/Card.tsx +1 -1
  230. package/src/components/Checkbox/Checkbox.tsx +1 -1
  231. package/src/components/DataTable/DataTable.test.tsx +1 -1
  232. package/src/components/DataTable/DataTable.tsx +1 -30
  233. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  234. package/src/components/DataTable/__tests__/styles.test.ts +2 -2
  235. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  236. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  237. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  238. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  239. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  240. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  241. package/src/components/DataTable/components/PaginationControls.tsx +1 -1
  242. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  243. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  244. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  245. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  246. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  247. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  248. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  249. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  250. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  251. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  252. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  253. package/src/components/DataTable/index.ts +4 -0
  254. package/src/components/DataTable/styles.ts +1 -1
  255. package/src/components/DataTable/types.ts +13 -0
  256. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  257. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  258. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  259. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  260. package/src/components/DataTable/utils/index.ts +1 -0
  261. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  262. package/src/components/Dialog/Dialog.tsx +2 -2
  263. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  264. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  265. package/src/components/EventSelector/EventSelector.tsx +3 -2
  266. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  267. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  268. package/src/components/FileUpload/FileUpload.tsx +2 -2
  269. package/src/components/Footer/Footer.tsx +1 -1
  270. package/src/components/Form/Form.test.tsx +4 -509
  271. package/src/components/Form/Form.tsx +1 -1
  272. package/src/components/Form/FormField.tsx +1 -1
  273. package/src/components/Form/index.ts +0 -12
  274. package/src/components/Header/Header.tsx +1 -1
  275. package/src/components/Input/Input.tsx +1 -1
  276. package/src/components/Label/Label.tsx +1 -1
  277. package/src/components/LoginForm/LoginForm.tsx +1 -1
  278. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  279. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  280. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  281. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  282. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  283. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  284. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  285. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  286. package/src/components/PaceLoginPage/PaceLoginPage.tsx +13 -12
  287. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  288. package/src/components/PasswordReset/index.ts +0 -2
  289. package/src/components/Progress/Progress.tsx +1 -1
  290. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  291. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  292. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  293. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  294. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  295. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  296. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  297. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  298. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  299. package/src/components/PublicLayout/index.ts +4 -2
  300. package/src/components/Select/Select.tsx +1 -1
  301. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  302. package/src/components/SessionRestorationLoader/index.ts +3 -0
  303. package/src/components/Switch/Switch.tsx +1 -1
  304. package/src/components/Table/Table.tsx +1 -1
  305. package/src/components/Toast/Toast.tsx +1 -1
  306. package/src/components/Tooltip/Tooltip.tsx +1 -1
  307. package/src/components/index.ts +4 -10
  308. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  309. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  310. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  311. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  312. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  313. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  314. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  315. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  316. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  317. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  318. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  319. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  320. package/src/hooks/public/usePublicEvent.ts +7 -6
  321. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  322. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  323. package/src/hooks/useComponentPerformance.ts +4 -1
  324. package/src/hooks/useDataTablePerformance.ts +4 -3
  325. package/src/hooks/useEventTheme.test.ts +18 -5
  326. package/src/hooks/useEventTheme.ts +4 -1
  327. package/src/hooks/useEvents.ts +2 -0
  328. package/src/hooks/useFileDisplay.ts +9 -8
  329. package/src/hooks/useFileReference.ts +4 -1
  330. package/src/hooks/useFileUrl.ts +4 -1
  331. package/src/hooks/useInactivityTracker.ts +5 -4
  332. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  333. package/src/hooks/useOrganisationSecurity.ts +8 -7
  334. package/src/hooks/usePerformanceMonitor.ts +6 -3
  335. package/src/hooks/usePermissionCache.ts +13 -6
  336. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  337. package/src/hooks/useSecureDataAccess.ts +9 -8
  338. package/src/hooks/useSessionRestoration.ts +4 -1
  339. package/src/hooks/useStorage.ts +4 -1
  340. package/src/index.ts +25 -8
  341. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  342. package/src/providers/services/EventServiceProvider.tsx +2 -1
  343. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  344. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  345. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  346. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  347. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  348. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  349. package/src/rbac/api.ts +5 -2
  350. package/src/rbac/audit-enhanced.ts +6 -6
  351. package/src/rbac/audit.test.ts +60 -38
  352. package/src/rbac/audit.ts +8 -8
  353. package/src/rbac/cache-invalidation.ts +7 -4
  354. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  355. package/src/rbac/components/NavigationGuard.tsx +7 -3
  356. package/src/rbac/components/NavigationProvider.tsx +6 -3
  357. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  358. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  359. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  360. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  361. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  362. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  363. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  364. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  365. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  366. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  367. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  368. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  369. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  370. package/src/rbac/engine.ts +15 -7
  371. package/src/rbac/hooks/usePermissions.ts +7 -3
  372. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  373. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  374. package/src/rbac/permissions.ts +5 -2
  375. package/src/rbac/security.test.ts +27 -16
  376. package/src/rbac/security.ts +5 -4
  377. package/src/services/AuthService.ts +22 -21
  378. package/src/services/EventService.ts +12 -12
  379. package/src/services/InactivityService.ts +5 -4
  380. package/src/services/OrganisationService.ts +26 -25
  381. package/src/services/__tests__/AuthService.test.ts +51 -19
  382. package/src/services/__tests__/EventService.test.ts +37 -5
  383. package/src/services/__tests__/InactivityService.test.ts +38 -4
  384. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  385. package/src/services/base/BaseService.ts +3 -1
  386. package/src/theming/__tests__/runtime.test.ts +21 -12
  387. package/src/theming/parseEventColours.ts +5 -19
  388. package/src/theming/runtime.ts +8 -4
  389. package/src/types/validation.ts +2 -29
  390. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  391. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  392. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  393. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  394. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  395. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  396. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  397. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  398. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  399. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  400. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  401. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  402. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  403. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  404. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  405. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  406. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  407. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  408. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  409. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  410. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  411. package/src/utils/__tests__/security.unit.test.ts +40 -18
  412. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  413. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  414. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  415. package/src/utils/{appIdResolver.test.ts → app/appIdResolver.test.ts} +28 -30
  416. package/src/utils/{appIdResolver.ts → app/appIdResolver.ts} +8 -5
  417. package/src/utils/{appNameResolver.test.ts → app/appNameResolver.test.ts} +1 -1
  418. package/src/utils/{appNameResolver.ts → app/appNameResolver.ts} +5 -1
  419. package/src/utils/{organisationContext.ts → context/organisationContext.ts} +6 -3
  420. package/src/utils/{sessionTracking.ts → context/sessionTracking.ts} +11 -12
  421. package/src/utils/{logger.ts → core/logger.ts} +4 -2
  422. package/src/utils/{deviceFingerprint.ts → device/deviceFingerprint.ts} +1 -1
  423. package/src/utils/{lazyLoad.tsx → dynamic/lazyLoad.tsx} +2 -2
  424. package/src/utils/{file-reference.test.ts → file-reference/__tests__/file-reference.test.ts} +5 -5
  425. package/src/utils/{file-reference.ts → file-reference/index.ts} +20 -38
  426. package/src/utils/index.ts +32 -54
  427. package/src/utils/{secureErrors.ts → security/secureErrors.ts} +6 -3
  428. package/src/utils/{security.ts → security/security.ts} +5 -2
  429. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  430. package/src/utils/storage/helpers.ts +15 -8
  431. package/src/{components/Dialog/utils/__tests__/safeHtml.unit.test.ts → utils/validation/__tests__/htmlSanitization.unit.test.ts} +9 -15
  432. package/src/{validation → utils/validation}/csrf.ts +1 -1
  433. package/src/{components/Dialog/utils/safeHtml.ts → utils/validation/htmlSanitization.ts} +9 -10
  434. package/src/utils/validation/index.ts +79 -0
  435. package/src/utils/{sanitization.ts → validation/sanitization.ts} +71 -2
  436. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  437. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  438. package/src/utils/{validationUtils.ts → validation/validationUtils.ts} +4 -1
  439. package/src/validation/index.ts +3 -34
  440. package/dist/UnifiedAuthProvider-CQDZRJIS.js +0 -16
  441. package/dist/chunk-24MKLB7U.js +0 -81
  442. package/dist/chunk-24MKLB7U.js.map +0 -1
  443. package/dist/chunk-3CG5L6RN.js.map +0 -1
  444. package/dist/chunk-3DBFLLLU.js.map +0 -1
  445. package/dist/chunk-5F3NDPJV.js.map +0 -1
  446. package/dist/chunk-66C4BSAY.js.map +0 -1
  447. package/dist/chunk-BDZUMRBD.js.map +0 -1
  448. package/dist/chunk-BYXRHAIF.js.map +0 -1
  449. package/dist/chunk-CDQ3PX7L.js +0 -18
  450. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  451. package/dist/chunk-CQZU6TFE.js.map +0 -1
  452. package/dist/chunk-F64FFPOZ.js.map +0 -1
  453. package/dist/chunk-GEVIB2UB.js.map +0 -1
  454. package/dist/chunk-GKHF54DI.js.map +0 -1
  455. package/dist/chunk-GVDR7WNV.js.map +0 -1
  456. package/dist/chunk-HMNOSGVA.js.map +0 -1
  457. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  458. package/dist/chunk-M6DDYFUD.js.map +0 -1
  459. package/dist/chunk-O3NWNXDY.js.map +0 -1
  460. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  461. package/dist/chunk-UJI6WSMD.js.map +0 -1
  462. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  463. package/dist/chunk-WP5I5GLN.js.map +0 -1
  464. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  465. package/src/components/Dialog/README.md +0 -804
  466. package/src/components/Form/FormErrorSummary.tsx +0 -113
  467. package/src/components/Form/FormFieldset.tsx +0 -127
  468. package/src/components/Form/FormLiveRegion.tsx +0 -198
  469. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  470. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  471. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  472. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  473. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  474. package/src/examples/CorrectPublicPageImplementation.tsx +0 -304
  475. package/src/examples/PublicEventPage.tsx +0 -287
  476. package/src/examples/PublicPageApp.tsx +0 -321
  477. package/src/examples/PublicPageUsageExample.tsx +0 -218
  478. package/src/utils/schemaUtils.ts +0 -37
  479. package/src/validation/__tests__/common.unit.test.ts +0 -101
  480. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  481. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  482. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  483. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  484. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  485. package/src/validation/__tests__/user.unit.test.ts +0 -440
  486. package/src/validation/sanitization.ts +0 -96
  487. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-CYOHOX3O.js.map} +0 -0
  488. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-5E5TUNMS.js.map} +0 -0
  489. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  490. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  491. /package/dist/{chunk-CTJRBUX2.js.map → chunk-2TWNJ46Y.js.map} +0 -0
  492. /package/dist/{chunk-ZV77RZMU.js.map → chunk-XARJS7CD.js.map} +0 -0
  493. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  494. /package/examples/{public-pages → features/public-pages}/index.ts +0 -0
  495. /package/examples/{RBAC → features/rbac}/CompleteRBACExample.tsx +0 -0
  496. /package/examples/{RBAC → features/rbac}/EventBasedApp.tsx +0 -0
  497. /package/examples/{RBAC → features/rbac}/PermissionExample.tsx +0 -0
  498. /package/examples/{RBAC → features/rbac}/index.ts +0 -0
  499. /package/src/utils/{appConfig.ts → app/appConfig.ts} +0 -0
  500. /package/src/utils/{appNameResolver.simple.test.ts → app/appNameResolver.simple.test.ts} +0 -0
  501. /package/src/utils/{audit.ts → audit/audit.ts} +0 -0
  502. /package/src/utils/{organisationContext.test.ts → context/organisationContext.test.ts} +0 -0
  503. /package/src/utils/{cn.ts → core/cn.ts} +0 -0
  504. /package/src/utils/{debugLogger.ts → core/debugLogger.ts} +0 -0
  505. /package/src/utils/{dynamicUtils.ts → dynamic/dynamicUtils.ts} +0 -0
  506. /package/src/utils/{formatDate.test.ts → formatting/formatDate.test.ts} +0 -0
  507. /package/src/utils/{formatting.ts → formatting/formatting.ts} +0 -0
  508. /package/src/utils/{bundleAnalysis.ts → performance/bundleAnalysis.ts} +0 -0
  509. /package/src/utils/{performanceBenchmark.ts → performance/performanceBenchmark.ts} +0 -0
  510. /package/src/utils/{performanceBudgets.ts → performance/performanceBudgets.ts} +0 -0
  511. /package/src/utils/{permissionTypes.ts → permissions/permissionTypes.ts} +0 -0
  512. /package/src/utils/{permissionUtils.test.ts → permissions/permissionUtils.test.ts} +0 -0
  513. /package/src/utils/{permissionUtils.ts → permissions/permissionUtils.ts} +0 -0
  514. /package/src/utils/{auth-utils.ts → security/auth-utils.ts} +0 -0
  515. /package/src/utils/{secureDataAccess.test.ts → security/secureDataAccess.test.ts} +0 -0
  516. /package/src/utils/{secureDataAccess.ts → security/secureDataAccess.ts} +0 -0
  517. /package/src/utils/{secureStorage.ts → security/secureStorage.ts} +0 -0
  518. /package/src/utils/{securityMonitor.ts → security/securityMonitor.ts} +0 -0
  519. /package/src/{validation → utils/validation}/common.ts +0 -0
  520. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  521. /package/src/{validation → utils/validation}/user.ts +0 -0
  522. /package/src/utils/{validation.ts → validation/validation.ts} +0 -0
@@ -68,6 +68,7 @@ import { useLocation, useNavigate, Outlet } from 'react-router-dom';
68
68
  import { useCan } from '../hooks';
69
69
  import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
70
70
  import { UUID, Permission, Scope, AccessLevel } from '../types';
71
+ import { getRBACLogger } from '../config';
71
72
 
72
73
  export interface RouteConfig {
73
74
  /** Route path */
@@ -307,7 +308,8 @@ export function RoleBasedRouter({
307
308
  if (!currentRouteConfig) {
308
309
  // Route not found in configuration
309
310
  if (strictMode) {
310
- console.error(`[RoleBasedRouter] STRICT MODE VIOLATION: Route not found in configuration`, {
311
+ const logger = getRBACLogger();
312
+ logger.error(`STRICT MODE VIOLATION: Route not found in configuration`, {
311
313
  route: currentPath,
312
314
  userId: user?.id,
313
315
  timestamp: new Date().toISOString()
@@ -60,6 +60,7 @@ import React, { createContext, useContext, useState, useCallback, useMemo, useEf
60
60
  import { useUnifiedAuth } from '../../providers/UnifiedAuthProvider';
61
61
  import { useSecureDataAccess } from '../../hooks/useSecureDataAccess';
62
62
  import { UUID, Scope, Permission } from '../types';
63
+ import { getRBACLogger } from '../config';
63
64
 
64
65
  export interface DataAccessRecord {
65
66
  table: string;
@@ -215,7 +216,8 @@ export function SecureDataProvider({
215
216
  try {
216
217
  validateContext();
217
218
  } catch (error) {
218
- console.error(`[SecureDataProvider] Organisation context validation failed:`, error);
219
+ const logger = getRBACLogger();
220
+ logger.error('Organisation context validation failed:', error);
219
221
  return false;
220
222
  }
221
223
 
@@ -282,14 +284,16 @@ export function SecureDataProvider({
282
284
  // Log strict mode violations
283
285
  useEffect(() => {
284
286
  if (strictMode && auditLog) {
285
- console.log(`[SecureDataProvider] Strict mode enabled - all data access attempts will be logged and enforced`);
287
+ const logger = getRBACLogger();
288
+ logger.debug('Strict mode enabled - all data access attempts will be logged and enforced');
286
289
  }
287
290
  }, [strictMode, auditLog]);
288
291
 
289
292
  // Log RLS enforcement
290
293
  useEffect(() => {
291
294
  if (enforceRLS && auditLog) {
292
- console.log(`[SecureDataProvider] RLS enforcement enabled - all queries will include organisation context`);
295
+ const logger = getRBACLogger();
296
+ logger.debug('RLS enforcement enabled - all queries will include organisation context');
293
297
  }
294
298
  }, [enforceRLS, auditLog]);
295
299
 
@@ -16,8 +16,31 @@ import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
16
16
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
17
17
  import { MemoryRouter } from 'react-router-dom';
18
18
 
19
+ // Mock the RBAC logger - define outside but reference in factory
20
+ const mockLogger = {
21
+ debug: vi.fn(),
22
+ error: vi.fn(),
23
+ warn: vi.fn(),
24
+ info: vi.fn(),
25
+ };
26
+
27
+ vi.mock('../../config', () => ({
28
+ getRBACLogger: vi.fn(() => mockLogger),
29
+ getRBACConfig: vi.fn(() => ({
30
+ debug: true,
31
+ logLevel: 'debug',
32
+ developmentMode: true,
33
+ audit: {
34
+ enabled: true,
35
+ logLevel: 'debug'
36
+ }
37
+ })),
38
+ isDebugMode: vi.fn(() => true),
39
+ isDevelopmentMode: vi.fn(() => true),
40
+ }));
41
+
19
42
  import { EnhancedNavigationMenu, EnhancedNavigationMenuProps } from '../EnhancedNavigationMenu';
20
- import { NavigationProvider, NavigationItem } from '../NavigationProvider';
43
+ import { NavigationProvider, NavigationItem, useNavigationPermissions } from '../NavigationProvider';
21
44
  import { useUnifiedAuth } from '../../../providers/UnifiedAuthProvider';
22
45
 
23
46
  // Mock the UnifiedAuthProvider
@@ -25,23 +48,26 @@ vi.mock('../../../providers/UnifiedAuthProvider', () => ({
25
48
  useUnifiedAuth: vi.fn()
26
49
  }));
27
50
 
28
- // Mock the NavigationProvider
29
- vi.mock('../NavigationProvider', () => ({
30
- NavigationProvider: ({ children }: { children: React.ReactNode }) => <div data-testid="navigation-provider">{children}</div>,
31
- useNavigationPermissions: vi.fn(() => ({
32
- hasNavigationPermission: vi.fn(() => true),
33
- getFilteredNavigationItems: vi.fn((items) => items),
34
- isEnabled: true,
35
- isStrictMode: true,
36
- isAuditLogEnabled: true,
37
- permissions: {},
38
- navigationAccessHistory: [],
39
- clearNavigationAccessHistory: vi.fn(),
40
- onNavigationAccess: vi.fn(),
41
- onStrictModeViolation: vi.fn()
42
- })),
43
- NavigationItem: {} // Add this to avoid import issues
44
- }));
51
+ // Mock only the useNavigationPermissions hook, not the provider itself
52
+ // This allows the real NavigationProvider to render and call logger in useEffect
53
+ vi.mock('../NavigationProvider', async () => {
54
+ const actual = await vi.importActual('../NavigationProvider');
55
+ return {
56
+ ...actual,
57
+ useNavigationPermissions: vi.fn(() => ({
58
+ hasNavigationPermission: vi.fn(() => true),
59
+ getFilteredNavigationItems: vi.fn((items) => items),
60
+ isEnabled: true,
61
+ isStrictMode: true,
62
+ isAuditLogEnabled: true,
63
+ permissions: {},
64
+ navigationAccessHistory: [],
65
+ clearNavigationAccessHistory: vi.fn(),
66
+ onNavigationAccess: vi.fn(),
67
+ onStrictModeViolation: vi.fn()
68
+ }))
69
+ };
70
+ });
45
71
 
46
72
  // Mock the NavigationGuard component
47
73
  vi.mock('../NavigationGuard', () => ({
@@ -52,7 +78,7 @@ vi.mock('../NavigationGuard', () => ({
52
78
  }));
53
79
 
54
80
  const mockUseUnifiedAuth = useUnifiedAuth as any;
55
- const mockUseNavigationPermissions = vi.fn();
81
+ const mockUseNavigationPermissions = useNavigationPermissions as any;
56
82
 
57
83
  // Test data
58
84
  const mockNavigationItems: NavigationItem[] = [
@@ -118,24 +144,19 @@ const TestWrapper: React.FC<{ children: React.ReactNode; navigationProps?: any }
118
144
  };
119
145
 
120
146
  describe('EnhancedNavigationMenu', () => {
121
- let consoleSpy: any;
122
-
123
147
  beforeEach(() => {
124
- consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
125
- vi.spyOn(console, 'error').mockImplementation(() => {});
148
+ vi.clearAllMocks();
126
149
 
127
150
  mockUseUnifiedAuth.mockReturnValue(mockUser);
128
151
  mockUseNavigationPermissions.mockReturnValue(defaultNavigationPermissions);
129
152
 
130
153
  // Reset mocks
131
154
  defaultNavigationPermissions.hasNavigationPermission.mockReturnValue(true);
132
- defaultNavigationPermissions.getFilteredNavigationItems.mockReturnValue(mockNavigationItems);
155
+ defaultNavigationPermissions.getFilteredNavigationItems.mockImplementation((items) => items || []);
133
156
  });
134
157
 
135
158
  afterEach(() => {
136
- consoleSpy.mockRestore();
137
- // Don't clear mocks to preserve the mock setup
138
- // vi.clearAllMocks();
159
+ vi.clearAllMocks();
139
160
  });
140
161
 
141
162
  describe('Basic Rendering', () => {
@@ -198,11 +219,10 @@ describe('EnhancedNavigationMenu', () => {
198
219
  </TestWrapper>
199
220
  );
200
221
 
201
- // The component renders all items due to mock behavior
202
- // This test verifies the component renders without crashing
222
+ // Only Dashboard should be visible after filtering
203
223
  expect(screen.getByText('Dashboard')).toBeInTheDocument();
204
- expect(screen.getByText('Events')).toBeInTheDocument();
205
- expect(screen.getByText('Users')).toBeInTheDocument();
224
+ expect(screen.queryByText('Events')).not.toBeInTheDocument();
225
+ expect(screen.queryByText('Users')).not.toBeInTheDocument();
206
226
  });
207
227
 
208
228
  it('should show all items when navigation permissions are disabled', () => {
@@ -389,14 +409,16 @@ describe('EnhancedNavigationMenu', () => {
389
409
  const dashboardButton = screen.getByRole('button', { name: /dashboard/i });
390
410
  await user.click(dashboardButton);
391
411
 
392
- expect(consoleSpy).toHaveBeenCalledWith(
393
- expect.stringContaining('[EnhancedNavigationMenu] Navigation item clicked:'),
394
- expect.objectContaining({
395
- item: 'dashboard',
396
- path: '/dashboard',
397
- permissions: ['read:dashboard']
398
- })
399
- );
412
+ await waitFor(() => {
413
+ expect(mockLogger.debug).toHaveBeenCalledWith(
414
+ 'Navigation item clicked:',
415
+ expect.objectContaining({
416
+ item: 'dashboard',
417
+ path: '/dashboard',
418
+ permissions: ['read:dashboard']
419
+ })
420
+ );
421
+ });
400
422
  });
401
423
 
402
424
  it('should not log when audit logging is disabled', async () => {
@@ -414,8 +436,9 @@ describe('EnhancedNavigationMenu', () => {
414
436
  const dashboardButton = screen.getByRole('button', { name: /dashboard/i });
415
437
  await user.click(dashboardButton);
416
438
 
417
- expect(consoleSpy).not.toHaveBeenCalledWith(
418
- expect.stringContaining('[EnhancedNavigationMenu] Navigation item clicked:')
439
+ expect(mockLogger.debug).not.toHaveBeenCalledWith(
440
+ 'Navigation item clicked:',
441
+ expect.any(Object)
419
442
  );
420
443
  });
421
444
 
@@ -466,7 +489,6 @@ describe('EnhancedNavigationMenu', () => {
466
489
 
467
490
  describe('Strict Mode', () => {
468
491
  it('should log strict mode violations when enabled', () => {
469
- const consoleErrorSpy = vi.spyOn(console, 'error');
470
492
  defaultNavigationPermissions.hasNavigationPermission.mockReturnValue(false);
471
493
  // Ensure the mock is applied
472
494
  mockUseNavigationPermissions.mockReturnValue(defaultNavigationPermissions);
@@ -485,7 +507,6 @@ describe('EnhancedNavigationMenu', () => {
485
507
  });
486
508
 
487
509
  it('should not log strict mode violations when disabled', () => {
488
- const consoleErrorSpy = vi.spyOn(console, 'error');
489
510
  defaultNavigationPermissions.hasNavigationPermission.mockReturnValue(false);
490
511
 
491
512
  render(
@@ -497,14 +518,15 @@ describe('EnhancedNavigationMenu', () => {
497
518
  </TestWrapper>
498
519
  );
499
520
 
500
- expect(consoleErrorSpy).not.toHaveBeenCalledWith(
501
- expect.stringContaining('[EnhancedNavigationMenu] STRICT MODE VIOLATION:')
521
+ expect(mockLogger.error).not.toHaveBeenCalledWith(
522
+ expect.stringContaining('STRICT MODE VIOLATION:'),
523
+ expect.any(Object)
502
524
  );
503
525
  });
504
526
  });
505
527
 
506
528
  describe('Initialization Logging', () => {
507
- it('should log initialization when audit logging is enabled', () => {
529
+ it('should log initialization when audit logging is enabled', async () => {
508
530
  render(
509
531
  <TestWrapper>
510
532
  <EnhancedNavigationMenu
@@ -514,17 +536,19 @@ describe('EnhancedNavigationMenu', () => {
514
536
  </TestWrapper>
515
537
  );
516
538
 
517
- expect(consoleSpy).toHaveBeenCalledWith(
518
- expect.stringContaining('[EnhancedNavigationMenu] Navigation menu initialized:'),
519
- expect.objectContaining({
520
- totalItems: 3,
521
- filteredItems: 3,
522
- strictMode: true
523
- })
524
- );
539
+ await waitFor(() => {
540
+ expect(mockLogger.debug).toHaveBeenCalledWith(
541
+ 'Navigation menu initialized:',
542
+ expect.objectContaining({
543
+ totalItems: 3,
544
+ filteredItems: 3,
545
+ strictMode: true
546
+ })
547
+ );
548
+ });
525
549
  });
526
550
 
527
- it('should log strict mode status on mount', () => {
551
+ it('should log strict mode status on mount', async () => {
528
552
  render(
529
553
  <TestWrapper>
530
554
  <EnhancedNavigationMenu
@@ -535,9 +559,11 @@ describe('EnhancedNavigationMenu', () => {
535
559
  </TestWrapper>
536
560
  );
537
561
 
538
- expect(consoleSpy).toHaveBeenCalledWith(
539
- expect.stringContaining('[EnhancedNavigationMenu] Strict mode enabled - all navigation access attempts will be logged and enforced')
540
- );
562
+ await waitFor(() => {
563
+ expect(mockLogger.debug).toHaveBeenCalledWith(
564
+ 'Strict mode enabled - all navigation access attempts will be logged and enforced'
565
+ );
566
+ });
541
567
  });
542
568
  });
543
569
 
@@ -545,8 +571,8 @@ describe('EnhancedNavigationMenu', () => {
545
571
  it('should handle missing navigation permissions gracefully', () => {
546
572
  mockUseNavigationPermissions.mockReturnValue({
547
573
  ...defaultNavigationPermissions,
548
- hasNavigationPermission: undefined,
549
- getFilteredNavigationItems: undefined
574
+ hasNavigationPermission: vi.fn(() => true),
575
+ getFilteredNavigationItems: vi.fn((items) => items)
550
576
  });
551
577
 
552
578
  expect(() => {
@@ -566,7 +592,7 @@ describe('EnhancedNavigationMenu', () => {
566
592
  );
567
593
 
568
594
  expect(screen.getByRole('navigation')).toBeInTheDocument();
569
- expect(screen.queryByRole('button')).not.toBeInTheDocument();
595
+ expect(screen.queryAllByRole('button')).toHaveLength(0);
570
596
  });
571
597
  });
572
598
 
@@ -13,6 +13,30 @@ import { ReactNode } from 'react';
13
13
  import { NavigationGuard } from '../NavigationGuard';
14
14
  import { useMultiplePermissions } from '../../hooks/usePermissions';
15
15
  import { useUnifiedAuth } from '../../../providers/UnifiedAuthProvider';
16
+ import { getRBACLogger } from '../../config';
17
+
18
+ // Mock the RBAC logger - create shared mock
19
+ const mockLogger = {
20
+ debug: vi.fn(),
21
+ error: vi.fn(),
22
+ warn: vi.fn(),
23
+ info: vi.fn(),
24
+ };
25
+
26
+ vi.mock('../../config', () => ({
27
+ getRBACLogger: vi.fn(() => mockLogger),
28
+ getRBACConfig: vi.fn(() => ({
29
+ debug: true,
30
+ logLevel: 'debug',
31
+ developmentMode: true,
32
+ audit: {
33
+ enabled: true,
34
+ logLevel: 'debug'
35
+ }
36
+ })),
37
+ isDebugMode: vi.fn(() => true),
38
+ isDevelopmentMode: vi.fn(() => true),
39
+ }));
16
40
 
17
41
  // Mock the RBAC hooks
18
42
  vi.mock('../../hooks/usePermissions', () => ({
@@ -499,8 +523,21 @@ describe('NavigationGuard Component', () => {
499
523
  });
500
524
 
501
525
  describe('Security Features', () => {
526
+
502
527
  it('prevents bypassing in strict mode', async () => {
503
- const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
528
+ vi.clearAllMocks();
529
+
530
+ // Create a local mock logger to ensure we can track calls
531
+ const localMockLogger = {
532
+ debug: vi.fn(),
533
+ error: vi.fn(),
534
+ warn: vi.fn(),
535
+ info: vi.fn(),
536
+ };
537
+
538
+ // Mock getRBACLogger to return our local mock
539
+ const mockGetRBACLogger = vi.mocked(getRBACLogger);
540
+ mockGetRBACLogger.mockReturnValue(localMockLogger);
504
541
 
505
542
  mockUseMultiplePermissions.mockReturnValue({
506
543
  results: { 'read:dashboard': false } as Record<string, boolean>,
@@ -513,6 +550,7 @@ describe('NavigationGuard Component', () => {
513
550
  <NavigationGuard
514
551
  navigationItem={mockNavigationItem}
515
552
  strictMode={true}
553
+ auditLog={true}
516
554
  fallback={<TestFallback />}
517
555
  >
518
556
  <TestComponent>Navigation Link</TestComponent>
@@ -523,20 +561,32 @@ describe('NavigationGuard Component', () => {
523
561
  expect(screen.getByTestId('test-fallback')).toBeInTheDocument();
524
562
  }, { interval: 10 });
525
563
 
526
- expect(consoleSpy).toHaveBeenCalledWith(
527
- expect.stringContaining('STRICT MODE VIOLATION'),
528
- expect.objectContaining({
529
- navigationItem: 'nav-dashboard',
530
- permissions: ['read:dashboard'],
531
- userId: 'user-123'
532
- })
533
- );
534
-
535
- consoleSpy.mockRestore();
564
+ await waitFor(() => {
565
+ expect(localMockLogger.error).toHaveBeenCalledWith(
566
+ expect.stringContaining('STRICT MODE VIOLATION'),
567
+ expect.objectContaining({
568
+ navigationItem: 'nav-dashboard',
569
+ permissions: ['read:dashboard'],
570
+ userId: 'user-123'
571
+ })
572
+ );
573
+ }, { timeout: 2000, interval: 100 });
536
574
  });
537
575
 
538
576
  it('logs navigation access attempts for audit', async () => {
539
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
577
+ vi.clearAllMocks();
578
+
579
+ // Create a local mock logger to ensure we can track calls
580
+ const localMockLogger = {
581
+ debug: vi.fn(),
582
+ error: vi.fn(),
583
+ warn: vi.fn(),
584
+ info: vi.fn(),
585
+ };
586
+
587
+ // Mock getRBACLogger to return our local mock
588
+ const mockGetRBACLogger = vi.mocked(getRBACLogger);
589
+ mockGetRBACLogger.mockReturnValue(localMockLogger);
540
590
 
541
591
  mockUseMultiplePermissions.mockReturnValue({
542
592
  results: { 'read:dashboard': false } as Record<string, boolean>,
@@ -559,17 +609,17 @@ describe('NavigationGuard Component', () => {
559
609
  expect(screen.getByTestId('test-fallback')).toBeInTheDocument();
560
610
  }, { interval: 10 });
561
611
 
562
- expect(consoleSpy).toHaveBeenCalledWith(
563
- expect.stringContaining('Navigation access attempt'),
564
- expect.objectContaining({
565
- navigationItem: 'nav-dashboard',
566
- permissions: ['read:dashboard'],
567
- userId: 'user-123',
568
- allowed: false
569
- })
570
- );
571
-
572
- consoleSpy.mockRestore();
612
+ await waitFor(() => {
613
+ expect(localMockLogger.debug).toHaveBeenCalledWith(
614
+ 'Navigation access attempt:',
615
+ expect.objectContaining({
616
+ navigationItem: 'nav-dashboard',
617
+ permissions: ['read:dashboard'],
618
+ userId: 'user-123',
619
+ allowed: false
620
+ })
621
+ );
622
+ }, { timeout: 2000, interval: 100 });
573
623
  });
574
624
 
575
625
  it('calls onDenied callback when access is denied', async () => {
@@ -628,7 +678,7 @@ describe('NavigationGuard Component', () => {
628
678
 
629
679
  describe('Configuration Options', () => {
630
680
  it('respects strictMode setting', async () => {
631
- const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
681
+ vi.clearAllMocks();
632
682
 
633
683
  mockUseMultiplePermissions.mockReturnValue({
634
684
  results: { 'read:dashboard': false } as Record<string, boolean>,
@@ -651,15 +701,15 @@ describe('NavigationGuard Component', () => {
651
701
  expect(screen.getByTestId('test-fallback')).toBeInTheDocument();
652
702
  }, { interval: 10 });
653
703
 
654
- expect(consoleSpy).not.toHaveBeenCalledWith(
655
- expect.stringContaining('STRICT MODE VIOLATION')
704
+ // Strict mode is disabled, so error should not be called
705
+ expect(mockLogger.error).not.toHaveBeenCalledWith(
706
+ expect.stringContaining('STRICT MODE VIOLATION'),
707
+ expect.anything()
656
708
  );
657
-
658
- consoleSpy.mockRestore();
659
709
  });
660
710
 
661
711
  it('respects auditLog setting', async () => {
662
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
712
+ vi.clearAllMocks();
663
713
 
664
714
  mockUseMultiplePermissions.mockReturnValue({
665
715
  results: { 'read:dashboard': false } as Record<string, boolean>,
@@ -682,11 +732,11 @@ describe('NavigationGuard Component', () => {
682
732
  expect(screen.getByTestId('test-fallback')).toBeInTheDocument();
683
733
  }, { interval: 10 });
684
734
 
685
- expect(consoleSpy).not.toHaveBeenCalledWith(
686
- expect.stringContaining('Navigation access attempt')
735
+ // Audit log is disabled, so debug should not be called
736
+ expect(mockLogger.debug).not.toHaveBeenCalledWith(
737
+ 'Navigation access attempt:',
738
+ expect.anything()
687
739
  );
688
-
689
- consoleSpy.mockRestore();
690
740
  });
691
741
 
692
742
  it('respects requireAll setting', async () => {
@@ -15,6 +15,29 @@ import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
15
15
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
16
16
  import { renderWithProviders } from '../../../__tests__/helpers';
17
17
 
18
+ // Mock the RBAC logger - define inside factory to avoid hoisting issues
19
+ const mockLogger = {
20
+ debug: vi.fn(),
21
+ error: vi.fn(),
22
+ warn: vi.fn(),
23
+ info: vi.fn(),
24
+ };
25
+
26
+ vi.mock('../../config', () => ({
27
+ getRBACLogger: vi.fn(() => mockLogger),
28
+ getRBACConfig: vi.fn(() => ({
29
+ debug: true,
30
+ logLevel: 'debug',
31
+ developmentMode: true,
32
+ audit: {
33
+ enabled: true,
34
+ logLevel: 'debug'
35
+ }
36
+ })),
37
+ isDebugMode: vi.fn(() => true),
38
+ isDevelopmentMode: vi.fn(() => true),
39
+ }));
40
+
18
41
  import {
19
42
  NavigationProvider,
20
43
  NavigationProviderProps,
@@ -117,11 +140,8 @@ const TestWrapper: React.FC<{
117
140
  };
118
141
 
119
142
  describe('NavigationProvider', () => {
120
- let consoleSpy: any;
121
-
122
143
  beforeEach(() => {
123
- consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
124
- vi.spyOn(console, 'error').mockImplementation(() => {});
144
+ vi.clearAllMocks();
125
145
 
126
146
  // Set up default mock with organisation context
127
147
  mockUseUnifiedAuth.mockReturnValue({
@@ -132,7 +152,6 @@ describe('NavigationProvider', () => {
132
152
  });
133
153
 
134
154
  afterEach(() => {
135
- consoleSpy.mockRestore();
136
155
  vi.clearAllMocks();
137
156
  });
138
157
 
@@ -358,28 +377,32 @@ describe('NavigationProvider', () => {
358
377
  });
359
378
 
360
379
  describe('Audit Logging', () => {
361
- it('should log strict mode status when enabled', () => {
380
+ it('should log strict mode status when enabled', async () => {
362
381
  renderWithProviders(
363
382
  <TestWrapper providerProps={{ strictMode: true, auditLog: true }}>
364
383
  <TestComponent />
365
384
  </TestWrapper>
366
385
  );
367
386
 
368
- expect(consoleSpy).toHaveBeenCalledWith(
369
- expect.stringContaining('[NavigationProvider] Strict mode enabled - all navigation access attempts will be logged and enforced')
370
- );
387
+ await waitFor(() => {
388
+ expect(mockLogger.debug).toHaveBeenCalledWith(
389
+ 'Strict mode enabled - all navigation access attempts will be logged and enforced'
390
+ );
391
+ });
371
392
  });
372
393
 
373
- it('should not log when audit logging is disabled', () => {
394
+ it('should not log when audit logging is disabled', async () => {
374
395
  renderWithProviders(
375
396
  <TestWrapper providerProps={{ auditLog: false }}>
376
397
  <TestComponent />
377
398
  </TestWrapper>
378
399
  );
379
400
 
380
- expect(consoleSpy).not.toHaveBeenCalledWith(
381
- expect.stringContaining('[NavigationProvider] Strict mode enabled')
382
- );
401
+ await waitFor(() => {
402
+ expect(mockLogger.debug).not.toHaveBeenCalledWith(
403
+ 'Strict mode enabled - all navigation access attempts will be logged and enforced'
404
+ );
405
+ });
383
406
  });
384
407
  });
385
408
 
@@ -30,12 +30,12 @@ vi.mock('../../utils/eventContext', () => ({
30
30
  }));
31
31
 
32
32
  // Mock the app name resolver
33
- vi.mock('../../../utils/appNameResolver', () => ({
33
+ vi.mock('../../../utils/app/appNameResolver', () => ({
34
34
  getCurrentAppName: vi.fn()
35
35
  }));
36
36
 
37
37
  import { createScopeFromEvent } from '../../utils/eventContext';
38
- import { getCurrentAppName } from '../../../utils/appNameResolver';
38
+ import { getCurrentAppName } from '../../../utils/app/appNameResolver';
39
39
 
40
40
  // Mock data
41
41
  const mockUser = {
@@ -23,6 +23,22 @@ import {
23
23
  } from '../PagePermissionProvider';
24
24
  import { useUnifiedAuth } from '../../../providers/UnifiedAuthProvider';
25
25
 
26
+ // Mock the Logger module
27
+ vi.mock('../../../utils/core/logger', () => {
28
+ const mockLoggerInstance = {
29
+ debug: vi.fn(),
30
+ warn: vi.fn(),
31
+ error: vi.fn(),
32
+ };
33
+ return {
34
+ createLogger: vi.fn(() => mockLoggerInstance),
35
+ };
36
+ });
37
+
38
+ // Get the mock instance after mock is set up
39
+ import { createLogger } from '../../../utils/core/logger';
40
+ const getMockLogger = () => createLogger('test');
41
+
26
42
  // Mock the UnifiedAuthProvider
27
43
  vi.mock('../../../providers/UnifiedAuthProvider', () => ({
28
44
  useUnifiedAuth: vi.fn(),
@@ -89,10 +105,7 @@ const TestWrapper: React.FC<{
89
105
  };
90
106
 
91
107
  describe('PagePermissionProvider', () => {
92
- let consoleSpy: any;
93
-
94
108
  beforeEach(() => {
95
- consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
96
109
  vi.spyOn(console, 'error').mockImplementation(() => {});
97
110
 
98
111
  // Set up default mock with organisation context
@@ -104,7 +117,6 @@ describe('PagePermissionProvider', () => {
104
117
  });
105
118
 
106
119
  afterEach(() => {
107
- consoleSpy.mockRestore();
108
120
  // Don't clear mocks to preserve the mock setup
109
121
  // vi.clearAllMocks();
110
122
  });
@@ -338,8 +350,9 @@ describe('PagePermissionProvider', () => {
338
350
  </TestWrapper>
339
351
  );
340
352
 
341
- expect(consoleSpy).toHaveBeenCalledWith(
342
- expect.stringContaining('[PagePermissionProvider] Strict mode enabled - all page access attempts will be logged and enforced')
353
+ const logger = getMockLogger();
354
+ expect(vi.mocked(logger.debug)).toHaveBeenCalledWith(
355
+ 'Strict mode enabled - all page access attempts will be logged and enforced'
343
356
  );
344
357
  });
345
358
 
@@ -350,8 +363,9 @@ describe('PagePermissionProvider', () => {
350
363
  </TestWrapper>
351
364
  );
352
365
 
353
- expect(consoleSpy).not.toHaveBeenCalledWith(
354
- expect.stringContaining('[PagePermissionProvider] Strict mode enabled')
366
+ const logger = getMockLogger();
367
+ expect(vi.mocked(logger.debug)).not.toHaveBeenCalledWith(
368
+ expect.stringContaining('Strict mode enabled')
355
369
  );
356
370
  });
357
371
  });