@jmruthers/pace-core 0.5.75 → 0.5.77

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 (507) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-SBHZQtCH.d.ts} +5 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/DataTable-QCNCV6IK.js +157 -0
  5. package/dist/{PublicLoadingSpinner-BKNBT6b6.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +33 -19
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-Z2FWNW7O.js} +4 -5
  8. package/dist/{api-DDMUKIUD.js → api-KG4A2X7P.js} +9 -3
  9. package/dist/{audit-6TOCAMKO.js → audit-65VNHEV2.js} +2 -2
  10. package/dist/{chunk-2DFZ432F.js → chunk-7PX43UYN.js} +197 -629
  11. package/dist/chunk-7PX43UYN.js.map +1 -0
  12. package/dist/{chunk-DAXLNIDY.js → chunk-C4RQ3GQA.js} +108 -32
  13. package/dist/chunk-C4RQ3GQA.js.map +1 -0
  14. package/dist/{chunk-LW7MMEAQ.js → chunk-CRKP3HXI.js} +2 -2
  15. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  16. package/dist/chunk-CVMVPYAL.js.map +1 -0
  17. package/dist/{chunk-CY3AHGO4.js → chunk-DDPG7FCX.js} +3395 -3254
  18. package/dist/chunk-DDPG7FCX.js.map +1 -0
  19. package/dist/{chunk-URUTVZ7N.js → chunk-DVHZ5L55.js} +2 -2
  20. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  21. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  22. package/dist/{chunk-WN6XJWOS.js → chunk-JDQ7T3QB.js} +256 -743
  23. package/dist/chunk-JDQ7T3QB.js.map +1 -0
  24. package/dist/{chunk-ZTT2AXMX.js → chunk-LMYTEMUH.js} +153 -132
  25. package/dist/chunk-LMYTEMUH.js.map +1 -0
  26. package/dist/{chunk-33PHABLB.js → chunk-NKT2DLZI.js} +13 -130
  27. package/dist/chunk-NKT2DLZI.js.map +1 -0
  28. package/dist/chunk-PUKTJMRT.js +732 -0
  29. package/dist/chunk-PUKTJMRT.js.map +1 -0
  30. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  31. package/dist/chunk-Q7APDV6H.js.map +1 -0
  32. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  33. package/dist/chunk-S63MFSY6.js.map +1 -0
  34. package/dist/{chunk-NTNILOBC.js → chunk-TLD5BEU6.js} +4 -4
  35. package/dist/chunk-WUXCWRL6.js +20 -0
  36. package/dist/chunk-WUXCWRL6.js.map +1 -0
  37. package/dist/{chunk-YNUBMSMV.js → chunk-YCKPEMJA.js} +186 -263
  38. package/dist/chunk-YCKPEMJA.js.map +1 -0
  39. package/dist/{chunk-A4FUBC7B.js → chunk-Z3T6RK3K.js} +2 -4
  40. package/dist/{chunk-A4FUBC7B.js.map → chunk-Z3T6RK3K.js.map} +1 -1
  41. package/dist/components.d.ts +6 -6
  42. package/dist/components.js +17 -20
  43. package/dist/components.js.map +1 -1
  44. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  45. package/dist/hooks.d.ts +21 -44
  46. package/dist/hooks.js +12 -13
  47. package/dist/hooks.js.map +1 -1
  48. package/dist/index.d.ts +19 -27
  49. package/dist/index.js +27 -33
  50. package/dist/index.js.map +1 -1
  51. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  52. package/dist/providers.d.ts +7 -21
  53. package/dist/providers.js +3 -10
  54. package/dist/rbac/index.d.ts +118 -215
  55. package/dist/rbac/index.js +18 -18
  56. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  57. package/dist/types.d.ts +3 -3
  58. package/dist/types.js +61 -18
  59. package/dist/types.js.map +1 -1
  60. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  61. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  62. package/dist/utils.d.ts +2 -2
  63. package/dist/utils.js +52 -9
  64. package/dist/utils.js.map +1 -1
  65. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  66. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  67. package/docs/README.md +142 -147
  68. package/docs/STYLE_GUIDE.md +37 -0
  69. package/docs/api/classes/ColumnFactory.md +17 -17
  70. package/docs/api/classes/ErrorBoundary.md +1 -1
  71. package/docs/api/classes/InvalidScopeError.md +4 -4
  72. package/docs/api/classes/MissingUserContextError.md +4 -4
  73. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  74. package/docs/api/classes/PermissionDeniedError.md +5 -5
  75. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  76. package/docs/api/classes/RBACAuditManager.md +8 -8
  77. package/docs/api/classes/RBACCache.md +35 -5
  78. package/docs/api/classes/RBACEngine.md +49 -20
  79. package/docs/api/classes/RBACError.md +4 -4
  80. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  81. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  82. package/docs/api/classes/StorageUtils.md +1 -1
  83. package/docs/api/enums/FileCategory.md +1 -1
  84. package/docs/api/interfaces/AggregateConfig.md +4 -4
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CardProps.md +1 -1
  87. package/docs/api/interfaces/ColorPalette.md +1 -1
  88. package/docs/api/interfaces/ColorShade.md +1 -1
  89. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  90. package/docs/api/interfaces/DataRecord.md +11 -0
  91. package/docs/api/interfaces/DataTableAction.md +65 -29
  92. package/docs/api/interfaces/DataTableColumn.md +36 -23
  93. package/docs/api/interfaces/DataTableProps.md +80 -38
  94. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  95. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  96. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  97. package/docs/api/interfaces/EventLogoProps.md +1 -1
  98. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  99. package/docs/api/interfaces/FileMetadata.md +1 -1
  100. package/docs/api/interfaces/FileReference.md +1 -1
  101. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  102. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  103. package/docs/api/interfaces/FileUploadProps.md +1 -1
  104. package/docs/api/interfaces/FooterProps.md +1 -1
  105. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  106. package/docs/api/interfaces/InputProps.md +1 -1
  107. package/docs/api/interfaces/LabelProps.md +1 -1
  108. package/docs/api/interfaces/LoginFormProps.md +1 -1
  109. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  110. package/docs/api/interfaces/NavigationContextType.md +9 -9
  111. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  112. package/docs/api/interfaces/NavigationItem.md +1 -1
  113. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  114. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  115. package/docs/api/interfaces/Organisation.md +1 -1
  116. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  117. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  118. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  119. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  120. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  121. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  122. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  123. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  124. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  125. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  126. package/docs/api/interfaces/PaletteData.md +1 -1
  127. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  128. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  129. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  130. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  131. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  132. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  133. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  134. package/docs/api/interfaces/RBACConfig.md +1 -1
  135. package/docs/api/interfaces/RBACLogger.md +1 -1
  136. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  137. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  138. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  139. package/docs/api/interfaces/RouteConfig.md +2 -2
  140. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  141. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  142. package/docs/api/interfaces/StorageConfig.md +1 -1
  143. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  144. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  145. package/docs/api/interfaces/StorageListOptions.md +1 -1
  146. package/docs/api/interfaces/StorageListResult.md +1 -1
  147. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  148. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  149. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  150. package/docs/api/interfaces/StyleImport.md +1 -1
  151. package/docs/api/interfaces/SwitchProps.md +1 -1
  152. package/docs/api/interfaces/ToastActionElement.md +1 -1
  153. package/docs/api/interfaces/ToastProps.md +1 -1
  154. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  155. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  156. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  157. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  159. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  160. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  161. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  162. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  163. package/docs/api/interfaces/UseResolvedScopeOptions.md +47 -0
  164. package/docs/api/interfaces/UseResolvedScopeReturn.md +47 -0
  165. package/docs/api/interfaces/UserEventAccess.md +11 -11
  166. package/docs/api/interfaces/UserMenuProps.md +1 -1
  167. package/docs/api/interfaces/UserProfile.md +1 -1
  168. package/docs/api/modules.md +303 -275
  169. package/docs/api-reference/components.md +193 -0
  170. package/docs/api-reference/hooks.md +265 -0
  171. package/docs/api-reference/providers.md +32 -7
  172. package/docs/api-reference/types.md +6 -0
  173. package/docs/api-reference/utilities.md +207 -0
  174. package/docs/architecture/README.md +6 -0
  175. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  176. package/docs/architecture/rbac-security-architecture.md +258 -0
  177. package/docs/architecture/services.md +9 -1
  178. package/docs/best-practices/README.md +26 -0
  179. package/docs/best-practices/accessibility.md +572 -0
  180. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  181. package/docs/best-practices/deployment.md +6 -0
  182. package/docs/best-practices/performance.md +475 -2
  183. package/docs/best-practices/security.md +6 -0
  184. package/docs/best-practices/testing.md +6 -0
  185. package/docs/core-concepts/authentication.md +21 -7
  186. package/docs/core-concepts/events.md +6 -0
  187. package/docs/core-concepts/organisations.md +6 -0
  188. package/docs/core-concepts/permissions.md +6 -0
  189. package/docs/core-concepts/rbac-system.md +6 -0
  190. package/docs/documentation-index.md +121 -182
  191. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  192. package/docs/getting-started/documentation-index.md +40 -0
  193. package/docs/getting-started/examples/README.md +878 -35
  194. package/docs/{faq.md → getting-started/faq.md} +7 -1
  195. package/docs/getting-started/installation-guide.md +6 -0
  196. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  197. package/docs/implementation-guides/app-layout.md +6 -0
  198. package/docs/implementation-guides/authentication.md +1021 -0
  199. package/docs/implementation-guides/component-styling.md +416 -0
  200. package/docs/implementation-guides/data-tables.md +1264 -2076
  201. package/docs/implementation-guides/dynamic-colors.md +6 -0
  202. package/docs/implementation-guides/event-theming-summary.md +6 -0
  203. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  204. package/docs/implementation-guides/file-upload-storage.md +6 -0
  205. package/docs/implementation-guides/forms.md +6 -0
  206. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  207. package/docs/implementation-guides/navigation.md +6 -0
  208. package/docs/implementation-guides/organisation-security.md +6 -0
  209. package/docs/implementation-guides/permission-enforcement.md +6 -0
  210. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  211. package/docs/implementation-guides/public-pages.md +6 -0
  212. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  213. package/docs/migration/README.md +7 -1
  214. package/docs/migration/organisation-context-timing-fix.md +6 -0
  215. package/docs/migration/rbac-migration.md +44 -1
  216. package/docs/migration/service-architecture.md +6 -0
  217. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  218. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  219. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  220. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  221. package/docs/rbac/README.md +6 -0
  222. package/docs/rbac/advanced-patterns.md +6 -0
  223. package/docs/rbac/api-reference.md +7 -1
  224. package/docs/rbac/breaking-changes-v3.md +222 -0
  225. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  226. package/docs/rbac/examples.md +6 -0
  227. package/docs/rbac/getting-started.md +6 -0
  228. package/docs/rbac/migration-guide.md +260 -0
  229. package/docs/rbac/quick-start.md +6 -0
  230. package/docs/rbac/rbac-rls-integration.md +6 -0
  231. package/docs/rbac/super-admin-guide.md +6 -0
  232. package/docs/rbac/troubleshooting.md +6 -0
  233. package/docs/security/README.md +6 -0
  234. package/docs/security/checklist.md +6 -0
  235. package/docs/styles/README.md +7 -1
  236. package/docs/{usage.md → styles/usage.md} +6 -0
  237. package/docs/testing/README.md +6 -0
  238. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  239. package/docs/troubleshooting/README.md +387 -5
  240. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  241. package/docs/troubleshooting/common-issues.md +6 -0
  242. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  243. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  244. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  245. package/docs/troubleshooting/styling-issues.md +6 -0
  246. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  247. package/package.json +1 -1
  248. package/src/__tests__/TEST_GUIDE_CURSOR.md +290 -0
  249. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  250. package/src/__tests__/helpers/supabaseMock.ts +48 -2
  251. package/src/__tests__/helpers/test-providers.tsx +3 -53
  252. package/src/components/DataTable/DataTable.test.tsx +319 -0
  253. package/src/components/DataTable/DataTable.tsx +32 -11
  254. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  255. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +17 -6
  256. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  257. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +96 -10
  258. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  259. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  260. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  261. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  262. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  263. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  264. package/src/components/DataTable/components/DataTableCore.tsx +442 -665
  265. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  266. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  267. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  268. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  269. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  270. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  271. package/src/components/DataTable/components/UnifiedTableBody.tsx +222 -278
  272. package/src/components/DataTable/components/index.ts +1 -2
  273. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  274. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +208 -275
  275. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  276. package/src/components/DataTable/core/index.ts +1 -8
  277. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  278. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  279. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  280. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  281. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +521 -0
  282. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +570 -0
  283. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  284. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +214 -0
  285. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +224 -0
  286. package/src/components/DataTable/hooks/index.ts +13 -0
  287. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  288. package/src/components/DataTable/hooks/useColumnReordering.ts +1 -0
  289. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  290. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  291. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  292. package/src/components/DataTable/hooks/useDataTablePermissions.ts +193 -0
  293. package/src/components/DataTable/hooks/useDataTableState.ts +51 -17
  294. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  295. package/src/components/DataTable/hooks/useHierarchicalState.ts +41 -9
  296. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  297. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  298. package/src/components/DataTable/hooks/useTableColumns.ts +156 -0
  299. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  300. package/src/components/DataTable/index.ts +13 -12
  301. package/src/components/DataTable/types.ts +129 -9
  302. package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +89 -0
  303. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +162 -28
  304. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +573 -0
  305. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +247 -0
  306. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +8 -6
  307. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +466 -0
  308. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +251 -0
  309. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  310. package/src/components/DataTable/utils/debugTools.ts +47 -21
  311. package/src/components/DataTable/utils/errorHandling.ts +52 -460
  312. package/src/components/DataTable/utils/exportUtils.ts +157 -28
  313. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  314. package/src/components/DataTable/utils/hierarchicalSorting.ts +50 -3
  315. package/src/components/DataTable/utils/hierarchicalUtils.ts +167 -34
  316. package/src/components/DataTable/utils/index.ts +7 -0
  317. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  318. package/src/components/DataTable/utils/rowUtils.ts +69 -0
  319. package/src/components/EventSelector/EventSelector.test.tsx +672 -0
  320. package/src/components/Label/__tests__/Label.test.tsx +434 -0
  321. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  322. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  323. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  324. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  325. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  326. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +190 -0
  327. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +185 -0
  328. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  329. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +313 -0
  330. package/src/components/Select/Select.test.tsx +143 -120
  331. package/src/components/Select/Select.tsx +48 -212
  332. package/src/components/Select/hooks.ts +36 -1
  333. package/src/components/Select/index.ts +2 -1
  334. package/src/components/examples/PermissionExample.tsx +173 -0
  335. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  336. package/src/examples/PublicEventPage.tsx +274 -0
  337. package/src/examples/PublicPageApp.tsx +308 -0
  338. package/src/examples/PublicPageUsageExample.tsx +216 -0
  339. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  340. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  341. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  342. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  343. package/src/hooks/useOrganisationPermissions.ts +12 -6
  344. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  345. package/src/hooks/useOrganisationSecurity.ts +41 -10
  346. package/src/hooks/useSecureDataAccess.test.ts +32 -29
  347. package/src/index.ts +0 -1
  348. package/src/providers/AuthProvider.simplified.tsx +880 -0
  349. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  350. package/src/providers/__tests__/ProviderLifecycle.test.tsx +341 -0
  351. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  352. package/src/providers/index.ts +0 -1
  353. package/src/providers/services/EventServiceProvider.tsx +19 -15
  354. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  355. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  356. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  357. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  358. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  359. package/src/rbac/README.md +1 -1
  360. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  361. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  362. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  363. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  364. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  365. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  366. package/src/rbac/adapters.tsx +26 -69
  367. package/src/rbac/api.test.ts +90 -27
  368. package/src/rbac/api.ts +61 -10
  369. package/src/rbac/audit.test.ts +33 -38
  370. package/src/rbac/audit.ts +21 -6
  371. package/src/rbac/cache.ts +33 -1
  372. package/src/rbac/components/NavigationGuard.tsx +11 -11
  373. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  374. package/src/rbac/components/NavigationProvider.tsx +37 -13
  375. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  376. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  377. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  378. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  379. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  380. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  381. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  382. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  383. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  384. package/src/rbac/engine.test.simple.ts +19 -13
  385. package/src/rbac/engine.test.ts +1 -0
  386. package/src/rbac/engine.ts +330 -766
  387. package/src/rbac/errors.ts +156 -0
  388. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +437 -0
  389. package/src/rbac/hooks/index.ts +2 -0
  390. package/src/rbac/hooks/usePermissions.ts +32 -10
  391. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  392. package/src/rbac/hooks/useRBAC.ts +147 -193
  393. package/src/rbac/hooks/useResolvedScope.ts +244 -0
  394. package/src/rbac/index.ts +7 -4
  395. package/src/rbac/security.ts +109 -18
  396. package/src/rbac/types.ts +12 -1
  397. package/src/services/AuthService.ts +2 -15
  398. package/src/services/EventService.ts +26 -46
  399. package/src/services/OrganisationService.ts +51 -31
  400. package/src/services/__tests__/AuthService.test.ts +1 -1
  401. package/src/services/__tests__/EventService.test.ts +1 -1
  402. package/src/services/__tests__/InactivityService.lifecycle.test.ts +411 -0
  403. package/src/services/__tests__/OrganisationService.pagination.test.ts +375 -0
  404. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  405. package/src/styles/base.css +208 -0
  406. package/src/styles/semantic.css +24 -0
  407. package/src/types/__tests__/README.md +114 -0
  408. package/src/types/__tests__/validation.test.ts +731 -0
  409. package/src/types/database.generated.ts +7347 -0
  410. package/src/types/database.ts +20 -0
  411. package/src/utils/__tests__/file-reference.test.ts +383 -0
  412. package/src/utils/__tests__/performanceBenchmark.test.ts +175 -0
  413. package/src/utils/appNameResolver.test.ts +54 -0
  414. package/src/utils/logger.ts +179 -0
  415. package/src/utils/organisationContext.ts +11 -4
  416. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  417. package/src/validation/__tests__/csrf.unit.test.ts +63 -0
  418. package/src/validation/__tests__/passwordSchema.unit.test.ts +105 -0
  419. package/dist/DataTable-HWZQGASI.js +0 -102
  420. package/dist/appNameResolver-UURKN7NF.js +0 -22
  421. package/dist/audit-6TOCAMKO.js.map +0 -1
  422. package/dist/chunk-2CHATWBF.js +0 -523
  423. package/dist/chunk-2CHATWBF.js.map +0 -1
  424. package/dist/chunk-2DFZ432F.js.map +0 -1
  425. package/dist/chunk-33PHABLB.js.map +0 -1
  426. package/dist/chunk-B2WTCLCV.js.map +0 -1
  427. package/dist/chunk-CY3AHGO4.js.map +0 -1
  428. package/dist/chunk-DAXLNIDY.js.map +0 -1
  429. package/dist/chunk-FGMFQSHX.js.map +0 -1
  430. package/dist/chunk-TYHR5X4W.js +0 -33
  431. package/dist/chunk-TYHR5X4W.js.map +0 -1
  432. package/dist/chunk-ULBI5JGB.js +0 -109
  433. package/dist/chunk-ULBI5JGB.js.map +0 -1
  434. package/dist/chunk-WN6XJWOS.js.map +0 -1
  435. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  436. package/dist/chunk-YNUBMSMV.js.map +0 -1
  437. package/dist/chunk-ZTT2AXMX.js.map +0 -1
  438. package/dist/eventContext-BBA42P6G.js +0 -14
  439. package/dist/eventContext-BBA42P6G.js.map +0 -1
  440. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  441. package/docs/api/interfaces/RBACContextType.md +0 -468
  442. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  443. package/docs/breaking-changes.md +0 -179
  444. package/docs/consuming-app-example.md +0 -290
  445. package/docs/documentation-style-checklist.md +0 -294
  446. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  447. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  448. package/docs/getting-started/examples/full-featured-app.md +0 -616
  449. package/docs/getting-started/quick-start.md +0 -426
  450. package/docs/implementation-guides/datatable-filtering.md +0 -313
  451. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  452. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  453. package/docs/implementation-guides/large-datasets.md +0 -281
  454. package/docs/implementation-guides/performance.md +0 -403
  455. package/docs/migration/quick-migration-guide.md +0 -320
  456. package/docs/migration-guide.md +0 -193
  457. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  458. package/docs/performance/README.md +0 -551
  459. package/docs/style-guide.md +0 -925
  460. package/docs/troubleshooting/authentication-issues.md +0 -334
  461. package/docs/troubleshooting/debugging.md +0 -1117
  462. package/docs/troubleshooting/migration.md +0 -918
  463. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  464. package/src/components/DataTable/components/DataTableBody.tsx +0 -488
  465. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -144
  466. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -515
  467. package/src/components/DataTable/core/ActionManager.ts +0 -235
  468. package/src/components/DataTable/core/ColumnManager.ts +0 -215
  469. package/src/components/DataTable/core/DataManager.ts +0 -188
  470. package/src/components/DataTable/core/DataTableContext.tsx +0 -181
  471. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -264
  472. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  473. package/src/components/DataTable/core/StateManager.ts +0 -311
  474. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -634
  475. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -193
  476. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -519
  477. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -714
  478. package/src/components/DataTable/core/interfaces.ts +0 -338
  479. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  480. package/src/components/Select/Select.bug-test.tsx +0 -69
  481. package/src/components/Select/Select.refactored.tsx +0 -497
  482. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  483. package/src/hooks/services/usePermissions.ts +0 -70
  484. package/src/hooks/services/useRBACService.ts +0 -30
  485. package/src/hooks/usePermissionCheck.ts +0 -150
  486. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  487. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  488. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  489. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  490. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  491. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  492. package/src/rbac/providers/RBACProvider.tsx +0 -645
  493. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  494. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  495. package/src/rbac/providers/index.ts +0 -11
  496. package/src/services/RBACService.ts +0 -522
  497. package/src/services/__tests__/RBACService.test.ts +0 -492
  498. package/src/services/interfaces/IRBACService.ts +0 -62
  499. package/src/utils/appNameResolver.test 2.ts +0 -494
  500. /package/dist/{DataTable-HWZQGASI.js.map → DataTable-QCNCV6IK.js.map} +0 -0
  501. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-Z2FWNW7O.js.map} +0 -0
  502. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  503. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  504. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-CRKP3HXI.js.map} +0 -0
  505. /package/dist/{chunk-URUTVZ7N.js.map → chunk-DVHZ5L55.js.map} +0 -0
  506. /package/dist/{chunk-NTNILOBC.js.map → chunk-TLD5BEU6.js.map} +0 -0
  507. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -8,7 +8,7 @@
