@jmruthers/pace-core 0.5.76 → 0.5.78

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 (447) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{RBACService-C4udt_Zp.d.ts → AuthService-Df3IozMG.d.ts} +10 -118
  3. package/dist/{DataTable-ntgmhO2W.d.ts → DataTable-BE0OXZKQ.d.ts} +9 -2
  4. package/dist/{DataTable-4GAVPIEG.js → DataTable-ETGVF4Y5.js} +50 -13
  5. package/dist/{PublicLoadingSpinner-BiNER8F5.d.ts → PublicLoadingSpinner-CnUaz0vG.d.ts} +5 -2
  6. package/dist/{UnifiedAuthProvider-Bj6YCf7c.d.ts → UnifiedAuthProvider-B391Aqum.d.ts} +42 -45
  7. package/dist/{UnifiedAuthProvider-3NKDOSOK.js → UnifiedAuthProvider-P5SOJAQ6.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-K34IM5CT.js → chunk-2OGV6IRV.js} +196 -626
  11. package/dist/chunk-2OGV6IRV.js.map +1 -0
  12. package/dist/{chunk-NTNILOBC.js → chunk-5BO3MI5Y.js} +4 -4
  13. package/dist/{chunk-XLZ7U46Z.js → chunk-CVMVPYAL.js} +9 -60
  14. package/dist/chunk-CVMVPYAL.js.map +1 -0
  15. package/dist/{chunk-URUTVZ7N.js → chunk-FL4ZCQLD.js} +2 -2
  16. package/dist/{chunk-LW7MMEAQ.js → chunk-FT2M4R4F.js} +2 -2
  17. package/dist/{chunk-5BSLGBYI.js → chunk-JCQZ6LA7.js} +2 -8
  18. package/dist/{chunk-5BSLGBYI.js.map → chunk-JCQZ6LA7.js.map} +1 -1
  19. package/dist/{chunk-KHJS6VIA.js → chunk-LRQ6RBJC.js} +157 -112
  20. package/dist/chunk-LRQ6RBJC.js.map +1 -0
  21. package/dist/{chunk-WN6XJWOS.js → chunk-MNJXXD6C.js} +274 -743
  22. package/dist/chunk-MNJXXD6C.js.map +1 -0
  23. package/dist/{chunk-KK73ZB4E.js → chunk-PTR5PMPE.js} +153 -132
  24. package/dist/chunk-PTR5PMPE.js.map +1 -0
  25. package/dist/{chunk-B2WTCLCV.js → chunk-Q7APDV6H.js} +18 -8
  26. package/dist/chunk-Q7APDV6H.js.map +1 -0
  27. package/dist/{chunk-A4FUBC7B.js → chunk-QGVSOUJ2.js} +2 -4
  28. package/dist/{chunk-A4FUBC7B.js.map → chunk-QGVSOUJ2.js.map} +1 -1
  29. package/dist/{chunk-FGMFQSHX.js → chunk-S63MFSY6.js} +500 -551
  30. package/dist/chunk-S63MFSY6.js.map +1 -0
  31. package/dist/{chunk-AFGTSUAD.js → chunk-VSOKOFRF.js} +4 -4
  32. package/dist/chunk-WUXCWRL6.js +20 -0
  33. package/dist/chunk-WUXCWRL6.js.map +1 -0
  34. package/dist/{chunk-Y6TXWPJO.js → chunk-YVVGHRGI.js} +105 -31
  35. package/dist/chunk-YVVGHRGI.js.map +1 -0
  36. package/dist/{chunk-M5IWZRBT.js → chunk-ZMNXIJP4.js} +2187 -981
  37. package/dist/chunk-ZMNXIJP4.js.map +1 -0
  38. package/dist/components.d.ts +6 -6
  39. package/dist/components.js +14 -18
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database-C3Szpi5J.d.ts → database-BXAfr2Y_.d.ts} +18 -0
  42. package/dist/hooks.d.ts +5 -5
  43. package/dist/hooks.js +8 -9
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +19 -27
  46. package/dist/index.js +21 -29
  47. package/dist/index.js.map +1 -1
  48. package/dist/{organisation-BtshODVF.d.ts → organisation-D6qRDtbF.d.ts} +1 -1
  49. package/dist/providers.d.ts +7 -21
  50. package/dist/providers.js +3 -10
  51. package/dist/rbac/index.d.ts +71 -221
  52. package/dist/rbac/index.js +15 -16
  53. package/dist/{types-CGX9Vyf5.d.ts → types-BDg1mAGG.d.ts} +36 -6
  54. package/dist/types.d.ts +3 -3
  55. package/dist/types.js +61 -18
  56. package/dist/types.js.map +1 -1
  57. package/dist/{unified-CM7T0aTK.d.ts → unified-DQ4VcT7H.d.ts} +1 -1
  58. package/dist/{usePublicRouteParams-B-CumWRc.d.ts → usePublicRouteParams-BlgwXweB.d.ts} +3 -3
  59. package/dist/utils.d.ts +2 -2
  60. package/dist/utils.js +52 -9
  61. package/dist/utils.js.map +1 -1
  62. package/docs/CONTENT_AUDIT_REPORT.md +253 -0
  63. package/docs/DOCUMENTATION_AUDIT.md +172 -0
  64. package/docs/README.md +142 -147
  65. package/docs/STYLE_GUIDE.md +37 -0
  66. package/docs/api/classes/ColumnFactory.md +17 -17
  67. package/docs/api/classes/ErrorBoundary.md +1 -1
  68. package/docs/api/classes/InvalidScopeError.md +4 -4
  69. package/docs/api/classes/MissingUserContextError.md +4 -4
  70. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  71. package/docs/api/classes/PermissionDeniedError.md +5 -5
  72. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  73. package/docs/api/classes/RBACAuditManager.md +8 -8
  74. package/docs/api/classes/RBACCache.md +35 -5
  75. package/docs/api/classes/RBACEngine.md +49 -20
  76. package/docs/api/classes/RBACError.md +4 -4
  77. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  78. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  79. package/docs/api/classes/StorageUtils.md +1 -1
  80. package/docs/api/enums/FileCategory.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +4 -4
  82. package/docs/api/interfaces/ButtonProps.md +1 -1
  83. package/docs/api/interfaces/CardProps.md +1 -1
  84. package/docs/api/interfaces/ColorPalette.md +1 -1
  85. package/docs/api/interfaces/ColorShade.md +1 -1
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +11 -0
  88. package/docs/api/interfaces/DataTableAction.md +65 -29
  89. package/docs/api/interfaces/DataTableColumn.md +36 -23
  90. package/docs/api/interfaces/DataTableProps.md +80 -38
  91. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  92. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  93. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  94. package/docs/api/interfaces/EventLogoProps.md +1 -1
  95. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  96. package/docs/api/interfaces/FileMetadata.md +1 -1
  97. package/docs/api/interfaces/FileReference.md +1 -1
  98. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  99. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  100. package/docs/api/interfaces/FileUploadProps.md +1 -1
  101. package/docs/api/interfaces/FooterProps.md +1 -1
  102. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  103. package/docs/api/interfaces/InputProps.md +1 -1
  104. package/docs/api/interfaces/LabelProps.md +1 -1
  105. package/docs/api/interfaces/LoginFormProps.md +1 -1
  106. package/docs/api/interfaces/NavigationAccessRecord.md +11 -11
  107. package/docs/api/interfaces/NavigationContextType.md +9 -9
  108. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  109. package/docs/api/interfaces/NavigationItem.md +1 -1
  110. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  112. package/docs/api/interfaces/Organisation.md +1 -1
  113. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  114. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  115. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  116. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  117. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  118. package/docs/api/interfaces/PaceLoginPageProps.md +16 -3
  119. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  120. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  121. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  122. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  123. package/docs/api/interfaces/PaletteData.md +1 -1
  124. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  125. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  126. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  127. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  128. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  129. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  130. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  131. package/docs/api/interfaces/RBACConfig.md +1 -1
  132. package/docs/api/interfaces/RBACLogger.md +1 -1
  133. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  134. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  135. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  136. package/docs/api/interfaces/RouteConfig.md +2 -2
  137. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  138. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  139. package/docs/api/interfaces/StorageConfig.md +1 -1
  140. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  141. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  142. package/docs/api/interfaces/StorageListOptions.md +1 -1
  143. package/docs/api/interfaces/StorageListResult.md +1 -1
  144. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  145. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  146. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  147. package/docs/api/interfaces/StyleImport.md +1 -1
  148. package/docs/api/interfaces/SwitchProps.md +1 -1
  149. package/docs/api/interfaces/ToastActionElement.md +1 -1
  150. package/docs/api/interfaces/ToastProps.md +1 -1
  151. package/docs/api/interfaces/UnifiedAuthContextType.md +94 -521
  152. package/docs/api/interfaces/UnifiedAuthProviderProps.md +16 -16
  153. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  154. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  155. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  156. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  157. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  158. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  159. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  160. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  161. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  162. package/docs/api/interfaces/UserEventAccess.md +11 -11
  163. package/docs/api/interfaces/UserMenuProps.md +1 -1
  164. package/docs/api/interfaces/UserProfile.md +1 -1
  165. package/docs/api/modules.md +251 -269
  166. package/docs/api-reference/components.md +193 -0
  167. package/docs/api-reference/hooks.md +265 -0
  168. package/docs/api-reference/providers.md +6 -0
  169. package/docs/api-reference/types.md +6 -0
  170. package/docs/api-reference/utilities.md +207 -0
  171. package/docs/architecture/README.md +6 -0
  172. package/docs/{database-schema-requirements.md → architecture/database-schema-requirements.md} +6 -0
  173. package/docs/architecture/rbac-security-architecture.md +258 -0
  174. package/docs/architecture/services.md +9 -1
  175. package/docs/best-practices/README.md +6 -0
  176. package/docs/best-practices/accessibility.md +6 -0
  177. package/docs/{common-patterns.md → best-practices/common-patterns.md} +6 -0
  178. package/docs/best-practices/deployment.md +6 -0
  179. package/docs/best-practices/performance.md +475 -2
  180. package/docs/best-practices/security.md +6 -0
  181. package/docs/best-practices/testing.md +6 -0
  182. package/docs/core-concepts/authentication.md +6 -0
  183. package/docs/core-concepts/events.md +6 -0
  184. package/docs/core-concepts/organisations.md +6 -0
  185. package/docs/core-concepts/permissions.md +6 -0
  186. package/docs/core-concepts/rbac-system.md +8 -0
  187. package/docs/documentation-index.md +121 -182
  188. package/docs/{consuming-app-vite-config.md → getting-started/consuming-app-vite-config.md} +6 -0
  189. package/docs/getting-started/documentation-index.md +40 -0
  190. package/docs/getting-started/examples/README.md +878 -35
  191. package/docs/{faq.md → getting-started/faq.md} +7 -1
  192. package/docs/getting-started/installation-guide.md +6 -0
  193. package/docs/{quick-reference.md → getting-started/quick-reference.md} +6 -0
  194. package/docs/implementation-guides/app-layout.md +6 -0
  195. package/docs/implementation-guides/authentication.md +1021 -0
  196. package/docs/implementation-guides/component-styling.md +6 -0
  197. package/docs/implementation-guides/data-tables.md +1264 -2076
  198. package/docs/implementation-guides/dynamic-colors.md +6 -0
  199. package/docs/implementation-guides/event-theming-summary.md +6 -0
  200. package/docs/{file-reference-system.md → implementation-guides/file-reference-system.md} +6 -0
  201. package/docs/implementation-guides/file-upload-storage.md +6 -0
  202. package/docs/implementation-guides/forms.md +6 -0
  203. package/docs/implementation-guides/inactivity-tracking.md +6 -0
  204. package/docs/implementation-guides/navigation.md +6 -0
  205. package/docs/implementation-guides/organisation-security.md +6 -0
  206. package/docs/implementation-guides/permission-enforcement.md +6 -0
  207. package/docs/implementation-guides/public-pages-advanced.md +6 -0
  208. package/docs/implementation-guides/public-pages.md +6 -0
  209. package/docs/migration/MIGRATION_GUIDE.md +827 -351
  210. package/docs/migration/README.md +7 -1
  211. package/docs/migration/organisation-context-timing-fix.md +6 -0
  212. package/docs/migration/rbac-migration.md +44 -1
  213. package/docs/migration/service-architecture.md +6 -0
  214. package/docs/migration/v0.4.15-tailwind-scanning.md +6 -0
  215. package/docs/migration/v0.4.16-css-first-approach.md +6 -0
  216. package/docs/migration/v0.4.17-source-path-fix.md +6 -0
  217. package/docs/rbac/README-rbac-rls-integration.md +6 -0
  218. package/docs/rbac/README.md +6 -0
  219. package/docs/rbac/advanced-patterns.md +6 -0
  220. package/docs/rbac/api-reference.md +7 -1
  221. package/docs/rbac/breaking-changes-v3.md +222 -0
  222. package/docs/rbac/examples/rbac-rls-integration-example.md +6 -0
  223. package/docs/rbac/examples.md +6 -0
  224. package/docs/rbac/getting-started.md +6 -0
  225. package/docs/rbac/migration-guide.md +260 -0
  226. package/docs/rbac/quick-start.md +70 -13
  227. package/docs/rbac/rbac-rls-integration.md +6 -0
  228. package/docs/rbac/super-admin-guide.md +6 -0
  229. package/docs/rbac/troubleshooting.md +6 -0
  230. package/docs/security/README.md +6 -0
  231. package/docs/security/checklist.md +6 -0
  232. package/docs/styles/README.md +7 -1
  233. package/docs/{usage.md → styles/usage.md} +6 -0
  234. package/docs/testing/README.md +6 -0
  235. package/docs/{visual-testing.md → testing/visual-testing.md} +6 -0
  236. package/docs/troubleshooting/README.md +387 -5
  237. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +6 -0
  238. package/docs/troubleshooting/common-issues.md +6 -0
  239. package/docs/troubleshooting/database-view-compatibility.md +6 -0
  240. package/docs/troubleshooting/organisation-context-setup.md +6 -0
  241. package/docs/troubleshooting/react-hooks-issue-analysis.md +6 -0
  242. package/docs/troubleshooting/styling-issues.md +6 -0
  243. package/docs/troubleshooting/tailwind-content-scanning.md +6 -0
  244. package/package.json +1 -1
  245. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -1
  246. package/src/__tests__/helpers/test-providers.tsx +3 -53
  247. package/src/components/DataTable/DataTable.test.tsx +319 -0
  248. package/src/components/DataTable/DataTable.tsx +32 -11
  249. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx.skip} +6 -4
  250. package/src/components/DataTable/__tests__/{DataTable.test.tsx → DataTable.test.tsx.skip} +6 -4
  251. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +31 -9
  252. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +601 -0
  253. package/src/components/DataTable/__tests__/keyboard.test.tsx +615 -0
  254. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +639 -0
  255. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx.skip +330 -0
  256. package/src/components/DataTable/components/AccessDeniedPage.tsx +2 -2
  257. package/src/components/DataTable/components/ActionButtons.tsx +88 -104
  258. package/src/components/DataTable/components/DataTableCore.tsx +309 -337
  259. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +4 -2
  260. package/src/components/DataTable/components/DataTableModals.tsx +22 -1
  261. package/src/components/DataTable/components/EditableRow.tsx +69 -84
  262. package/src/components/DataTable/components/EmptyState.tsx +5 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +65 -36
  264. package/src/components/DataTable/components/PaginationControls.tsx +40 -100
  265. package/src/components/DataTable/components/UnifiedTableBody.tsx +125 -148
  266. package/src/components/DataTable/context/DataTableContext.tsx +1 -1
  267. package/src/components/DataTable/core/ColumnFactory.ts +5 -0
  268. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +12 -10
  269. package/src/components/DataTable/examples/HierarchicalExample.tsx +1 -1
  270. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +1 -0
  271. package/src/components/DataTable/examples/PerformanceExample.tsx +1 -0
  272. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +1 -5
  273. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +167 -0
  274. package/src/components/DataTable/hooks/index.ts +7 -0
  275. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +32 -15
  276. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +102 -0
  277. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +89 -0
  278. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +117 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +71 -27
  280. package/src/components/DataTable/hooks/useDataTableState.ts +39 -11
  281. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +33 -0
  282. package/src/components/DataTable/hooks/useHierarchicalState.ts +15 -1
  283. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +447 -0
  284. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +94 -0
  285. package/src/components/DataTable/hooks/useTableColumns.ts +10 -7
  286. package/src/components/DataTable/hooks/useTableHandlers.ts +174 -0
  287. package/src/components/DataTable/index.ts +12 -3
  288. package/src/components/DataTable/types.ts +129 -9
  289. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +159 -22
  290. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +111 -0
  291. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +15 -29
  292. package/src/components/DataTable/utils/a11yUtils.ts +244 -0
  293. package/src/components/DataTable/utils/debugTools.ts +609 -0
  294. package/src/components/DataTable/utils/exportUtils.ts +114 -16
  295. package/src/components/DataTable/utils/flexibleImport.ts +202 -32
  296. package/src/components/DataTable/utils/hierarchicalUtils.ts +1 -1
  297. package/src/components/DataTable/utils/index.ts +2 -0
  298. package/src/components/DataTable/utils/paginationUtils.ts +350 -0
  299. package/src/components/DataTable/utils/rowUtils.ts +6 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -24
  301. package/src/components/NavigationMenu/NavigationMenu.tsx +19 -8
  302. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +1 -23
  303. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +56 -6
  304. package/src/components/PaceLoginPage/PaceLoginPage.tsx +137 -13
  305. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +1 -1
  306. package/src/components/Select/Select.tsx +1 -0
  307. package/src/components/examples/PermissionExample.tsx +173 -0
  308. package/src/examples/CorrectPublicPageImplementation.tsx +301 -0
  309. package/src/examples/PublicEventPage.tsx +274 -0
  310. package/src/examples/PublicPageApp.tsx +308 -0
  311. package/src/examples/PublicPageUsageExample.tsx +216 -0
  312. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +12 -1
  313. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +129 -17
  314. package/src/hooks/__tests__/useRBAC.unit.test.ts +151 -846
  315. package/src/hooks/useOrganisationPermissions.test.ts +42 -18
  316. package/src/hooks/useOrganisationPermissions.ts +12 -6
  317. package/src/hooks/useOrganisationSecurity.test.ts +138 -85
  318. package/src/hooks/useOrganisationSecurity.ts +41 -10
  319. package/src/index.ts +0 -1
  320. package/src/providers/AuthProvider.simplified.tsx +880 -0
  321. package/src/providers/UnifiedAuthProvider.test.simple.tsx +8 -8
  322. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +29 -19
  323. package/src/providers/index.ts +0 -1
  324. package/src/providers/services/EventServiceProvider.tsx +19 -15
  325. package/src/providers/services/InactivityServiceProvider.tsx +19 -15
  326. package/src/providers/services/OrganisationServiceProvider.tsx +19 -15
  327. package/src/providers/services/UnifiedAuthProvider.tsx +156 -127
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +1 -1
  329. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -3
  330. package/src/rbac/README.md +1 -1
  331. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +25 -27
  332. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +313 -0
  333. package/src/rbac/__tests__/engine.comprehensive.test.ts +114 -348
  334. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +28 -110
  335. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +33 -85
  336. package/src/rbac/__tests__/scenarios.user-role.test.tsx +2 -2
  337. package/src/rbac/adapters.tsx +26 -69
  338. package/src/rbac/api.test.ts +90 -27
  339. package/src/rbac/api.ts +61 -10
  340. package/src/rbac/audit.test.ts +33 -38
  341. package/src/rbac/audit.ts +21 -6
  342. package/src/rbac/cache.ts +33 -1
  343. package/src/rbac/components/NavigationGuard.tsx +11 -11
  344. package/src/rbac/components/NavigationProvider.test.tsx +11 -5
  345. package/src/rbac/components/NavigationProvider.tsx +37 -13
  346. package/src/rbac/components/PagePermissionGuard.tsx +111 -50
  347. package/src/rbac/components/PagePermissionProvider.tsx +5 -5
  348. package/src/rbac/components/PermissionEnforcer.tsx +11 -11
  349. package/src/rbac/components/RoleBasedRouter.tsx +5 -5
  350. package/src/rbac/components/SecureDataProvider.tsx +5 -5
  351. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +8 -8
  352. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +14 -14
  353. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +12 -12
  354. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +6 -6
  355. package/src/rbac/engine.test.simple.ts +19 -13
  356. package/src/rbac/engine.test.ts +1 -0
  357. package/src/rbac/engine.ts +330 -766
  358. package/src/rbac/errors.ts +156 -0
  359. package/src/rbac/hooks/usePermissions.ts +32 -10
  360. package/src/rbac/hooks/useRBAC.test.ts +126 -512
  361. package/src/rbac/hooks/useRBAC.ts +147 -193
  362. package/src/rbac/hooks/useResolvedScope.ts +12 -0
  363. package/src/rbac/index.ts +7 -4
  364. package/src/rbac/security.ts +109 -18
  365. package/src/rbac/types.ts +12 -1
  366. package/src/services/AuthService.ts +2 -15
  367. package/src/services/EventService.ts +43 -46
  368. package/src/services/OrganisationService.ts +51 -31
  369. package/src/services/__tests__/AuthService.test.ts +1 -1
  370. package/src/services/__tests__/EventService.test.ts +1 -1
  371. package/src/services/__tests__/OrganisationService.test.ts +1 -1
  372. package/src/services/base/BaseService.ts +8 -0
  373. package/src/styles/base.css +208 -0
  374. package/src/styles/semantic.css +24 -0
  375. package/src/types/database.generated.ts +7347 -0
  376. package/src/types/database.ts +20 -0
  377. package/src/utils/logger.ts +179 -0
  378. package/src/utils/organisationContext.ts +11 -4
  379. package/src/utils/storage/__tests__/helpers.unit.test.ts +6 -2
  380. package/dist/appNameResolver-UURKN7NF.js +0 -22
  381. package/dist/audit-6TOCAMKO.js.map +0 -1
  382. package/dist/chunk-B2WTCLCV.js.map +0 -1
  383. package/dist/chunk-FGMFQSHX.js.map +0 -1
  384. package/dist/chunk-K34IM5CT.js.map +0 -1
  385. package/dist/chunk-KHJS6VIA.js.map +0 -1
  386. package/dist/chunk-KK73ZB4E.js.map +0 -1
  387. package/dist/chunk-M5IWZRBT.js.map +0 -1
  388. package/dist/chunk-ULBI5JGB.js +0 -109
  389. package/dist/chunk-ULBI5JGB.js.map +0 -1
  390. package/dist/chunk-WN6XJWOS.js.map +0 -1
  391. package/dist/chunk-XLZ7U46Z.js.map +0 -1
  392. package/dist/chunk-Y6TXWPJO.js.map +0 -1
  393. package/docs/DOCUMENTATION_CHECKLIST.md +0 -281
  394. package/docs/TERMINOLOGY.md +0 -231
  395. package/docs/api/interfaces/RBACContextType.md +0 -468
  396. package/docs/api/interfaces/RBACProviderProps.md +0 -107
  397. package/docs/best-practices/performance-expansion.md +0 -473
  398. package/docs/breaking-changes.md +0 -179
  399. package/docs/consuming-app-example.md +0 -290
  400. package/docs/documentation-templates.md +0 -539
  401. package/docs/examples/navigation-menu-auth-fix.md +0 -344
  402. package/docs/getting-started/examples/basic-auth-app.md +0 -520
  403. package/docs/getting-started/examples/full-featured-app.md +0 -616
  404. package/docs/getting-started/quick-start.md +0 -376
  405. package/docs/implementation-guides/datatable-filtering.md +0 -313
  406. package/docs/implementation-guides/datatable-rbac-usage.md +0 -317
  407. package/docs/implementation-guides/hierarchical-datatable.md +0 -850
  408. package/docs/implementation-guides/large-datasets.md +0 -281
  409. package/docs/implementation-guides/performance.md +0 -403
  410. package/docs/migration/quick-migration-guide.md +0 -320
  411. package/docs/migration-guide.md +0 -193
  412. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +0 -226
  413. package/docs/performance/README.md +0 -551
  414. package/docs/style-guide.md +0 -964
  415. package/docs/troubleshooting/authentication-issues.md +0 -334
  416. package/docs/troubleshooting/debugging.md +0 -1117
  417. package/docs/troubleshooting/migration.md +0 -918
  418. package/src/__tests__/hooks/usePermissions.test.ts +0 -261
  419. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +0 -574
  420. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -613
  421. package/src/hooks/services/__tests__/useServiceHooks.test.tsx +0 -137
  422. package/src/hooks/services/usePermissions.ts +0 -70
  423. package/src/hooks/services/useRBACService.ts +0 -30
  424. package/src/hooks/usePermissionCheck.ts +0 -150
  425. package/src/providers/__tests__/ServiceProviders.test.tsx +0 -477
  426. package/src/providers/services/RBACServiceProvider.tsx +0 -79
  427. package/src/rbac/__tests__/integration.authflow.test.tsx +0 -119
  428. package/src/rbac/__tests__/integration.navigation.test.tsx +0 -69
  429. package/src/rbac/__tests__/integration.securedata.test.tsx +0 -92
  430. package/src/rbac/__tests__/integration.smoke.test.tsx +0 -73
  431. package/src/rbac/providers/RBACProvider.tsx +0 -645
  432. package/src/rbac/providers/__tests__/RBACProvider.integration.test.tsx +0 -688
  433. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +0 -1186
  434. package/src/rbac/providers/index.ts +0 -11
  435. package/src/services/RBACService.ts +0 -522
  436. package/src/services/__tests__/RBACService.test.ts +0 -492
  437. package/src/services/interfaces/IRBACService.ts +0 -62
  438. package/src/utils/appNameResolver.test 2.ts +0 -494
  439. /package/dist/{DataTable-4GAVPIEG.js.map → DataTable-ETGVF4Y5.js.map} +0 -0
  440. /package/dist/{UnifiedAuthProvider-3NKDOSOK.js.map → UnifiedAuthProvider-P5SOJAQ6.js.map} +0 -0
  441. /package/dist/{api-DDMUKIUD.js.map → api-KG4A2X7P.js.map} +0 -0
  442. /package/dist/{appNameResolver-UURKN7NF.js.map → audit-65VNHEV2.js.map} +0 -0
  443. /package/dist/{chunk-NTNILOBC.js.map → chunk-5BO3MI5Y.js.map} +0 -0
  444. /package/dist/{chunk-URUTVZ7N.js.map → chunk-FL4ZCQLD.js.map} +0 -0
  445. /package/dist/{chunk-LW7MMEAQ.js.map → chunk-FT2M4R4F.js.map} +0 -0
  446. /package/dist/{chunk-AFGTSUAD.js.map → chunk-VSOKOFRF.js.map} +0 -0
  447. /package/docs/{app.css.example → styles/app.css.example} +0 -0
