@jmruthers/pace-core 0.5.68 → 0.5.69

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 (375) hide show
  1. package/dist/{DataTable-4IUY7BXB.js → DataTable-MPBSXUC6.js} +5 -6
  2. package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
  3. package/dist/{chunk-PXWEDX7Y.js → chunk-2ARQW6VX.js} +3 -3
  4. package/dist/{chunk-MOJXHWDE.js → chunk-6JILXFEA.js} +335 -5
  5. package/dist/chunk-6JILXFEA.js.map +1 -0
  6. package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
  7. package/dist/chunk-6RBH67W7.js.map +1 -0
  8. package/dist/{chunk-ZMS23NS5.js → chunk-FJTAWPAQ.js} +3 -5
  9. package/dist/{chunk-ZMS23NS5.js.map → chunk-FJTAWPAQ.js.map} +1 -1
  10. package/dist/{chunk-OPCWH3A4.js → chunk-NO5QHMDX.js} +7 -6
  11. package/dist/chunk-NO5QHMDX.js.map +1 -0
  12. package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
  13. package/dist/chunk-O3NWNXDY.js.map +1 -0
  14. package/dist/{chunk-UYA6U6H7.js → chunk-Q2UP3ZWQ.js} +4 -4
  15. package/dist/{chunk-KRCRNXPD.js → chunk-RVYGJPOD.js} +79 -18
  16. package/dist/chunk-RVYGJPOD.js.map +1 -0
  17. package/dist/{chunk-NN45OBIS.js → chunk-UCMHBF7Y.js} +3 -5
  18. package/dist/{chunk-NN45OBIS.js.map → chunk-UCMHBF7Y.js.map} +1 -1
  19. package/dist/{chunk-ZPG4XPV5.js → chunk-V3QO3LL7.js} +5 -7
  20. package/dist/chunk-V3QO3LL7.js.map +1 -0
  21. package/dist/{chunk-U6GPOF6J.js → chunk-ZXJGZLLO.js} +17 -17
  22. package/dist/{chunk-U6GPOF6J.js.map → chunk-ZXJGZLLO.js.map} +1 -1
  23. package/dist/components.d.ts +1 -1
  24. package/dist/components.js +8 -9
  25. package/dist/components.js.map +1 -1
  26. package/dist/hooks.d.ts +1 -1
  27. package/dist/hooks.js +9 -6
  28. package/dist/hooks.js.map +1 -1
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +16 -16
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers.js +5 -7
  33. package/dist/rbac/index.js +5 -6
  34. package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
  35. package/dist/utils.d.ts +4 -1
  36. package/dist/utils.js +3 -3
  37. package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
  38. package/docs/README.md +22 -10
  39. package/docs/api/classes/ColumnFactory.md +1 -1
  40. package/docs/api/classes/ErrorBoundary.md +1 -1
  41. package/docs/api/classes/InvalidScopeError.md +1 -1
  42. package/docs/api/classes/MissingUserContextError.md +1 -1
  43. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  44. package/docs/api/classes/PermissionDeniedError.md +1 -1
  45. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  46. package/docs/api/classes/RBACAuditManager.md +1 -1
  47. package/docs/api/classes/RBACCache.md +1 -1
  48. package/docs/api/classes/RBACEngine.md +1 -1
  49. package/docs/api/classes/RBACError.md +1 -1
  50. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  51. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  52. package/docs/api/classes/StorageUtils.md +1 -1
  53. package/docs/api/interfaces/AggregateConfig.md +1 -1
  54. package/docs/api/interfaces/ButtonProps.md +1 -1
  55. package/docs/api/interfaces/CardProps.md +1 -1
  56. package/docs/api/interfaces/ColorPalette.md +1 -1
  57. package/docs/api/interfaces/ColorShade.md +1 -1
  58. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  59. package/docs/api/interfaces/DataTableAction.md +1 -1
  60. package/docs/api/interfaces/DataTableColumn.md +1 -1
  61. package/docs/api/interfaces/DataTableProps.md +1 -1
  62. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  63. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  64. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  65. package/docs/api/interfaces/EventContextType.md +1 -1
  66. package/docs/api/interfaces/EventLogoProps.md +1 -1
  67. package/docs/api/interfaces/EventProviderProps.md +1 -1
  68. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  69. package/docs/api/interfaces/FileUploadProps.md +1 -1
  70. package/docs/api/interfaces/FooterProps.md +1 -1
  71. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  72. package/docs/api/interfaces/InputProps.md +1 -1
  73. package/docs/api/interfaces/LabelProps.md +1 -1
  74. package/docs/api/interfaces/LoginFormProps.md +1 -1
  75. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  76. package/docs/api/interfaces/NavigationContextType.md +1 -1
  77. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  78. package/docs/api/interfaces/NavigationItem.md +1 -1
  79. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  80. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  81. package/docs/api/interfaces/Organisation.md +1 -1
  82. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  83. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  84. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  85. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  86. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  87. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  88. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  89. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  90. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  91. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  92. package/docs/api/interfaces/PaletteData.md +1 -1
  93. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  94. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  95. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  96. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  97. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  98. package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
  99. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  100. package/docs/api/interfaces/RBACConfig.md +1 -1
  101. package/docs/api/interfaces/RBACContextType.md +1 -1
  102. package/docs/api/interfaces/RBACLogger.md +1 -1
  103. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  104. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  105. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  106. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  107. package/docs/api/interfaces/RouteConfig.md +1 -1
  108. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  109. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  110. package/docs/api/interfaces/StorageConfig.md +1 -1
  111. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  112. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  113. package/docs/api/interfaces/StorageListOptions.md +1 -1
  114. package/docs/api/interfaces/StorageListResult.md +1 -1
  115. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  116. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  117. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  118. package/docs/api/interfaces/StyleImport.md +1 -1
  119. package/docs/api/interfaces/SwitchProps.md +1 -1
  120. package/docs/api/interfaces/ToastActionElement.md +1 -1
  121. package/docs/api/interfaces/ToastProps.md +1 -1
  122. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  123. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  124. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  125. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  126. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  127. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  128. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  129. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  130. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  131. package/docs/api/interfaces/UserEventAccess.md +1 -1
  132. package/docs/api/interfaces/UserMenuProps.md +1 -1
  133. package/docs/api/interfaces/UserProfile.md +1 -1
  134. package/docs/api/modules.md +39 -14
  135. package/docs/architecture/services.md +374 -0
  136. package/docs/best-practices/README.md +1 -1
  137. package/docs/best-practices/testing.md +1 -1
  138. package/docs/breaking-changes.md +182 -0
  139. package/docs/common-patterns.md +445 -0
  140. package/docs/core-concepts/authentication.md +26 -11
  141. package/docs/core-concepts/events.md +2 -0
  142. package/docs/core-concepts/organisations.md +2 -0
  143. package/docs/core-concepts/permissions.md +2 -0
  144. package/docs/{INDEX.md → documentation-index.md} +26 -38
  145. package/docs/faq.md +286 -0
  146. package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
  147. package/docs/getting-started/installation-guide.md +284 -0
  148. package/docs/getting-started/quick-start.md +8 -1
  149. package/docs/implementation-guides/app-layout.md +3 -1
  150. package/docs/implementation-guides/data-tables.md +2 -0
  151. package/docs/implementation-guides/dynamic-colors.md +47 -2
  152. package/docs/implementation-guides/event-theming-summary.md +220 -0
  153. package/docs/implementation-guides/forms.md +9 -7
  154. package/docs/implementation-guides/navigation.md +2 -0
  155. package/docs/migration/service-architecture.md +351 -0
  156. package/docs/rbac/README-rbac-rls-integration.md +2 -2
  157. package/docs/rbac/README.md +1 -1
  158. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  159. package/docs/rbac/quick-start.md +2 -0
  160. package/docs/rbac/rbac-rls-integration.md +2 -2
  161. package/docs/style-guide.md +136 -1
  162. package/docs/testing/README.md +1 -1
  163. package/docs/troubleshooting/authentication-issues.md +334 -0
  164. package/docs/troubleshooting/common-issues.md +2 -0
  165. package/docs/troubleshooting/styling-issues.md +199 -144
  166. package/docs/usage.md +23 -2
  167. package/package.json +1 -1
  168. package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
  169. package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
  170. package/src/__tests__/fixtures/test-data.ts +90 -0
  171. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
  172. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
  173. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
  174. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
  175. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
  176. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
  177. package/src/__tests__/helpers/component-test-utils.tsx +14 -4
  178. package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
  179. package/src/__tests__/helpers/test-providers.tsx +329 -0
  180. package/src/__tests__/helpers/test-utils.tsx +91 -45
  181. package/src/__tests__/helpers/timer-utils.ts +71 -0
  182. package/src/__tests__/hooks/usePermissions.test.ts +1 -5
  183. package/src/__tests__/integration/UserProfile.test.tsx +1 -5
  184. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
  185. package/src/__tests__/setup.ts +34 -28
  186. package/src/components/Alert/Alert.test.tsx +1 -5
  187. package/src/components/Avatar/Avatar.test.tsx +1 -5
  188. package/src/components/Button/Button.test.tsx +4 -20
  189. package/src/components/Card/Card.test.tsx +1 -5
  190. package/src/components/Checkbox/Checkbox.test.tsx +1 -5
  191. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
  192. package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
  193. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
  194. package/src/components/DataTable/__tests__/styles.test.ts +382 -0
  195. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
  196. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
  197. package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
  198. package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
  199. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
  200. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
  201. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
  202. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
  203. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
  204. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
  205. package/src/components/Footer/Footer.test.tsx +1 -5
  206. package/src/components/Form/Form.test.tsx +22 -35
  207. package/src/components/Header/Header.test.tsx +1 -9
  208. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
  209. package/src/components/Input/Input.test.tsx +2 -10
  210. package/src/components/LoginForm/LoginForm.test.tsx +1 -5
  211. package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
  212. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
  213. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
  214. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
  215. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
  216. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
  217. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
  218. package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
  219. package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
  220. package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
  221. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
  222. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
  223. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
  224. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
  225. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
  226. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
  227. package/src/components/Select/Select.bug-test.tsx +69 -0
  228. package/src/components/Select/Select.refactored.tsx +497 -0
  229. package/src/components/Select/Select.test.tsx +42 -49
  230. package/src/components/Select/Select.tsx +5 -2
  231. package/src/components/Select/hooks.ts +254 -0
  232. package/src/components/Switch/Switch.test.tsx +1 -5
  233. package/src/components/Table/__tests__/Table.test.tsx +775 -0
  234. package/src/components/Toast/Toast.test.tsx +15 -8
  235. package/src/components/Tooltip/Tooltip.test.tsx +1 -5
  236. package/src/components/UserMenu/UserMenu.test.tsx +3 -15
  237. package/src/components/__tests__/FileDisplay.test.tsx +575 -0
  238. package/src/components/__tests__/FileUpload.test.tsx +446 -0
  239. package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
  242. package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
  243. package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
  244. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
  245. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
  246. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
  247. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
  248. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
  249. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
  250. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
  251. package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
  252. package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
  253. package/src/hooks/index.ts +3 -0
  254. package/src/hooks/public/usePublicEvent.ts +30 -9
  255. package/src/hooks/public/usePublicRouteParams.ts +13 -3
  256. package/src/hooks/services/useAuth.ts +50 -0
  257. package/src/hooks/services/useAuthService.ts +30 -0
  258. package/src/hooks/services/useCurrentEvent.ts +36 -0
  259. package/src/hooks/services/useCurrentOrganisation.ts +52 -0
  260. package/src/hooks/services/useEventService.ts +30 -0
  261. package/src/hooks/services/useInactivityService.ts +30 -0
  262. package/src/hooks/services/useOrganisationService.ts +30 -0
  263. package/src/hooks/services/usePermissions.ts +70 -0
  264. package/src/hooks/services/useRBACService.ts +30 -0
  265. package/src/hooks/useCounter.test.ts +1 -5
  266. package/src/hooks/useEventTheme.ts +86 -0
  267. package/src/hooks/useOrganisationPermissions.test.ts +2 -5
  268. package/src/hooks/useOrganisationSecurity.test.ts +1 -5
  269. package/src/hooks/usePermissionCache.test.ts +1 -5
  270. package/src/hooks/usePermissionCheck.ts +150 -0
  271. package/src/hooks/useSecureDataAccess.test.ts +1 -5
  272. package/src/index.ts +1 -0
  273. package/src/providers/OrganisationProvider.test.tsx +1 -5
  274. package/src/providers/OrganisationProvider.tsx +56 -4
  275. package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
  276. package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
  277. package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
  278. package/src/providers/__tests__/EventProvider.test.tsx +211 -110
  279. package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
  280. package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
  281. package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
  282. package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
  283. package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
  284. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
  285. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
  286. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
  287. package/src/providers/services/AuthServiceProvider.tsx +65 -0
  288. package/src/providers/services/EventServiceProvider.tsx +83 -0
  289. package/src/providers/services/InactivityServiceProvider.tsx +83 -0
  290. package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
  291. package/src/providers/services/RBACServiceProvider.tsx +79 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
  294. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
  296. package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
  297. package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
  298. package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
  299. package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
  300. package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
  301. package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
  302. package/src/rbac/api.test.ts +1 -9
  303. package/src/rbac/cache.test.ts +10 -8
  304. package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
  305. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
  306. package/src/rbac/components/NavigationProvider.test.tsx +1 -5
  307. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
  308. package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
  309. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
  310. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
  311. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
  312. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
  313. package/src/rbac/config.test.ts +1 -5
  314. package/src/rbac/hooks/useCan.test.ts +262 -9
  315. package/src/rbac/hooks/usePermissions.test.ts +246 -6
  316. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
  317. package/src/rbac/hooks/useRBAC.test.ts +472 -198
  318. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
  319. package/src/services/AuthService.ts +416 -0
  320. package/src/services/EventService.ts +366 -0
  321. package/src/services/InactivityService.ts +388 -0
  322. package/src/services/OrganisationService.ts +592 -0
  323. package/src/services/RBACService.ts +522 -0
  324. package/src/services/__tests__/AuthService.test.ts +356 -0
  325. package/src/services/__tests__/BaseService.test.ts +314 -0
  326. package/src/services/__tests__/EventService.test.ts +489 -0
  327. package/src/services/__tests__/InactivityService.test.ts +403 -0
  328. package/src/services/__tests__/OrganisationService.test.ts +660 -0
  329. package/src/services/__tests__/RBACService.test.ts +492 -0
  330. package/src/services/base/BaseService.ts +87 -0
  331. package/src/services/interfaces/IAuthService.ts +39 -0
  332. package/src/services/interfaces/IEventService.ts +30 -0
  333. package/src/services/interfaces/IInactivityService.ts +31 -0
  334. package/src/services/interfaces/IOrganisationService.ts +41 -0
  335. package/src/services/interfaces/IRBACService.ts +62 -0
  336. package/src/theming/__tests__/runtime.test.ts +540 -0
  337. package/src/types/__tests__/file-reference.test.ts +447 -0
  338. package/src/types/__tests__/organisation.test.ts +1133 -0
  339. package/src/types/__tests__/theme.test.ts +830 -0
  340. package/src/types/__tests__/type-validation.test.ts +527 -0
  341. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
  342. package/src/utils/__tests__/debugLogger.test.ts +417 -0
  343. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
  344. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
  345. package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
  346. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
  347. package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
  348. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
  349. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
  350. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
  351. package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
  352. package/src/utils/appIdResolver.test.ts +6 -10
  353. package/src/utils/appNameResolver.simple.test.ts +142 -0
  354. package/src/utils/appNameResolver.test.ts +31 -458
  355. package/src/utils/appNameResolver.test.ts.backup +494 -0
  356. package/src/utils/debugLogger.ts +26 -5
  357. package/src/utils/formatDate.test.ts +1 -5
  358. package/src/utils/organisationContext.test.ts +1 -5
  359. package/src/utils/performanceBudgets.ts +3 -4
  360. package/src/utils/secureDataAccess.test.ts +1 -5
  361. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
  362. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
  363. package/dist/chunk-D7ARGIA3.js.map +0 -1
  364. package/dist/chunk-IPCH4YPT.js +0 -315
  365. package/dist/chunk-IPCH4YPT.js.map +0 -1
  366. package/dist/chunk-KRCRNXPD.js.map +0 -1
  367. package/dist/chunk-MOJXHWDE.js.map +0 -1
  368. package/dist/chunk-OPCWH3A4.js.map +0 -1
  369. package/dist/chunk-ZPG4XPV5.js.map +0 -1
  370. package/dist/chunk-ZPK5656W.js.map +0 -1
  371. package/docs/getting-started/installation.md +0 -269
  372. package/src/__tests__/REBUILD_PLAN.md +0 -223
  373. /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-MPBSXUC6.js.map} +0 -0
  374. /package/dist/{chunk-PXWEDX7Y.js.map → chunk-2ARQW6VX.js.map} +0 -0
  375. /package/dist/{chunk-UYA6U6H7.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
@@ -0,0 +1,522 @@
1
+ /**
2
+ * @file RBAC Service
3
+ * @package @jmruthers/pace-core
4
+ * @module Services
5
+ * @since 0.1.0
6
+ *
7
+ * RBAC service implementation.
8
+ * Handles role-based access control, permissions, and event access management.
9
+ */
10
+
11
+ import { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';
12
+ import { BaseService } from './base/BaseService';
13
+ import { IRBACService, UserEventAccess, AppConfig } from './interfaces/IRBACService';
14
+ import { AccessLevel } from '../types/unified';
15
+ import { DebugLogger } from '../utils/debugLogger';
16
+
17
+ export class RBACService extends BaseService implements IRBACService {
18
+ private permissions: Record<string, boolean> = {};
19
+ private roles: string[] = [];
20
+ private accessLevel: AccessLevel = AccessLevel.VIEWER;
21
+ private rbacLoading = false;
22
+ private rbacError: Error | null = null;
23
+ private selectedEventId: string | null = null;
24
+ private appConfig: AppConfig | null = null;
25
+ private userEventAccess: UserEventAccess[] = [];
26
+ private eventAccessLoading = false;
27
+ private selectedOrganisationId: string | null = null;
28
+
29
+ // Dependencies
30
+ private supabaseClient: SupabaseClient | null = null;
31
+ private user: User | null = null;
32
+ private session: Session | null = null;
33
+ private appName: string = '';
34
+
35
+ constructor(supabaseClient: SupabaseClient, user: User | null, session: Session | null, appName: string) {
36
+ super();
37
+ this.supabaseClient = supabaseClient;
38
+ this.user = user;
39
+ this.session = session;
40
+ this.appName = appName;
41
+ }
42
+
43
+ // Update dependencies
44
+ updateDependencies(user: User | null, session: Session | null, appName: string): void {
45
+ this.user = user;
46
+ this.session = session;
47
+ this.appName = appName;
48
+ this.notify();
49
+ }
50
+
51
+ // RBAC state getters
52
+ getPermissions(): Record<string, boolean> {
53
+ return this.permissions;
54
+ }
55
+
56
+ getRoles(): string[] {
57
+ return this.roles;
58
+ }
59
+
60
+ getAccessLevel(): AccessLevel {
61
+ return this.accessLevel;
62
+ }
63
+
64
+ isLoading(): boolean {
65
+ return this.rbacLoading;
66
+ }
67
+
68
+ getError(): Error | null {
69
+ return this.rbacError;
70
+ }
71
+
72
+ getSelectedEventId(): string | null {
73
+ return this.selectedEventId;
74
+ }
75
+
76
+ getAppConfig(): AppConfig | null {
77
+ return this.appConfig;
78
+ }
79
+
80
+ getUserEventAccess(): UserEventAccess[] {
81
+ return this.userEventAccess;
82
+ }
83
+
84
+ isEventAccessLoading(): boolean {
85
+ return this.eventAccessLoading;
86
+ }
87
+
88
+ getSelectedOrganisationId(): string | null {
89
+ return this.selectedOrganisationId;
90
+ }
91
+
92
+ // RBAC methods
93
+ hasPermission(permission: string, orgId?: string): boolean {
94
+ return !!this.permissions[permission];
95
+ }
96
+
97
+ hasAnyPermission(permissions: string[], orgId?: string): boolean {
98
+ return permissions.some(p => !!this.permissions[p]);
99
+ }
100
+
101
+ hasAllPermissions(permissions: string[], orgId?: string): boolean {
102
+ return permissions.every(p => !!this.permissions[p]);
103
+ }
104
+
105
+ hasRole(role: string): boolean {
106
+ const isSuperAdmin = this.user?.user_metadata?.globalRole === 'super_admin';
107
+ if (role.toLowerCase() === 'super_admin' || role.toLowerCase() === 'super') {
108
+ return isSuperAdmin;
109
+ }
110
+ return this.roles.includes(role);
111
+ }
112
+
113
+ hasAccessLevel(level: AccessLevel): boolean {
114
+ const levels = Object.values(AccessLevel);
115
+ return levels.indexOf(this.accessLevel) >= levels.indexOf(level);
116
+ }
117
+
118
+ canAccess(resource: string, action: string, orgId?: string): boolean {
119
+ const permission = `${resource}:${action}`;
120
+ return this.hasPermission(permission, orgId);
121
+ }
122
+
123
+ async validatePermission(permission: string, orgId?: string): Promise<boolean> {
124
+ return this.hasPermission(permission, orgId);
125
+ }
126
+
127
+ async validateAccess(resource: string, action: string, orgId?: string): Promise<boolean> {
128
+ return this.canAccess(resource, action, orgId);
129
+ }
130
+
131
+ async refreshPermissions(eventId?: string, orgId?: string): Promise<void> {
132
+ if (!this.supabaseClient || !this.user || !this.appConfig || !this.session) {
133
+ DebugLogger.log('RBACService', 'refreshPermissions: Missing required dependencies, clearing permissions');
134
+ this.permissions = {};
135
+ this.roles = [];
136
+ this.accessLevel = AccessLevel.VIEWER;
137
+ this.notify();
138
+ return;
139
+ }
140
+
141
+ // Check for super admin first - admin override should happen regardless of app configuration
142
+ const isSuperAdmin = this.user?.user_metadata?.globalRole === 'super_admin';
143
+ if (isSuperAdmin) {
144
+ this.permissions = {
145
+ 'admin:create': true,
146
+ 'admin:read': true,
147
+ 'admin:update': true,
148
+ 'admin:delete': true,
149
+ 'users:create': true,
150
+ 'users:read': true,
151
+ 'users:update': true,
152
+ 'users:delete': true,
153
+ 'events:create': true,
154
+ 'events:read': true,
155
+ 'events:update': true,
156
+ 'events:delete': true
157
+ };
158
+ this.roles = ['super_admin'];
159
+ this.accessLevel = AccessLevel.ADMIN;
160
+ this.notify();
161
+ return;
162
+ }
163
+
164
+ // Determine if we should load permissions without an event
165
+ const shouldLoadDirectPermissions = !eventId && !this.appConfig.requires_event;
166
+ const shouldLoadEventPermissions = eventId;
167
+ const shouldClearPermissions = !eventId && this.appConfig.requires_event;
168
+
169
+ // If no eventId and app requires events, clear permissions
170
+ if (shouldClearPermissions) {
171
+ this.permissions = {};
172
+ this.roles = [];
173
+ this.accessLevel = AccessLevel.VIEWER;
174
+ this.notify();
175
+ return;
176
+ }
177
+
178
+ // Only proceed if we should load permissions
179
+ if (!shouldLoadDirectPermissions && !shouldLoadEventPermissions) {
180
+ return;
181
+ }
182
+
183
+ this.rbacLoading = true;
184
+ this.rbacError = null;
185
+ this.notify();
186
+
187
+ try {
188
+ // Use the same app name resolution as PagePermissionGuard
189
+ const { getCurrentAppName } = await import('../utils/appNameResolver');
190
+ const resolvedAppName = getCurrentAppName() || this.appName;
191
+
192
+ // First resolve app name to app_id
193
+ const { data: appData, error: appError } = await this.supabaseClient
194
+ .from('rbac_apps')
195
+ .select('id')
196
+ .eq('name', resolvedAppName)
197
+ .eq('is_active', true)
198
+ .single();
199
+
200
+ if (appError || !appData) {
201
+ console.warn('App not found or inactive:', resolvedAppName);
202
+ this.rbacLoading = false;
203
+ this.notify();
204
+ return;
205
+ }
206
+
207
+ const { data, error } = await this.supabaseClient.rpc('rbac_permissions_get', {
208
+ p_user_id: this.user.id,
209
+ p_app_id: appData.id,
210
+ p_event_id: eventId || null,
211
+ p_organisation_id: orgId || this.selectedOrganisationId || null
212
+ });
213
+
214
+ if (error) {
215
+ throw error;
216
+ }
217
+
218
+ const { permissions, roles, access_level } = this.transformRBACPermissions(data, this.appName);
219
+
220
+ this.permissions = permissions;
221
+ this.roles = roles;
222
+ this.accessLevel = access_level;
223
+ } catch (err: any) {
224
+ this.rbacError = err;
225
+ } finally {
226
+ this.rbacLoading = false;
227
+ this.notify();
228
+ }
229
+ }
230
+
231
+ setSelectedEventId(eventId: string | null): void {
232
+ this.selectedEventId = eventId;
233
+ this.notify();
234
+ }
235
+
236
+ async loadUserEventAccess(orgId?: string): Promise<void> {
237
+ if (!this.supabaseClient || !this.user || !this.session) {
238
+ DebugLogger.log('RBACService', 'loadUserEventAccess: Missing required dependencies, clearing event access');
239
+ this.userEventAccess = [];
240
+ this.notify();
241
+ return;
242
+ }
243
+
244
+ this.eventAccessLoading = true;
245
+ this.notify();
246
+
247
+ try {
248
+ // Use the same app name resolution as PagePermissionGuard
249
+ const { getCurrentAppName } = await import('../utils/appNameResolver');
250
+ const resolvedAppName = getCurrentAppName() || this.appName;
251
+
252
+ // First resolve app name to app_id
253
+ const { data: appData, error: appError } = await this.supabaseClient
254
+ .from('rbac_apps')
255
+ .select('id')
256
+ .eq('name', resolvedAppName)
257
+ .eq('is_active', true)
258
+ .single();
259
+
260
+ if (appError || !appData) {
261
+ console.warn('App not found or inactive:', resolvedAppName);
262
+ this.eventAccessLoading = false;
263
+ this.notify();
264
+ return;
265
+ }
266
+
267
+ const { data, error } = await this.supabaseClient
268
+ .from('rbac_event_app_roles')
269
+ .select(`
270
+ event_id,
271
+ role,
272
+ granted_at
273
+ `)
274
+ .eq('user_id', this.user.id)
275
+ .eq('app_id', appData.id);
276
+
277
+ if (error) {
278
+ console.error('Failed to load user event access:', error);
279
+ this.userEventAccess = [];
280
+ this.notify();
281
+ return;
282
+ }
283
+
284
+ const eventAccess = data?.map(item => ({
285
+ event_id: item.event_id,
286
+ event_name: (item as any).event_name || 'Unknown Event', // Event details not available in this query
287
+ event_description: (item as any).event_description || null, // Not available in this schema
288
+ start_date: (item as any).start_date || '', // Event date not available in this query
289
+ end_date: (item as any).end_date || '', // Event date not available in this query
290
+ event_status: (item as any).event_status || 'unknown', // Not available in this schema
291
+ app_id: (item as any).app_id || appData.id,
292
+ access_level: (item as any).access_level || item.role, // Map role to access_level
293
+ granted_at: item.granted_at,
294
+ organisation_id: (item as any).organisation_id || '' // Will be populated from event's organisation_id if needed
295
+ })) || [];
296
+
297
+ this.userEventAccess = eventAccess;
298
+ } catch (error) {
299
+ console.error('Error loading user event access:', error);
300
+ this.userEventAccess = [];
301
+ } finally {
302
+ this.eventAccessLoading = false;
303
+ this.notify();
304
+ }
305
+ }
306
+
307
+ getUserEventAccessById(eventId: string): UserEventAccess | undefined {
308
+ return this.userEventAccess.find(access => access.event_id === eventId);
309
+ }
310
+
311
+ requireOrganisationContext(): string {
312
+ if (!this.selectedOrganisationId) {
313
+ throw new Error('Organisation context is required but not available');
314
+ }
315
+ return this.selectedOrganisationId;
316
+ }
317
+
318
+ // Lifecycle methods
319
+ async initialize(): Promise<void> {
320
+ await super.initialize();
321
+ await this.loadAppConfig();
322
+
323
+ // Load permissions for regular users after app config is loaded
324
+ const isSuperAdmin = this.user?.user_metadata?.globalRole === 'super_admin';
325
+ if (!isSuperAdmin && this.appConfig) {
326
+ await this.refreshPermissions(this.selectedEventId || undefined);
327
+ }
328
+
329
+ await this.loadPersistedState();
330
+ }
331
+
332
+ cleanup(): void {
333
+ super.cleanup();
334
+ }
335
+
336
+ protected async doInitialize(): Promise<void> {
337
+ // Set super admin roles and permissions based on user metadata
338
+ const isSuperAdmin = this.user?.user_metadata?.globalRole === 'super_admin';
339
+ if (isSuperAdmin) {
340
+ this.roles = ['super_admin'];
341
+ this.accessLevel = AccessLevel.ADMIN;
342
+ // Set super admin permissions immediately
343
+ this.permissions = {
344
+ 'admin:create': true,
345
+ 'admin:read': true,
346
+ 'admin:update': true,
347
+ 'admin:delete': true,
348
+ 'users:create': true,
349
+ 'users:read': true,
350
+ 'users:update': true,
351
+ 'users:delete': true,
352
+ 'events:create': true,
353
+ 'events:read': true,
354
+ 'events:update': true,
355
+ 'events:delete': true
356
+ };
357
+ } else {
358
+ this.roles = [];
359
+ this.accessLevel = AccessLevel.VIEWER;
360
+ this.permissions = {};
361
+ }
362
+ }
363
+
364
+ protected doCleanup(): void {
365
+ // No specific cleanup needed
366
+ }
367
+
368
+ private async loadAppConfig(): Promise<void> {
369
+ if (!this.supabaseClient) return;
370
+
371
+ try {
372
+ // Use the same app name resolution as PagePermissionGuard
373
+ const { getCurrentAppName } = await import('../utils/appNameResolver');
374
+ const resolvedAppName = getCurrentAppName() || this.appName;
375
+
376
+ // First resolve app name to app_id
377
+ const { data: appData, error: appError } = await this.supabaseClient
378
+ .from('rbac_apps')
379
+ .select('id')
380
+ .eq('name', resolvedAppName)
381
+ .eq('is_active', true)
382
+ .single();
383
+
384
+ if (appError || !appData) {
385
+ console.warn('App not found or inactive:', resolvedAppName);
386
+ this.appConfig = {
387
+ supports_direct_access: false,
388
+ requires_event: true
389
+ };
390
+ return;
391
+ }
392
+
393
+ const response = await this.supabaseClient.rpc('get_app_config', {
394
+ app_id: appData.id
395
+ });
396
+
397
+ const { data } = response || {};
398
+
399
+ if (data && data.length > 0) {
400
+ this.appConfig = {
401
+ supports_direct_access: false,
402
+ requires_event: data[0].requires_event
403
+ };
404
+ } else {
405
+ // Default configuration if app not found
406
+ this.appConfig = {
407
+ supports_direct_access: false,
408
+ requires_event: true
409
+ };
410
+ }
411
+ } catch (error) {
412
+ console.warn('Failed to load app configuration:', error);
413
+ // Default configuration on error
414
+ this.appConfig = {
415
+ supports_direct_access: false,
416
+ requires_event: true
417
+ };
418
+ }
419
+ }
420
+
421
+ private async loadPersistedState(): Promise<void> {
422
+ try {
423
+ const persistedEvent = localStorage.getItem('pace-core-selected-event');
424
+ if (persistedEvent) {
425
+ this.selectedEventId = JSON.parse(persistedEvent);
426
+ }
427
+ } catch (error) {
428
+ console.warn("Clearing corrupted localStorage data");
429
+ localStorage.removeItem('pace-core-selected-event');
430
+ }
431
+ }
432
+
433
+ private transformRBACPermissions(rbacData: any[], appName: string) {
434
+ const permissions: Record<string, boolean> = {};
435
+ let roles: string[] = [];
436
+ let access_level: AccessLevel = AccessLevel.VIEWER;
437
+
438
+ if (!rbacData || !Array.isArray(rbacData)) {
439
+ return { permissions: {}, roles: ['viewer'], access_level: AccessLevel.VIEWER };
440
+ }
441
+
442
+ // Check for super admin first
443
+ const superAdminPerm = rbacData.find((p: any) => p.permission_type === 'all_permissions');
444
+ if (superAdminPerm) {
445
+ return {
446
+ permissions: { 'all:all': true } as Record<string, boolean>,
447
+ roles: ['super'],
448
+ access_level: AccessLevel.SUPER
449
+ };
450
+ }
451
+
452
+ // Process event-app permissions
453
+ const eventAppPerms = rbacData.filter((p: any) => p.permission_type === 'event_app_access');
454
+ if (eventAppPerms.length > 0) {
455
+ const role = eventAppPerms[0].role_name;
456
+
457
+ // Map RBAC roles to AccessLevel
458
+ switch (role) {
459
+ case 'event_admin':
460
+ access_level = AccessLevel.ADMIN;
461
+ roles = ['admin'];
462
+ break;
463
+ case 'planner':
464
+ access_level = AccessLevel.PLANNER;
465
+ roles = ['planner'];
466
+ break;
467
+ case 'participant':
468
+ access_level = AccessLevel.PARTICIPANT;
469
+ roles = ['participant'];
470
+ break;
471
+ case 'editor':
472
+ access_level = AccessLevel.EDITOR;
473
+ roles = ['editor'];
474
+ break;
475
+ case 'viewer':
476
+ default:
477
+ access_level = AccessLevel.VIEWER;
478
+ roles = ['viewer'];
479
+ break;
480
+ }
481
+
482
+ // Set permissions from the RPC response
483
+ eventAppPerms.forEach((perm: any) => {
484
+ if (perm.permission) {
485
+ permissions[perm.permission] = true;
486
+ }
487
+ });
488
+
489
+ // For now, we'll set basic permissions based on role
490
+ // In a full implementation, you'd want to fetch page-specific permissions
491
+ const basePermissions = ['read'];
492
+ if (['event_admin', 'planner'].includes(role)) {
493
+ basePermissions.push('create', 'update');
494
+ }
495
+ if (role === 'event_admin') {
496
+ basePermissions.push('delete');
497
+ }
498
+
499
+ // Set permissions for all pages (simplified approach)
500
+ // In a real implementation, you'd want to get actual page permissions
501
+ basePermissions.forEach(operation => {
502
+ permissions[`default:${operation}`] = true;
503
+ });
504
+ }
505
+
506
+ // Process organisation permissions
507
+ const orgPerms = rbacData.filter((p: any) => p.permission_type === 'organisation_access');
508
+ if (orgPerms.length > 0) {
509
+ const role = orgPerms[0].role_name;
510
+ if (role === 'org_admin') {
511
+ access_level = AccessLevel.ADMIN;
512
+ roles = ['admin'];
513
+ // Org admins get all permissions
514
+ ['create', 'read', 'update', 'delete'].forEach(operation => {
515
+ permissions[`default:${operation}`] = true;
516
+ });
517
+ }
518
+ }
519
+
520
+ return { permissions, roles, access_level };
521
+ }
522
+ }