8
8
  * Provides organisation service instance to React components.
9
9
  */
10
10
 
11
- import React, { createContext, useContext, useMemo, useEffect } from 'react';
11
+ import React, { createContext, useContext, useMemo, useEffect, useRef } from 'react';
12
12
  import { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';
13
13
  import { OrganisationService } from '../../services/OrganisationService';
14
14
 
@@ -32,28 +32,32 @@ export function OrganisationServiceProvider({
32
32
  user,
33
33
  session
34
34
  }: OrganisationServiceProviderProps) {
35
- // Create service instance with useMemo to prevent recreation on every render
36
- const organisationService = useMemo(
37
- () => new OrganisationService(supabaseClient, user, session),
38
- [supabaseClient, user, session]
39
- );
35
+ // Create service instance once with useRef to avoid recreation on auth state changes
36
+ const organisationServiceRef = useRef<OrganisationService | null>(null);
37
+
38
+ if (!organisationServiceRef.current) {
39
+ organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);
40
+ }
41
+
42
+ const organisationService = organisationServiceRef.current;
40
43
 
41
- // Update service dependencies when they change
44
+ // Update service dependencies when they change without recreation
42
45
  useEffect(() => {
43
46
  organisationService.updateDependencies(user, session);
44
- }, [organisationService, user, session]);
45
-
46
- // Initialize service on mount
47
- useEffect(() => {
47
+
48
+ // Re-initialize service when user/session changes
49
+ let isMounted = true;
50
+
48
51
  organisationService.initialize().catch(error => {
49
- console.error('[OrganisationServiceProvider] Failed to initialize organisation service:', error);
52
+ if (isMounted) {
53
+ console.error('[OrganisationServiceProvider] Failed to initialize organisation service:', error);
54
+ }
50
55
  });
51
56
 
52
- // Cleanup on unmount
53
57
  return () => {
54
- organisationService.cleanup();
58
+ isMounted = false;
55
59
  };
56
- }, [organisationService]);
60
+ }, [organisationService, user, session]);
57
61
 