@@ -137,11 +137,12 @@ const PagePermissionGuardComponent = ({
137
137
 
138
138
 
139
139
 
140
- const { user, selectedOrganisationId, selectedEventId, supabase } = useUnifiedAuth();
140
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
141
141
 
142
142
  const [hasChecked, setHasChecked] = useState(false);
143
143
  const [checkError, setCheckError] = useState<Error | null>(null);
144
144
  const [resolvedScope, setResolvedScope] = useState<Scope | null>(null);
145
+ const scopeResolutionAbortRef = useRef<AbortController | null>(null);
145
146
 
146
147
  // Use ref to avoid infinite re-renders from supabase dependency
147
148
  const supabaseRef = useRef(supabase);
@@ -184,15 +185,37 @@ const PagePermissionGuardComponent = ({
184
185
 
185
186
  // Resolve scope - either use provided scope or resolve from context
186
187
  useEffect(() => {
188
+ const abortController = new AbortController();
189
+ scopeResolutionAbortRef.current?.abort();
190
+ scopeResolutionAbortRef.current = abortController;
191
+ const { signal } = abortController;
192
+
193
+ const safeSetResolvedScope = (value: Scope | null) => {
194
+ if (!signal.aborted) {
195
+ setResolvedScope(value);
196
+ }
197
+ };
198
+
199
+ const safeSetCheckError = (value: Error | null) => {
200
+ if (!signal.aborted) {
201
+ setCheckError(value);
202
+ }
203
+ };
204
+
187
205
  const resolveScope = async () => {
206
+ if (signal.aborted) {
207
+ return;
208
+ }
209
+
188
210
  if (scope) {
189
- setResolvedScope(scope);
211
+ safeSetResolvedScope(scope);
212
+ safeSetCheckError(null);
190
213
  return;
191
214
  }
192
215
 
193
216
  // Get app ID from package.json or environment
194
217
  let appId: string | undefined = undefined;
195
-
218
+
196
219
  // Try to resolve from database
197
220
  if (supabaseRef.current) {
198
221
  const appName = getCurrentAppName();
@@ -204,16 +227,26 @@ const PagePermissionGuardComponent = ({
204
227
  .eq('name', appName)
205
228
  .eq('is_active', true)
206
229
  .single() as { data: { id: string; name: string; is_active: boolean } | null; error: any };
207
-
230
+
231
+ if (signal.aborted) {
232
+ return;
233
+ }
234
+
208
235
  if (error) {
209
236
  console.error('[PagePermissionGuard] Database error resolving app ID:', error);
210
- // Check if app exists but is inactive
237
+ if (signal.aborted) {
238
+ return;
239
+ }
211
240
  const { data: inactiveApp } = await supabaseRef.current
212
241
  .from('rbac_apps')
213
242
  .select('id, name, is_active')
214
243
  .eq('name', appName)
215
244
  .single() as { data: { id: string; name: string; is_active: boolean } | null };
216
-
245
+
246
+ if (signal.aborted) {
247
+ return;
248
+ }
249
+
217
250
  if (inactiveApp) {
218
251
  console.error(`[PagePermissionGuard] App "${appName}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
219
252
  } else {
@@ -225,6 +258,9 @@ const PagePermissionGuardComponent = ({
225
258
  console.error('[PagePermissionGuard] No app data returned for:', appName);
226
259
  }
227
260
  } catch (error) {
261
+ if (signal.aborted) {
262
+ return;
263
+ }
228
264
  console.error('[PagePermissionGuard] Unexpected error resolving app ID:', error);
229
265
  }
230
266
  } else {
@@ -232,114 +268,139 @@ const PagePermissionGuardComponent = ({
232
268
  }
233
269
  }
234
270
 
271
+ if (signal.aborted) {
272
+ return;
273
+ }
274
+
235
275
  // If we have both organisation and event, use them directly
236
- if (selectedOrganisationId && selectedEventId) {
276
+ if (selectedOrganisation && selectedEvent) {
237
277
  if (!appId) {
238
- // In test environments, allow undefined appId
239
278
  if (import.meta.env.MODE === 'test') {
240
279
  console.warn('[PagePermissionGuard] App ID not resolved in test environment, proceeding without it');
241
280
  } else {
242
281
  console.error('[PagePermissionGuard] CRITICAL: App ID not resolved. Check console for details.');
243
- setCheckError(new Error('App ID not resolved. Check console for database errors.'));
244
- setResolvedScope(null); // Ensure we don't proceed with incomplete scope
282
+ safeSetCheckError(new Error('App ID not resolved. Check console for database errors.'));
283
+ safeSetResolvedScope(null);
245
284
  return;
246
285
  }
247
286
  }
248
-
249
- // Validate that appId is a UUID, not an app name (only in production)
287
+
250
288
  if (import.meta.env.MODE === 'production' && appId) {
251
289
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
252
290
  if (!uuidRegex.test(appId)) {
253
291
  console.error('[PagePermissionGuard] CRITICAL: App ID is not a valid UUID:', appId);
254
- setCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
255
- setResolvedScope(null); // Ensure we don't proceed with invalid scope
292
+ safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
293
+ safeSetResolvedScope(null);
256
294
  return;
257
295
  }
258
296
  }
259
- const resolvedScope = {
260
- organisationId: selectedOrganisationId,
261
- eventId: selectedEventId,
297
+ const resolvedContext = {
298
+ organisationId: selectedOrganisation.id,
299
+ eventId: selectedEvent.event_id,
262
300
  appId: appId
263
301
  };
264
- setResolvedScope(resolvedScope);
265
- setCheckError(null); // Clear any previous errors
302
+ safeSetResolvedScope(resolvedContext);
303
+ safeSetCheckError(null);
304
+ return;
305
+ }
306
+
307
+ if (signal.aborted) {
266
308
  return;
267
309
  }
268
310
 
269
311
  // If we only have organisation, use it
270
- if (selectedOrganisationId) {
312
+ if (selectedOrganisation) {
271
313
  if (!appId) {
272
- // In test environments, allow undefined appId
273
314
  if (import.meta.env.MODE === 'test') {
274
315
  console.warn('[PagePermissionGuard] App ID not resolved in test environment, proceeding without it');
275
316
  } else {
276
317
  console.error('[PagePermissionGuard] CRITICAL: App ID not resolved. Check console for details.');
277
- setCheckError(new Error('App ID not resolved. Check console for database errors.'));
278
- setResolvedScope(null); // Ensure we don't proceed with incomplete scope
318
+ safeSetCheckError(new Error('App ID not resolved. Check console for database errors.'));
319
+ safeSetResolvedScope(null);
279
320
  return;
280
321
  }
281
322
  }
282
-
283
- // Validate that appId is a UUID, not an app name (only in production)
323
+
284
324
  if (import.meta.env.MODE === 'production' && appId) {
285
325
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
286
326
  if (!uuidRegex.test(appId)) {
287
327
  console.error('[PagePermissionGuard] CRITICAL: App ID is not a valid UUID:', appId);
288
- setCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
289
- setResolvedScope(null); // Ensure we don't proceed with invalid scope
328
+ safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
329
+ safeSetResolvedScope(null);
290
330
  return;
291
331
  }
292
332
  }
293
- const resolvedScope = {
294
- organisationId: selectedOrganisationId,
295
- eventId: selectedEventId || undefined,
333
+ const resolvedContext = {
334
+ organisationId: selectedOrganisation.id,
335
+ eventId: selectedEvent?.event_id || undefined,
296
336
  appId: appId
297
337
  };
298
- setResolvedScope(resolvedScope);
299
- setCheckError(null); // Clear any previous errors
338
+ safeSetResolvedScope(resolvedContext);
339
+ safeSetCheckError(null);
340
+ return;
341
+ }
342
+
343
+ if (signal.aborted) {
300
344
  return;
301
345
  }
302
346
 
303
347
  // If we only have event, resolve organisation from event
304
- if (selectedEventId && supabaseRef.current) {
348
+ if (selectedEvent && supabaseRef.current) {
305
349
  try {
306
- const eventScope = await createScopeFromEvent(supabaseRef.current, selectedEventId);
350
+ const eventScope = await createScopeFromEvent(supabaseRef.current, selectedEvent.event_id);
351
+
352
+ if (signal.aborted) {
353
+ return;
354
+ }
355
+
307
356
  if (!eventScope) {
308
- setCheckError(new Error('Could not resolve organization from event context'));
309
- setResolvedScope(null); // Ensure we don't proceed with incomplete scope
357
+ safeSetCheckError(new Error('Could not resolve organization from event context'));
358
+ safeSetResolvedScope(null);
310
359
  return;
311
360
  }
312
- // Preserve the resolved app ID
313
- setResolvedScope({
361
+ safeSetResolvedScope({
314
362
  ...eventScope,
315
363
  appId: appId || eventScope.appId
316
364
  });
317
- setCheckError(null); // Clear any previous errors
365
+ safeSetCheckError(null);
318
366
  } catch (error) {
319
- setCheckError(error as Error);
320
- setResolvedScope(null); // Ensure we don't proceed with incomplete scope
367
+ if (signal.aborted) {
368
+ return;
369
+ }
370
+ safeSetCheckError(error as Error);
371
+ safeSetResolvedScope(null);
321
372
  }
322
373
  return;
323
374
  }
324
375
 
325
- // No context available - provide more helpful error message
326
- const errorMessage = !selectedOrganisationId && !selectedEventId
376
+ if (signal.aborted) {
377
+ return;
378
+ }
379
+
380
+ const errorMessage = !selectedOrganisation && !selectedEvent
327
381
  ? 'Either organisation context or event context is required for page permission checking'
328
382
  : 'Insufficient context for permission checking. Please ensure you are properly authenticated and have selected an organisation or event.';
329
-
383
+
330
384
  console.error('[PagePermissionGuard] Context resolution failed:', {
331
- selectedOrganisationId,
332
- selectedEventId,
385
+ selectedOrganisation: selectedOrganisation ? (selectedOrganisation as any).id : null,
386
+ selectedEvent: selectedEvent ? (selectedEvent as any).event_id : null,
333
387
  appId,
334
388
  error: errorMessage
335
389
  });
336
-
337
- setCheckError(new Error(errorMessage));
338
- setResolvedScope(null); // Ensure we don't proceed with incomplete scope
390
+
391
+ safeSetCheckError(new Error(errorMessage));
392
+ safeSetResolvedScope(null);
339
393
  };
340
394
 
341
395
  resolveScope();
342
- }, [scope, selectedOrganisationId, selectedEventId]);
396
+
397
+ return () => {
398
+ abortController.abort();
399
+ if (scopeResolutionAbortRef.current === abortController) {
400
+ scopeResolutionAbortRef.current = null;
401
+ }
402
+ };
403
+ }, [scope, selectedOrganisation, selectedEvent]);
343
404
 
344
405
  // Determine the page ID for permission checking
345
406
  const effectivePageId = useMemo((): string => {
@@ -130,20 +130,20 @@ export function PagePermissionProvider({
130
130
  onStrictModeViolation,
131
131
  maxHistorySize = 1000
132
132
  }: PagePermissionProviderProps) {
133
- const { user, selectedOrganisationId, selectedEventId } = useUnifiedAuth();
133
+ const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
134
134
  const [pageAccessHistory, setPageAccessHistory] = useState<PageAccessRecord[]>([]);
135
135
  const [isEnabled, setIsEnabled] = useState(true);
136
136
 
137
137
  // Get current scope
138
138
  const currentScope = useMemo((): Scope | null => {
139
- if (!selectedOrganisationId) return null;
139
+ if (!selectedOrganisation) return null;
140
140
 
141
141
  return {
142
- organisationId: selectedOrganisationId,
143
- eventId: selectedEventId || undefined,
142
+ organisationId: selectedOrganisation.id,
143
+ eventId: selectedEvent?.event_id || undefined,
144
144
  appId: undefined
145
145
  };
146
- }, [selectedOrganisationId, selectedEventId]);
146
+ }, [selectedOrganisation, selectedEvent]);
147
147
 
148
148
  // Check if user has permission for a page
149
149
  const hasPagePermission = useCallback((
@@ -126,7 +126,7 @@ export function PermissionEnforcer({
126
126
  loading = <DefaultLoading />,
127
127
  requireAll = true
128
128
  }: PermissionEnforcerProps) {
129
- const { user, selectedOrganisationId, selectedEventId, supabase } = useUnifiedAuth();
129
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
130
130
  const [hasChecked, setHasChecked] = useState(false);
131
131
  const [checkError, setCheckError] = useState<Error | null>(null);
132
132
  const [permissionResults, setPermissionResults] = useState<Record<string, boolean>>({});
@@ -141,29 +141,29 @@ export function PermissionEnforcer({
141
141
  }
142
142
 
143
143
  // If we have both organisation and event, use them directly
144
- if (selectedOrganisationId && selectedEventId) {
144
+ if (selectedOrganisation && selectedEvent) {
145
145
  setResolvedScope({
146
- organisationId: selectedOrganisationId,
147
- eventId: selectedEventId,
146
+ organisationId: selectedOrganisation.id,
147
+ eventId: selectedEvent.event_id,
148
148
  appId: undefined
149
149
  });
150
150
  return;
151
151
  }
152
152
 
153
153
  // If we only have organisation, use it
154
- if (selectedOrganisationId) {
154
+ if (selectedOrganisation) {
155
155
  setResolvedScope({
156
- organisationId: selectedOrganisationId,
157
- eventId: selectedEventId || undefined,
156
+ organisationId: selectedOrganisation.id,
157
+ eventId: selectedEvent?.event_id || undefined,
158
158
  appId: undefined
159
159
  });
160
160
  return;
161
161
  }
162
162
 
163
163
  // If we only have event, resolve organisation from event
164
- if (selectedEventId && supabase) {
164
+ if (selectedEvent && supabase) {
165
165
  try {
166
- const eventScope = await createScopeFromEvent(supabase, selectedEventId);
166
+ const eventScope = await createScopeFromEvent(supabase, selectedEvent.event_id);
167
167
  if (!eventScope) {
168
168
  setCheckError(new Error('Could not resolve organization from event context'));
169
169
  return;
@@ -180,14 +180,14 @@ export function PermissionEnforcer({
180
180
  };
181
181
 
182
182
  resolveScope();
183
- }, [scope, selectedOrganisationId, selectedEventId, supabase]);
183
+ }, [scope, selectedOrganisation, selectedEvent, supabase]);
184
184
 
185
185
  // Check permissions using the first permission as a representative
186
186
  // For multiple permissions, we'll check them sequentially
187
187
  const representativePermission = permissions[0];
188
188
  const { can, isLoading, error } = useCan(
189
189
  user?.id || '',
190
- resolvedScope || { eventId: selectedEventId || undefined },
190
+ resolvedScope || { eventId: selectedEvent?.event_id || undefined },
191
191
  representativePermission,
192
192
  undefined,
193
193
  true // Use cache
@@ -186,7 +186,7 @@ export function RoleBasedRouter({
186
186
  maxHistorySize = 1000,
187
187
  unauthorizedComponent: UnauthorizedComponent = DefaultUnauthorizedComponent
188
188
  }: RoleBasedRouterProps) {
189
- const { user, selectedOrganisationId, selectedEventId } = useUnifiedAuth();
189
+ const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
190
190
  const location = useLocation();
191
191
  const navigate = useNavigate();
192
192
  const [routeAccessHistory, setRouteAccessHistory] = useState<RouteAccessRecord[]>([]);
@@ -194,14 +194,14 @@ export function RoleBasedRouter({
194
194
 
195
195
  // Get current scope
196
196
  const currentScope = useMemo((): Scope | null => {
197
- if (!selectedOrganisationId) return null;
197
+ if (!selectedOrganisation) return null;
198
198
 
199
199
  return {
200
- organisationId: selectedOrganisationId,
201
- eventId: selectedEventId || undefined,
200
+ organisationId: selectedOrganisation.id,
201
+ eventId: selectedEvent?.event_id || undefined,
202
202
  appId: undefined
203
203
  };
204
- }, [selectedOrganisationId, selectedEventId]);
204
+ }, [selectedOrganisation, selectedEvent]);
205
205
 
206
206
  // Get route configuration for current path
207
207
  const currentRouteConfig = useMemo((): RouteConfig | null => {
@@ -141,21 +141,21 @@ export function SecureDataProvider({
141
141
  maxHistorySize = 1000,
142
142
  enforceRLS = true
143
143
  }: SecureDataProviderProps) {
144
- const { user, selectedOrganisationId, selectedEventId } = useUnifiedAuth();
144
+ const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
145
145
  const { validateContext } = useSecureDataAccess();
146
146
  const [dataAccessHistory, setDataAccessHistory] = useState<DataAccessRecord[]>([]);
147
147
  const [isEnabled, setIsEnabled] = useState(true);
148
148
 
149
149
  // Get current scope
150
150
  const currentScope = useMemo((): Scope | null => {
151
- if (!selectedOrganisationId) return null;
151
+ if (!selectedOrganisation) return null;
152
152
 
153
153
  return {
154
- organisationId: selectedOrganisationId,
155
- eventId: selectedEventId || undefined,
154
+ organisationId: selectedOrganisation.id,
155
+ eventId: selectedEvent?.event_id || undefined,
156
156
  appId: undefined
157
157
  };
158
- }, [selectedOrganisationId, selectedEventId]);
158
+ }, [selectedOrganisation, selectedEvent]);
159
159
 
160
160
  // Check if data access is allowed for a table and operation
161
161
  const isDataAccessAllowed = useCallback((
@@ -78,8 +78,8 @@ describe('NavigationGuard Component', () => {
78
78
  // Default mock implementations
79
79
  mockUseUnifiedAuth.mockReturnValue({
80
80
  user: mockUser,
81
- selectedOrganisationId: 'org-123',
82
- selectedEventId: 'event-123',
81
+ selectedOrganisation: { id: 'org-123' },
82
+ selectedEvent: { event_id: 'event-123' },
83
83
  supabase: {} as any
84
84
  });
85
85
 
@@ -366,8 +366,8 @@ describe('NavigationGuard Component', () => {
366
366
  it('resolves scope from organisation only', async () => {
367
367
  mockUseUnifiedAuth.mockReturnValue({
368
368
  user: mockUser,
369
- selectedOrganisationId: 'org-123',
370
- selectedEventId: null,
369
+ selectedOrganisation: { id: 'org-123' },
370
+ selectedEvent: null,
371
371
  supabase: {} as any
372
372
  });
373
373
 
@@ -402,8 +402,8 @@ describe('NavigationGuard Component', () => {
402
402
  it('resolves scope from event context when organisation not available', async () => {
403
403
  mockUseUnifiedAuth.mockReturnValue({
404
404
  user: mockUser,
405
- selectedOrganisationId: null,
406
- selectedEventId: 'event-123',
405
+ selectedOrganisation: null,
406
+ selectedEvent: { event_id: 'event-123' },
407
407
  supabase: {} as any
408
408
  });
409
409
 
@@ -713,8 +713,8 @@ describe('NavigationGuard Component', () => {
713
713
  it('handles missing user gracefully', async () => {
714
714
  mockUseUnifiedAuth.mockReturnValue({
715
715
  user: null,
716
- selectedOrganisationId: 'org-123',
717
- selectedEventId: 'event-123',
716
+ selectedOrganisation: { id: 'org-123' },
717
+ selectedEvent: { event_id: 'event-123' },
718
718
  supabase: {} as any
719
719
  });
720
720
 
@@ -77,8 +77,8 @@ describe('PagePermissionGuard Component', () => {
77
77
  // Default mock implementations
78
78
  mockUseUnifiedAuth.mockReturnValue({
79
79
  user: mockUser,
80
- selectedOrganisationId: 'org-123',
81
- selectedEventId: 'event-123',
80
+ selectedOrganisation: { id: 'org-123' },
81
+ selectedEvent: { event_id: 'event-123' },
82
82
  supabase: {
83
83
  from: vi.fn().mockReturnValue({
84
84
  select: vi.fn().mockReturnValue({
@@ -433,8 +433,8 @@ describe('PagePermissionGuard Component', () => {
433
433
  // Mock database returning invalid app ID
434
434
  mockUseUnifiedAuth.mockReturnValue({
435
435
  user: mockUser,
436
- selectedOrganisationId: 'org-123',
437
- selectedEventId: 'event-123',
436
+ selectedOrganisation: { id: 'org-123' },
437
+ selectedEvent: { event_id: 'event-123' },
438
438
  supabase: {
439
439
  from: vi.fn().mockReturnValue({
440
440
  select: vi.fn().mockReturnValue({
@@ -547,8 +547,8 @@ describe('PagePermissionGuard Component', () => {
547
547
  it('resolves scope from organisation only', async () => {
548
548
  mockUseUnifiedAuth.mockReturnValue({
549
549
  user: mockUser,
550
- selectedOrganisationId: 'org-123',
551
- selectedEventId: null,
550
+ selectedOrganisation: { id: 'org-123' },
551
+ selectedEvent: null,
552
552
  supabase: {
553
553
  from: vi.fn().mockReturnValue({
554
554
  select: vi.fn().mockReturnValue({
@@ -600,8 +600,8 @@ describe('PagePermissionGuard Component', () => {
600
600
  it('resolves scope from event context when organisation not available', async () => {
601
601
  mockUseUnifiedAuth.mockReturnValue({
602
602
  user: mockUser,
603
- selectedOrganisationId: null,
604
- selectedEventId: 'event-123',
603
+ selectedOrganisation: null,
604
+ selectedEvent: { event_id: 'event-123' },
605
605
  supabase: {
606
606
  from: vi.fn().mockReturnValue({
607
607
  select: vi.fn().mockReturnValue({
@@ -663,8 +663,8 @@ describe('PagePermissionGuard Component', () => {
663
663
  it('handles scope resolution errors', async () => {
664
664
  mockUseUnifiedAuth.mockReturnValue({
665
665
  user: mockUser,
666
- selectedOrganisationId: null,
667
- selectedEventId: 'event-123',
666
+ selectedOrganisation: null,
667
+ selectedEvent: { event_id: 'event-123' },
668
668
  supabase: {} as any
669
669
  });
670
670
 
@@ -689,8 +689,8 @@ describe('PagePermissionGuard Component', () => {
689
689
  it('handles missing context gracefully', async () => {
690
690
  mockUseUnifiedAuth.mockReturnValue({
691
691
  user: mockUser,
692
- selectedOrganisationId: null,
693
- selectedEventId: null,
692
+ selectedOrganisation: null,
693
+ selectedEvent: null,
694
694
  supabase: null
695
695
  });
696
696
 
@@ -960,8 +960,8 @@ describe('PagePermissionGuard Component', () => {
960
960
  it('handles database errors during app resolution', async () => {
961
961
  mockUseUnifiedAuth.mockReturnValue({
962
962
  user: mockUser,
963
- selectedOrganisationId: 'org-123',
964
- selectedEventId: 'event-123',
963
+ selectedOrganisation: { id: 'org-123' },
964
+ selectedEvent: { event_id: 'event-123' },
965
965
  supabase: {
966
966
  from: vi.fn().mockReturnValue({
967
967
  select: vi.fn().mockReturnValue({
@@ -70,8 +70,8 @@ describe('PermissionEnforcer Component', () => {
70
70
  // Default mock implementations
71
71
  mockUseUnifiedAuth.mockReturnValue({
72
72
  user: mockUser,
73
- selectedOrganisationId: 'org-123',
74
- selectedEventId: 'event-123',
73
+ selectedOrganisation: { id: 'org-123' },
74
+ selectedEvent: { event_id: 'event-123' },
75
75
  supabase: {} as any
76
76
  });
77
77
 
@@ -377,8 +377,8 @@ describe('PermissionEnforcer Component', () => {
377
377
  it('resolves scope from organisation only', async () => {
378
378
  mockUseUnifiedAuth.mockReturnValue({
379
379
  user: mockUser,
380
- selectedOrganisationId: 'org-123',
381
- selectedEventId: null,
380
+ selectedOrganisation: { id: 'org-123' },
381
+ selectedEvent: null,
382
382
  supabase: {} as any
383
383
  });
384
384
 
@@ -416,8 +416,8 @@ describe('PermissionEnforcer Component', () => {
416
416
  it('resolves scope from event context when organisation not available', async () => {
417
417
  mockUseUnifiedAuth.mockReturnValue({
418
418
  user: mockUser,
419
- selectedOrganisationId: null,
420
- selectedEventId: 'event-123',
419
+ selectedOrganisation: null,
420
+ selectedEvent: { event_id: 'event-123' },
421
421
  supabase: {} as any
422
422
  });
423
423
 
@@ -462,8 +462,8 @@ describe('PermissionEnforcer Component', () => {
462
462
  it('handles scope resolution errors', async () => {
463
463
  mockUseUnifiedAuth.mockReturnValue({
464
464
  user: mockUser,
465
- selectedOrganisationId: null,
466
- selectedEventId: 'event-123',
465
+ selectedOrganisation: null,
466
+ selectedEvent: { event_id: 'event-123' },
467
467
  supabase: {} as any
468
468
  });
469
469
 
@@ -488,8 +488,8 @@ describe('PermissionEnforcer Component', () => {
488
488
  it('handles missing context gracefully', async () => {
489
489
  mockUseUnifiedAuth.mockReturnValue({
490
490
  user: mockUser,
491
- selectedOrganisationId: null,
492
- selectedEventId: null,
491
+ selectedOrganisation: null,
492
+ selectedEvent: null,
493
493
  supabase: null
494
494
  });
495
495
 
@@ -739,8 +739,8 @@ describe('PermissionEnforcer Component', () => {
739
739
  it('handles missing user gracefully', async () => {
740
740
  mockUseUnifiedAuth.mockReturnValue({
741
741
  user: null,
742
- selectedOrganisationId: 'org-123',
743
- selectedEventId: 'event-123',
742
+ selectedOrganisation: { id: 'org-123' },
743
+ selectedEvent: { event_id: 'event-123' },
744
744
  supabase: {} as any
745
745
  });
746
746
 
@@ -99,8 +99,8 @@ describe('RoleBasedRouter Component', () => {
99
99
  // Default mock implementations
100
100
  mockUseUnifiedAuth.mockReturnValue({
101
101
  user: mockUser,
102
- selectedOrganisationId: 'org-123',
103
- selectedEventId: 'event-123'
102
+ selectedOrganisation: { id: 'org-123' },
103
+ selectedEvent: { event_id: 'event-123' }
104
104
  });
105
105
 
106
106
  mockUseLocation.mockReturnValue({
@@ -611,8 +611,8 @@ describe('RoleBasedRouter Component', () => {
611
611
  it('handles missing user gracefully', async () => {
612
612
  mockUseUnifiedAuth.mockReturnValue({
613
613
  user: null,
614
- selectedOrganisationId: 'org-123',
615
- selectedEventId: 'event-123'
614
+ selectedOrganisation: { id: 'org-123' },
615
+ selectedEvent: { event_id: 'event-123' }
616
616
  });
617
617
 
618
618
  mockUseCan.mockReturnValue({
@@ -648,8 +648,8 @@ describe('RoleBasedRouter Component', () => {
648
648
  it('handles missing organisation context', async () => {
649
649
  mockUseUnifiedAuth.mockReturnValue({
650
650
  user: mockUser,
651
- selectedOrganisationId: null,
652
- selectedEventId: null
651
+ selectedOrganisation: null,
652
+ selectedEvent: null
653
653
  });
654
654
 
655
655
  mockUseCan.mockReturnValue({