58
62
  const contextValue = useMemo(() => ({
59
63
  organisationService
@@ -4,76 +4,61 @@
4
4
  * @module Providers/Services
5
5
  * @since 0.1.0
6
6
  *
7
- * Unified authentication provider using service architecture.
8
- * Combines all services in a single provider for backward compatibility.
7
+ * Unified authentication provider for authentication, organisations, events, and inactivity tracking.
8
+ * Note: RBAC functionality is available via useRBAC() hook from '@jmruthers/pace-core/rbac'
9
9
  */
10
10
 
11
11
  import React, { createContext, useContext, useMemo } from 'react';
12
- import { type SupabaseClient } from '@supabase/supabase-js';
12
+ import { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';
13
13
  import { AuthServiceProvider } from './AuthServiceProvider';
14
- import { RBACServiceProvider } from './RBACServiceProvider';
15
14
  import { OrganisationServiceProvider } from './OrganisationServiceProvider';
16
15
  import { EventServiceProvider } from './EventServiceProvider';
17
16
  import { InactivityServiceProvider } from './InactivityServiceProvider';
18
17
  import { useAuthService } from '../../hooks/services/useAuthService';
19
- import { useRBACService } from '../../hooks/services/useRBACService';
20
18
  import { useOrganisationService } from '../../hooks/services/useOrganisationService';
21
19
  import { useEventService } from '../../hooks/services/useEventService';
22
20
  import { useInactivityService } from '../../hooks/services/useInactivityService';
21
+ import type { Organisation, OrganisationMembership } from '../../types/organisation';
22
+ import type { Event } from '../../types/unified';
23
+ import type { AuthError } from '@supabase/supabase-js';
23
24
 
24
- // Re-export UserEventAccess type from IRBACService
25
- export type { UserEventAccess } from '../../services/interfaces/IRBACService';
25
+ // Re-export UserEventAccess type
26
+ export interface UserEventAccess {
27
+ event_id: string;
28
+ event_name: string;
29
+ event_description?: string | null;
30
+ start_date: string;
31
+ end_date: string;
32
+ event_status: string;
33
+ app_id: string;
34
+ access_level: string;
35
+ granted_at: string;
36
+ organisation_id: string;
37
+ }
26
38
 
27
- // Combined context type - now service-aware and secure
39
+ // Combined context type - focuses on auth, organisations, events, and inactivity
28
40
  export interface UnifiedAuthContextType {
29
41
  // Auth state
30
- user: any | null;
31
- session: any | null;
42
+ user: User | null;
43
+ session: Session | null;
32
44
  isAuthenticated: boolean;
33
45
  authLoading: boolean;
34
- authError: any | null;
35
- error: any | null; // Alias for authError for backward compatibility
46
+ authError: AuthError | null;
47
+ error: AuthError | null; // Alias for authError for backward compatibility
36
48
  supabase: SupabaseClient | null;
37
49
 
38
50
  // Auth methods
39
- signIn: (email: string, password?: string) => Promise<{ error: any | null }>;
40
- signUp: (email: string, password: string) => Promise<{ error: any | null }>;
41
- signOut: () => Promise<{ error: any | null }>;
42
- resetPassword: (email: string) => Promise<{ error: any | null }>;
43
- updatePassword: (password: string) => Promise<{ error: any | null }>;
44
- refreshSession: () => Promise<{ error: any | null }>;
45
-
46
- // RBAC state
47
- permissions: Record<string, boolean>;
48
- roles: string[];
49
- accessLevel: any;
50
- rbacLoading: boolean;
51
- rbacError: Error | null;
52
- selectedEventId: string | null;
53
- appConfig: any | null;
54
- userEventAccess: any[];
55
- eventAccessLoading: boolean;
56
- selectedOrganisationId: string | null;
57
-
58
- // RBAC methods
59
- hasPermission: (permission: string, orgId?: string) => boolean;
60
- hasAnyPermission: (permissions: string[], orgId?: string) => boolean;
61
- hasAllPermissions: (permissions: string[], orgId?: string) => boolean;
62
- hasRole: (role: string) => boolean;
63
- hasAccessLevel: (level: any) => boolean;
64
- canAccess: (resource: string, action: string, orgId?: string) => boolean;
65
- validatePermission: (permission: string, orgId?: string) => Promise<boolean>;
66
- validateAccess: (resource: string, action: string, orgId?: string) => Promise<boolean>;
67
- refreshPermissions: (eventId?: string, orgId?: string) => Promise<void>;
68
- setSelectedEventId: (eventId: string | null) => void;
69
- loadUserEventAccess: (orgId?: string) => Promise<void>;
70
- getUserEventAccess: (eventId: string) => any | undefined;
71
- requireOrganisationContext: () => string;
51
+ signIn: (email: string, password?: string) => Promise<{ error: AuthError | null }>;
52
+ signUp: (email: string, password: string) => Promise<{ error: AuthError | null }>;
53
+ signOut: () => Promise<{ error: AuthError | null }>;
54
+ resetPassword: (email: string) => Promise<{ error: AuthError | null }>;
55
+ updatePassword: (password: string) => Promise<{ error: AuthError | null }>;
56
+ refreshSession: () => Promise<{ error: AuthError | null }>;
72
57
 
73
58
  // Organisation state
74
- selectedOrganisation: any | null;
75
- organisations: any[];
76
- userMemberships: any[];
59
+ selectedOrganisation: Organisation | null;
60
+ organisations: Organisation[];
61
+ userMemberships: OrganisationMembership[];
77
62
  organisationLoading: boolean;
78
63
  organisationError: Error | null;
79
64
  hasValidOrganisationContext: boolean;
@@ -84,18 +69,18 @@ export interface UnifiedAuthContextType {
84
69
  getUserRole: (orgId?: string) => string;
85
70
  validateOrganisationAccess: (orgId: string) => boolean;
86
71
  refreshOrganisations: () => Promise<void>;
87
- ensureOrganisationContext: () => any;
72
+ ensureOrganisationContext: () => Organisation;
88
73
  isOrganisationSecure: () => boolean;
89
- getPrimaryOrganisation: () => any | null;
74
+ getPrimaryOrganisation: () => Organisation | null;
90
75
 
91
76
  // Event state
92
- events: any[];
93
- selectedEvent: any | null;
77
+ events: Event[];
78
+ selectedEvent: Event | null;
94
79
  eventLoading: boolean;
95
80
  eventError: Error | null;
96
81
 
97
82
  // Event methods
98
- setSelectedEvent: (event: any | null) => void;
83
+ setSelectedEvent: (event: Event | null) => void;
99
84
  refreshEvents: () => Promise<void>;
100
85
 
101
86
  // Inactivity state
@@ -116,6 +101,7 @@ export interface UnifiedAuthContextType {
116
101
 
117
102
  // Additional unified properties
118
103
  appName: string;
104
+ appConfig: { requires_event: boolean } | null;
119
105
  isLoading: boolean;
120
106
  hasErrors: boolean;
121
107
  }
@@ -137,7 +123,9 @@ export interface UnifiedAuthProviderProps {
137
123
  persistState?: boolean;
138
124
  enablePersistence?: boolean;
139
125
  requireOrganisationContext?: boolean;
140
- enableRBAC?: boolean;
126
+
127
+ // App configuration
128
+ appConfig?: { requires_event: boolean } | null;
141
129
 
142
130
  // Inactivity auto-logout configuration - MANDATORY for security
143
131
  idleTimeoutMs: number; // REQUIRED: Inactivity timeout in milliseconds
@@ -155,21 +143,60 @@ export interface UnifiedAuthProviderProps {
155
143
  function UnifiedAuthContextProvider({
156
144
  children,
157
145
  appName,
146
+ appConfig = { requires_event: true }, // Default to requiring events
158
147
  ...props
159
148
  }: UnifiedAuthProviderProps) {
160
149
  const authService = useAuthService();
161
- const rbacService = useRBACService();
162
150
  const organisationService = useOrganisationService();
163
- const eventService = useEventService();
164
151
  const inactivityService = useInactivityService();
152
+
153
+ // Try to get event service, but provide fallback if not available
154
+ let eventService;
155
+ try {
156
+ eventService = useEventService();
157
+ } catch (error) {
158
+ // EventService not available - provide fallback implementation
159
+ eventService = {
160
+ getEvents: () => [],
161
+ getSelectedEvent: () => null,
162
+ isLoading: () => false,
163
+ getError: () => null,
164
+ setSelectedEvent: () => {},
165
+ refreshEvents: async () => {}
166
+ };
167
+ }
165
168
 
169
+ // Get current auth state - these will trigger re-renders when services change
170
+ const currentUser = authService.getUser();
171
+ const currentSession = authService.getSession();
172
+ const isAuth = !!(currentUser && currentSession);
173
+
174
+ // Get loading states - these will trigger re-renders when services change
175
+ const authLoading = authService.isLoading();
176
+ const orgLoading = organisationService.isLoading();
177
+ const eventLoading = eventService.isLoading();
178
+ const totalLoading = authLoading || orgLoading || eventLoading;
179
+
180
+ // Log auth state for debugging with detailed loading states
181
+ console.log('[UnifiedAuthContext] Auth state:', {
182
+ isAuthenticated: isAuth,
183
+ user: currentUser?.email,
184
+ session: currentSession ? 'exists' : 'null',
185
+ totalLoading,
186
+ authLoading,
187
+ orgLoading,
188
+ eventLoading,
189
+ orgContextReady: organisationService.isContextReady()
190
+ });
191
+
166
192
  // Memoized combined context value
167
- const contextValue = useMemo<UnifiedAuthContextType>(() => ({
193
+ const contextValue = useMemo<UnifiedAuthContextType>(() => {
194
+ return {
168
195
  // Auth state
169
- user: authService.getUser(),
170
- session: authService.getSession(),
171
- isAuthenticated: authService.isAuthenticated(),
172
- authLoading: authService.isLoading(),
196
+ user: currentUser,
197
+ session: currentSession,
198
+ isAuthenticated: isAuth,
199
+ authLoading: authLoading,
173
200
  authError: authService.getError(),
174
201
  error: authService.getError(), // Alias for backward compatibility
175
202
  supabase: authService.getSupabaseClient(),
@@ -182,38 +209,11 @@ function UnifiedAuthContextProvider({
182
209
  updatePassword: authService.updatePassword.bind(authService),
183
210
  refreshSession: authService.refreshSession.bind(authService),
184
211
 
185
- // RBAC state
186
- permissions: rbacService.getPermissions(),
187
- roles: rbacService.getRoles(),
188
- accessLevel: rbacService.getAccessLevel(),
189
- rbacLoading: rbacService.isLoading(),
190
- rbacError: rbacService.getError(),
191
- selectedEventId: rbacService.getSelectedEventId(),
192
- appConfig: rbacService.getAppConfig(),
193
- userEventAccess: rbacService.getUserEventAccess(),
194
- eventAccessLoading: rbacService.isEventAccessLoading(),
195
- selectedOrganisationId: rbacService.getSelectedOrganisationId(),
196
-
197
- // RBAC methods
198
- hasPermission: rbacService.hasPermission.bind(rbacService),
199
- hasAnyPermission: rbacService.hasAnyPermission.bind(rbacService),
200
- hasAllPermissions: rbacService.hasAllPermissions.bind(rbacService),
201
- hasRole: rbacService.hasRole.bind(rbacService),
202
- hasAccessLevel: rbacService.hasAccessLevel.bind(rbacService),
203
- canAccess: rbacService.canAccess.bind(rbacService),
204
- validatePermission: rbacService.validatePermission.bind(rbacService),
205
- validateAccess: rbacService.validateAccess.bind(rbacService),
206
- refreshPermissions: rbacService.refreshPermissions.bind(rbacService),
207
- setSelectedEventId: rbacService.setSelectedEventId.bind(rbacService),
208
- loadUserEventAccess: rbacService.loadUserEventAccess.bind(rbacService),
209
- getUserEventAccess: rbacService.getUserEventAccess.bind(rbacService),
210
- requireOrganisationContext: rbacService.requireOrganisationContext.bind(rbacService),
211
-
212
212
  // Organisation state
213
213
  selectedOrganisation: organisationService.getSelectedOrganisation(),
214
214
  organisations: organisationService.getOrganisations(),
215
215
  userMemberships: organisationService.getUserMemberships(),
216
- organisationLoading: organisationService.isLoading(),
216
+ organisationLoading: orgLoading,
217
217
  organisationError: organisationService.getError(),
218
218
  hasValidOrganisationContext: organisationService.hasValidOrganisationContext(),
219
219
  isContextReady: organisationService.isContextReady(),
@@ -230,7 +230,7 @@ function UnifiedAuthContextProvider({
230
230
  // Event state
231
231
  events: eventService.getEvents(),
232
232
  selectedEvent: eventService.getSelectedEvent(),
233
- eventLoading: eventService.isLoading(),
233
+ eventLoading: eventLoading,
234
234
  eventError: eventService.getError(),
235
235
 
236
236
  // Event methods
@@ -255,9 +255,11 @@ function UnifiedAuthContextProvider({
255
255
 
256
256
  // Additional unified properties
257
257
  appName,
258
- isLoading: authService.isLoading() || rbacService.isLoading() || organisationService.isLoading() || eventService.isLoading(),
259
- hasErrors: !!(authService.getError() || rbacService.getError() || organisationService.getError() || eventService.getError()),
260
- }), [authService, rbacService, organisationService, eventService, inactivityService, appName]);
258
+ appConfig: appConfig,
259
+ isLoading: totalLoading,
260
+ hasErrors: !!(authService.getError() || organisationService.getError() || eventService.getError()),
261
+ };
262
+ }, [authService, organisationService, eventService, inactivityService, appName, appConfig, currentUser, currentSession, isAuth, authLoading, orgLoading, eventLoading, totalLoading]);
261
263
 
262
264
  return (
263
265
  <UnifiedAuthContext.Provider value={contextValue}>
@@ -266,15 +268,53 @@ function UnifiedAuthContextProvider({
266
268
  );
267
269
  }
268
270
 
271
+ // Wrapper for EventServiceProvider that reads selectedOrganisation from OrganisationService
272
+ function EventServiceProviderWrapper({
273
+ children,
274
+ supabaseClient,
275
+ user,
276
+ session,
277
+ appName
278
+ }: {
279
+ children: React.ReactNode;
280
+ supabaseClient: SupabaseClient;
281
+ user: User | null;
282
+ session: Session | null;
283
+ appName: string;
284
+ }) {
285
+ const organisationService = useOrganisationService();
286
+ const selectedOrganisation = organisationService.getSelectedOrganisation();
287
+
288
+ // Only render EventServiceProvider if user and session are available
289
+ if (!user || !session) {
290
+ return <>{children}</>;
291
+ }
292
+
293
+ return (
294
+ <EventServiceProvider
295
+ supabaseClient={supabaseClient}
296
+ user={user}
297
+ session={session}
298
+ appName={appName}
299
+ selectedOrganisation={selectedOrganisation}
300
+ setSelectedEventId={() => {
301
+ // Event selection is now handled at the application level
302
+ }}
303
+ >
304
+ {children}
305
+ </EventServiceProvider>
306
+ );
307
+ }
308
+
269
309
  // Internal component that provides user/session to child providers
270
310
  function ServiceAwareProviders({
271
311
  children,
272
312
  supabaseClient,
273
313
  appName,
314
+ appConfig,
274
315
  persistState,
275
316
  enablePersistence,
276
317
  requireOrganisationContext,
277
- enableRBAC,
278
318
  idleTimeoutMs,
279
319
  warnBeforeMs,
280
320
  onIdleLogout,
@@ -284,54 +324,43 @@ function ServiceAwareProviders({
284
324
  const authService = useAuthService();
285
325
 
286
326
  return (
287
- <RBACServiceProvider
327
+ <OrganisationServiceProvider
288
328
  supabaseClient={supabaseClient}
289
329
  user={authService.getUser()}
290
330
  session={authService.getSession()}
291
- appName={appName}
292
331
  >
293
- <OrganisationServiceProvider
332
+ <EventServiceProviderWrapper
294
333
  supabaseClient={supabaseClient}
295
334
  user={authService.getUser()}
296
335
  session={authService.getSession()}
336
+ appName={appName}
297
337
  >
298
- <EventServiceProvider
338
+ <InactivityServiceProvider
299
339
  supabaseClient={supabaseClient}
300
340
  user={authService.getUser()}
301
341
  session={authService.getSession()}
302
- appName={appName}
303
- selectedOrganisation={null} // Will be updated by OrganisationService
304
- setSelectedEventId={(eventId: string | null) => {
305
- // This will be handled by the RBACService
306
- }}
342
+ idleTimeoutMs={idleTimeoutMs}
343
+ warnBeforeMs={warnBeforeMs}
344
+ onIdleLogout={onIdleLogout}
307
345
  >
308
- <InactivityServiceProvider
346
+ <UnifiedAuthContextProvider
347
+ appName={appName}
348
+ appConfig={appConfig}
309
349
  supabaseClient={supabaseClient}
310
- user={authService.getUser()}
311
- session={authService.getSession()}
350
+ persistState={persistState}
351
+ enablePersistence={enablePersistence}
352
+ requireOrganisationContext={requireOrganisationContext}
312
353
  idleTimeoutMs={idleTimeoutMs}
313
354
  warnBeforeMs={warnBeforeMs}
314
355
  onIdleLogout={onIdleLogout}
356
+ renderInactivityWarning={renderInactivityWarning}
357
+ dangerouslyDisableInactivity={dangerouslyDisableInactivity}
315
358
  >
316
- <UnifiedAuthContextProvider
317
- appName={appName}
318
- supabaseClient={supabaseClient}
319
- persistState={persistState}
320
- enablePersistence={enablePersistence}
321
- requireOrganisationContext={requireOrganisationContext}
322
- enableRBAC={enableRBAC}
323
- idleTimeoutMs={idleTimeoutMs}
324
- warnBeforeMs={warnBeforeMs}
325
- onIdleLogout={onIdleLogout}
326
- renderInactivityWarning={renderInactivityWarning}
327
- dangerouslyDisableInactivity={dangerouslyDisableInactivity}
328
- >
329
- {children}
330
- </UnifiedAuthContextProvider>
331
- </InactivityServiceProvider>
332
- </EventServiceProvider>
333
- </OrganisationServiceProvider>
334
- </RBACServiceProvider>
359
+ {children}
360
+ </UnifiedAuthContextProvider>
361
+ </InactivityServiceProvider>
362
+ </EventServiceProviderWrapper>
363
+ </OrganisationServiceProvider>
335
364
  );
336
365
  }
337
366
 
@@ -339,10 +368,10 @@ export function UnifiedAuthProvider({
339
368
  children,
340
369
  supabaseClient,
341
370
  appName,
371
+ appConfig = { requires_event: true }, // Default to requiring events
342
372
  persistState = true,
343
373
  enablePersistence,
344
374
  requireOrganisationContext = true,
345
- enableRBAC = false,
346
375
  idleTimeoutMs = 30 * 60 * 1000, // 30 minutes
347
376
  warnBeforeMs = 60 * 1000, // 60 seconds
348
377
  onIdleLogout,
@@ -354,10 +383,10 @@ export function UnifiedAuthProvider({
354
383
  <ServiceAwareProviders
355
384
  supabaseClient={supabaseClient}
356
385
  appName={appName}
386
+ appConfig={appConfig}
357
387
  persistState={persistState}
358
388
  enablePersistence={enablePersistence}
359
389
  requireOrganisationContext={requireOrganisationContext}
360
- enableRBAC={enableRBAC}
361
390
  idleTimeoutMs={idleTimeoutMs}
362
391
  warnBeforeMs={warnBeforeMs}
363
392
  onIdleLogout={onIdleLogout}
@@ -95,7 +95,7 @@ describe('AuthServiceProvider Integration', () => {
95
95
 
96
96
  expect(screen.getByTestId('user-id')).toHaveTextContent('no-user');
97
97
  expect(screen.getByTestId('is-authenticated')).toHaveTextContent('false');
98
- expect(screen.getByTestId('is-loading')).toHaveTextContent('true');
98
+ expect(screen.getByTestId('is-loading')).toHaveTextContent('false'); // Initial state is not loading
99
99
  expect(screen.getByTestId('error')).toHaveTextContent('no-error');
100
100
  });
101
101
 
@@ -62,8 +62,8 @@ function TestComponent() {
62
62
  <div data-testid="is-authenticated">{auth.isAuthenticated.toString()}</div>
63
63
  <div data-testid="is-loading">{auth.isLoading.toString()}</div>
64
64
  <div data-testid="app-name">{auth.appName}</div>
65
- <div data-testid="permissions-count">{Object.keys(auth.permissions).length}</div>
66
- <div data-testid="roles-count">{auth.roles.length}</div>
65
+ <div data-testid="permissions-count">{0}</div>
66
+ <div data-testid="roles-count">{0}</div>
67
67
  <div data-testid="organisations-count">{auth.organisations.length}</div>
68
68
  <div data-testid="events-count">{auth.events.length}</div>
69
69
  </div>
@@ -97,7 +97,7 @@ describe('UnifiedAuthProvider Integration', () => {
97
97
 
98
98
  expect(screen.getByTestId('user-id')).toHaveTextContent('no-user');
99
99
  expect(screen.getByTestId('is-authenticated')).toHaveTextContent('false');
100
- expect(screen.getByTestId('is-loading')).toHaveTextContent('true');
100
+ expect(screen.getByTestId('is-loading')).toHaveTextContent('false');
101
101
  expect(screen.getByTestId('app-name')).toHaveTextContent('TEST_APP');
102
102
  expect(screen.getByTestId('permissions-count')).toHaveTextContent('0');
103
103
  expect(screen.getByTestId('roles-count')).toHaveTextContent('0');
@@ -592,7 +592,7 @@ const permissions = await getPermissionMap({
592
592
  userId: 'user-123',
593
593
  scope: { organisationId: 'org-456', appId: 'app-789' }
594
594
  });
595
- // Returns: { [pageId]: Operation[] }
595
+ // Returns: { [permission]: boolean }
596
596
  ```
597
597
 
598
598
  ### React Hooks
@@ -180,17 +180,17 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
180
180
 
181
181
  render(
182
182
  <PermissionGuard
183
- scope={{ organisationId: 'org-123' as UUID }}
184
- permission="read:users" as Permission
185
- children={<div>Protected Content</div>}
183
+ {...defaultProps}
184
+ userId={'' as any}
185
+ fallback={<div>No Access</div>}
186
186
  />
187
187
  );
188
-
189
- expect(screen.getByText('Permission check failed: User context not available')).toBeInTheDocument();
190
- expect(screen.getByText('Debug info')).toBeInTheDocument();
188
+
189
+ expect(screen.getByText('No Access')).toBeInTheDocument();
190
+ expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
191
191
  });
192
192
 
193
- it('infers userId from window.__PACE_USER__ when not provided', () => {
193
+ it('does not infer userId from window.__PACE_USER__ when not provided', () => {
194
194
  mockUseCan.mockReturnValue({
195
195
  can: true,
196
196
  isLoading: false,
@@ -202,14 +202,13 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
202
202
 
203
203
  render(
204
204
  <PermissionGuard
205
- scope={{ organisationId: 'org-123' as UUID }}
206
- permission="read:users" as Permission
207
- children={<div>Protected Content</div>}
205
+ {...defaultProps}
206
+ userId={'' as any}
207
+ fallback={<div>No Access</div>}
208
208
  />
209
209
  );
210
-
211
- expect(screen.getByText('Protected Content')).toBeInTheDocument();
212
- expect(mockUseCan).toHaveBeenCalledWith('inferred-user-123', expect.any(Object), expect.any(String), undefined);
210
+
211
+ expect(mockUseCan).toHaveBeenCalledWith('', expect.any(Object), expect.any(String), undefined);
213
212
  });
214
213
  });
215
214
 
@@ -437,28 +436,27 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
437
436
  });
438
437
 
439
438
  describe('User Context Inference', () => {
440
- it('shows error when no userId provided and cannot infer from context', () => {
439
+ it('renders fallback when user context is missing', () => {
441
440
  mockUseAccessLevel.mockReturnValue({
442
441
  accessLevel: 'viewer',
443
442
  isLoading: false,
444
443
  error: null,
445
444
  });
446
445
 
447
- // Mock window.__PACE_USER__ as undefined
448
- (window as any).__PACE_USER__ = undefined;
449
-
450
446
  render(
451
447
  <AccessLevelGuard
452
- scope={{ organisationId: 'org-123' as UUID }}
448
+ {...defaultProps}
449
+ userId={'' as any}
453
450
  minLevel="admin"
454
- children={<div>Admin Content</div>}
451
+ fallback={<div>No Access</div>}
455
452
  />
456
453
  );
457
-
458
- expect(screen.getByText('Access level check failed: User context not available')).toBeInTheDocument();
454
+
455
+ expect(screen.getByText('No Access')).toBeInTheDocument();
456
+ expect(screen.queryByText('Admin Content')).not.toBeInTheDocument();
459
457
  });
460
458
 
461
- it('infers userId from window.__PACE_USER__ when not provided', () => {
459
+ it('does not infer userId from window globals', () => {
462
460
  mockUseAccessLevel.mockReturnValue({
463
461
  accessLevel: 'admin',
464
462
  isLoading: false,
@@ -470,14 +468,14 @@ describe('RBAC Adapters - Comprehensive Tests', () => {
470
468
 
471
469
  render(
472
470
  <AccessLevelGuard
473
- scope={{ organisationId: 'org-123' as UUID }}
471
+ {...defaultProps}
472
+ userId={'' as any}
474
473
  minLevel="admin"
475
- children={<div>Admin Content</div>}
474
+ fallback={<div>No Access</div>}
476
475
  />
477
476
  );
478
-
479
- expect(screen.getByText('Admin Content')).toBeInTheDocument();
480
- expect(mockUseAccessLevel).toHaveBeenCalledWith('inferred-user-123', expect.any(Object));
477
+
478
+ expect(mockUseAccessLevel).toHaveBeenCalledWith('', expect.any(Object));
481
479
  });
482
480
  });
483
481
  });