@jmruthers/pace-core 0.5.191 → 0.6.1

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 (380) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +372 -0
  4. package/cursor-rules/01-standards-compliance.mdc +275 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +341 -0
  7. package/cursor-rules/04-testing-standards.mdc +315 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +392 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +309 -0
  11. package/cursor-rules/CHANGELOG.md +101 -0
  12. package/cursor-rules/README.md +191 -0
  13. package/dist/{AuthService-CbP_utw2.d.ts → AuthService-DjnJHDtC.d.ts} +1 -0
  14. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-CH1U5Tpy.d.ts} +1 -1
  15. package/dist/{DataTable-WKRZD47S.js → DataTable-DQ7RSOHE.js} +8 -7
  16. package/dist/{PublicPageProvider-ULXC_u6U.d.ts → PublicPageProvider-ce4xlHYA.d.ts} +37 -156
  17. package/dist/{UnifiedAuthProvider-BYA9qB-o.d.ts → UnifiedAuthProvider-185Ih4dj.d.ts} +2 -0
  18. package/dist/{UnifiedAuthProvider-FTSG5XH7.js → UnifiedAuthProvider-ATAP5UTR.js} +3 -3
  19. package/dist/{api-IHKALJZD.js → api-N774RPUA.js} +2 -2
  20. package/dist/{chunk-6C4YBBJM.js → chunk-3QRJFVBR.js} +1 -1
  21. package/dist/chunk-3QRJFVBR.js.map +1 -0
  22. package/dist/{chunk-OETXORNB.js → chunk-3XTALGJF.js} +211 -136
  23. package/dist/chunk-3XTALGJF.js.map +1 -0
  24. package/dist/{chunk-6TQDD426.js → chunk-4N5C5XZU.js} +47 -228
  25. package/dist/chunk-4N5C5XZU.js.map +1 -0
  26. package/dist/{chunk-LOMZXPSN.js → chunk-4ZC4GX36.js} +47 -74
  27. package/dist/chunk-4ZC4GX36.js.map +1 -0
  28. package/dist/{chunk-6LTQQAT6.js → chunk-BYFSK72L.js} +357 -158
  29. package/dist/chunk-BYFSK72L.js.map +1 -0
  30. package/dist/{chunk-XYXSXPUK.js → chunk-EXUD6RNJ.js} +50 -10
  31. package/dist/chunk-EXUD6RNJ.js.map +1 -0
  32. package/dist/{chunk-VKB2CO4Z.js → chunk-GLK6VM3F.js} +244 -249
  33. package/dist/chunk-GLK6VM3F.js.map +1 -0
  34. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  35. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  36. package/dist/{chunk-XNYQOL3Z.js → chunk-JBKQ3SAO.js} +9 -18
  37. package/dist/chunk-JBKQ3SAO.js.map +1 -0
  38. package/dist/{chunk-ROXMHMY2.js → chunk-KNC55RTG.js} +13 -3
  39. package/dist/{chunk-ROXMHMY2.js.map → chunk-KNC55RTG.js.map} +1 -1
  40. package/dist/{chunk-QWWZ5CAQ.js → chunk-LXQLPRQ2.js} +2 -2
  41. package/dist/{chunk-ULHIJK66.js → chunk-T33XF5ZC.js} +255 -140
  42. package/dist/chunk-T33XF5ZC.js.map +1 -0
  43. package/dist/{chunk-VRGWKHDB.js → chunk-XM25TVIE.js} +100 -33
  44. package/dist/chunk-XM25TVIE.js.map +1 -0
  45. package/dist/components.d.ts +4 -4
  46. package/dist/components.js +9 -9
  47. package/dist/hooks.d.ts +6 -6
  48. package/dist/hooks.js +20 -25
  49. package/dist/hooks.js.map +1 -1
  50. package/dist/index.d.ts +11 -11
  51. package/dist/index.js +18 -21
  52. package/dist/index.js.map +1 -1
  53. package/dist/providers.d.ts +3 -3
  54. package/dist/providers.js +2 -2
  55. package/dist/rbac/index.d.ts +2 -20
  56. package/dist/rbac/index.js +7 -9
  57. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-BJAlWfuJ.d.ts} +3 -3
  58. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  59. package/dist/utils.d.ts +1 -1
  60. package/dist/utils.js +3 -3
  61. package/docs/api/classes/ColumnFactory.md +1 -1
  62. package/docs/api/classes/ErrorBoundary.md +1 -1
  63. package/docs/api/classes/InvalidScopeError.md +1 -1
  64. package/docs/api/classes/Logger.md +1 -1
  65. package/docs/api/classes/MissingUserContextError.md +1 -1
  66. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  67. package/docs/api/classes/PermissionDeniedError.md +2 -2
  68. package/docs/api/classes/RBACAuditManager.md +2 -2
  69. package/docs/api/classes/RBACCache.md +1 -1
  70. package/docs/api/classes/RBACEngine.md +2 -2
  71. package/docs/api/classes/RBACError.md +1 -1
  72. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  73. package/docs/api/classes/SecureSupabaseClient.md +10 -10
  74. package/docs/api/classes/StorageUtils.md +1 -1
  75. package/docs/api/enums/FileCategory.md +1 -1
  76. package/docs/api/enums/LogLevel.md +1 -1
  77. package/docs/api/enums/RBACErrorCode.md +1 -1
  78. package/docs/api/enums/RPCFunction.md +1 -1
  79. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  80. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +1 -1
  82. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  83. package/docs/api/interfaces/AvatarProps.md +1 -1
  84. package/docs/api/interfaces/BadgeProps.md +1 -1
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CalendarProps.md +1 -1
  87. package/docs/api/interfaces/CardProps.md +1 -1
  88. package/docs/api/interfaces/ColorPalette.md +1 -1
  89. package/docs/api/interfaces/ColorShade.md +1 -1
  90. package/docs/api/interfaces/ComplianceResult.md +1 -1
  91. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  92. package/docs/api/interfaces/DataRecord.md +1 -1
  93. package/docs/api/interfaces/DataTableAction.md +1 -1
  94. package/docs/api/interfaces/DataTableColumn.md +1 -1
  95. package/docs/api/interfaces/DataTableProps.md +1 -1
  96. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  97. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  98. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  99. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  100. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  101. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  102. package/docs/api/interfaces/ExportColumn.md +1 -1
  103. package/docs/api/interfaces/ExportOptions.md +1 -1
  104. package/docs/api/interfaces/FileDisplayProps.md +24 -11
  105. package/docs/api/interfaces/FileMetadata.md +1 -1
  106. package/docs/api/interfaces/FileReference.md +1 -1
  107. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  108. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  109. package/docs/api/interfaces/FileUploadProps.md +1 -1
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/FormFieldProps.md +1 -1
  112. package/docs/api/interfaces/FormProps.md +1 -1
  113. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  114. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  115. package/docs/api/interfaces/InputProps.md +1 -1
  116. package/docs/api/interfaces/LabelProps.md +1 -1
  117. package/docs/api/interfaces/LoggerConfig.md +1 -1
  118. package/docs/api/interfaces/LoginFormProps.md +1 -1
  119. package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
  120. package/docs/api/interfaces/NavigationContextType.md +1 -1
  121. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  122. package/docs/api/interfaces/NavigationItem.md +1 -1
  123. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  124. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  125. package/docs/api/interfaces/Organisation.md +1 -1
  126. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  127. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  128. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  129. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  130. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  131. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  132. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  133. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  134. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  135. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  136. package/docs/api/interfaces/PaletteData.md +1 -1
  137. package/docs/api/interfaces/ParsedAddress.md +1 -1
  138. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  139. package/docs/api/interfaces/ProgressProps.md +1 -1
  140. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  141. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  142. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  143. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  144. package/docs/api/interfaces/QuickFix.md +1 -1
  145. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  146. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  147. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  148. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  149. package/docs/api/interfaces/RBACConfig.md +2 -2
  150. package/docs/api/interfaces/RBACContext.md +1 -1
  151. package/docs/api/interfaces/RBACLogger.md +1 -1
  152. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  153. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  154. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  155. package/docs/api/interfaces/RBACPermissionCheckResult.md +2 -2
  156. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  157. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  158. package/docs/api/interfaces/RBACResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleGrantParams.md +2 -2
  160. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  161. package/docs/api/interfaces/RBACRoleRevokeParams.md +2 -2
  162. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  163. package/docs/api/interfaces/RBACRoleValidateParams.md +2 -2
  164. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  165. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  166. package/docs/api/interfaces/RBACRolesListResult.md +2 -2
  167. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  168. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  169. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  170. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  171. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  172. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  173. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  174. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  175. package/docs/api/interfaces/RouteConfig.md +2 -2
  176. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  177. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  178. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  179. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  180. package/docs/api/interfaces/SetupIssue.md +1 -1
  181. package/docs/api/interfaces/StorageConfig.md +1 -1
  182. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  183. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  184. package/docs/api/interfaces/StorageListOptions.md +1 -1
  185. package/docs/api/interfaces/StorageListResult.md +1 -1
  186. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  187. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  188. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  189. package/docs/api/interfaces/StyleImport.md +1 -1
  190. package/docs/api/interfaces/SwitchProps.md +1 -1
  191. package/docs/api/interfaces/TabsContentProps.md +1 -1
  192. package/docs/api/interfaces/TabsListProps.md +1 -1
  193. package/docs/api/interfaces/TabsProps.md +1 -1
  194. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  195. package/docs/api/interfaces/TextareaProps.md +1 -1
  196. package/docs/api/interfaces/ToastActionElement.md +1 -1
  197. package/docs/api/interfaces/ToastProps.md +1 -1
  198. package/docs/api/interfaces/UnifiedAuthContextType.md +60 -38
  199. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  200. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  201. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  202. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  203. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  205. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  207. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  208. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  209. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  210. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  211. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  212. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  213. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  214. package/docs/api/interfaces/UserEventAccess.md +1 -1
  215. package/docs/api/interfaces/UserMenuProps.md +1 -1
  216. package/docs/api/interfaces/UserProfile.md +1 -1
  217. package/docs/api/modules.md +194 -209
  218. package/docs/getting-started/cursor-rules.md +262 -0
  219. package/docs/getting-started/installation-guide.md +6 -1
  220. package/docs/getting-started/quick-start.md +6 -1
  221. package/docs/migration/MIGRATION_GUIDE.md +4 -4
  222. package/docs/migration/REACT_19_MIGRATION.md +227 -0
  223. package/docs/migration/database-changes-december-2025.md +2 -1
  224. package/docs/rbac/event-based-apps.md +124 -6
  225. package/docs/standards/README.md +39 -0
  226. package/docs/troubleshooting/migration.md +4 -4
  227. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  228. package/package.json +11 -6
  229. package/scripts/audit-consuming-app.cjs +961 -0
  230. package/scripts/check-pace-core-compliance.cjs +315 -61
  231. package/scripts/install-cursor-rules.cjs +236 -0
  232. package/src/__tests__/helpers/test-providers.tsx +1 -1
  233. package/src/__tests__/helpers/test-utils.tsx +1 -1
  234. package/src/__tests__/rls-policies.test.ts +3 -1
  235. package/src/components/Badge/Badge.tsx +2 -4
  236. package/src/components/Button/Button.tsx +5 -4
  237. package/src/components/Calendar/Calendar.tsx +1 -1
  238. package/src/components/DataTable/DataTable.test.tsx +57 -93
  239. package/src/components/DataTable/DataTable.tsx +2 -2
  240. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +172 -45
  241. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +121 -28
  242. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +9 -8
  243. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +20 -52
  244. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +170 -34
  245. package/src/components/DataTable/__tests__/keyboard.test.tsx +75 -12
  246. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +88 -16
  247. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  248. package/src/components/DataTable/components/AccessDeniedPage.tsx +1 -1
  249. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  250. package/src/components/DataTable/components/DataTableCore.tsx +4 -7
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -1
  252. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  253. package/src/components/DataTable/components/UnifiedTableBody.tsx +86 -17
  254. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  255. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  256. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  257. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  258. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  259. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  260. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  261. package/src/components/DataTable/hooks/useColumnReordering.ts +2 -2
  262. package/src/components/DataTable/hooks/useDataTablePermissions.ts +75 -10
  263. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  264. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  265. package/src/components/Dialog/Dialog.tsx +6 -5
  266. package/src/components/ErrorBoundary/ErrorBoundary.tsx +1 -1
  267. package/src/components/EventSelector/EventSelector.tsx +1 -1
  268. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -3
  269. package/src/components/FileDisplay/FileDisplay.tsx +16 -4
  270. package/src/components/Footer/Footer.tsx +1 -1
  271. package/src/components/Form/Form.test.tsx +36 -15
  272. package/src/components/Form/Form.tsx +30 -26
  273. package/src/components/Header/Header.tsx +1 -1
  274. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  275. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  276. package/src/components/Input/Input.tsx +28 -30
  277. package/src/components/Label/Label.tsx +1 -1
  278. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  279. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  280. package/src/components/LoginForm/LoginForm.tsx +8 -8
  281. package/src/components/NavigationMenu/NavigationMenu.test.tsx +6 -4
  282. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -11
  283. package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -1
  284. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  285. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +75 -52
  286. package/src/components/PaceAppLayout/PaceAppLayout.tsx +98 -69
  287. package/src/components/PaceAppLayout/README.md +1 -1
  288. package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -8
  289. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  290. package/src/components/PasswordChange/PasswordChangeForm.tsx +1 -1
  291. package/src/components/Progress/Progress.tsx +1 -1
  292. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +5 -9
  293. package/src/components/ProtectedRoute/ProtectedRoute.tsx +0 -1
  294. package/src/components/PublicLayout/PublicPageLayout.tsx +1 -1
  295. package/src/components/PublicLayout/PublicPageProvider.tsx +0 -1
  296. package/src/components/Select/Select.tsx +33 -22
  297. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +1 -1
  298. package/src/components/Table/Table.tsx +1 -1
  299. package/src/components/Textarea/Textarea.tsx +27 -29
  300. package/src/components/Toast/Toast.tsx +1 -1
  301. package/src/components/Tooltip/Tooltip.tsx +1 -1
  302. package/src/components/UserMenu/UserMenu.tsx +1 -1
  303. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  304. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +14 -7
  305. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  306. package/src/hooks/public/usePublicEvent.ts +1 -1
  307. package/src/hooks/public/usePublicEventLogo.ts +1 -1
  308. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  309. package/src/hooks/services/useAuthService.ts +21 -3
  310. package/src/hooks/services/useEventService.ts +21 -3
  311. package/src/hooks/services/useInactivityService.ts +21 -3
  312. package/src/hooks/services/useOrganisationService.ts +21 -3
  313. package/src/hooks/useDataTableState.ts +8 -18
  314. package/src/hooks/useFileDisplay.ts +10 -17
  315. package/src/hooks/useFocusManagement.ts +2 -2
  316. package/src/hooks/useFocusTrap.ts +4 -4
  317. package/src/hooks/useFormDialog.ts +8 -7
  318. package/src/hooks/useInactivityTracker.ts +1 -1
  319. package/src/hooks/usePermissionCache.ts +1 -1
  320. package/src/hooks/useSecureDataAccess.test.ts +16 -9
  321. package/src/hooks/useSecureDataAccess.ts +22 -6
  322. package/src/hooks/useToast.ts +2 -2
  323. package/src/providers/__tests__/OrganisationProvider.test.tsx +57 -13
  324. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  325. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  326. package/src/providers/services/EventServiceProvider.tsx +0 -8
  327. package/src/providers/services/UnifiedAuthProvider.tsx +196 -46
  328. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +13 -3
  329. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +34 -40
  330. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +82 -0
  331. package/src/rbac/adapters.tsx +3 -22
  332. package/src/rbac/api.test.ts +2 -2
  333. package/src/rbac/api.ts +7 -1
  334. package/src/rbac/components/EnhancedNavigationMenu.tsx +3 -16
  335. package/src/rbac/components/NavigationGuard.tsx +2 -11
  336. package/src/rbac/components/NavigationProvider.tsx +1 -2
  337. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  338. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  339. package/src/rbac/components/PermissionEnforcer.tsx +46 -13
  340. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  341. package/src/rbac/components/SecureDataProvider.tsx +1 -2
  342. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +7 -43
  343. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +4 -11
  344. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +3 -3
  345. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +1 -1
  346. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +1 -1
  347. package/src/rbac/engine.ts +14 -2
  348. package/src/rbac/hooks/index.ts +0 -3
  349. package/src/rbac/hooks/usePermissions.ts +51 -11
  350. package/src/rbac/hooks/useRBAC.ts +3 -13
  351. package/src/rbac/hooks/useResolvedScope.test.ts +75 -54
  352. package/src/rbac/hooks/useResolvedScope.ts +58 -33
  353. package/src/rbac/hooks/useSecureSupabase.ts +4 -9
  354. package/src/rbac/secureClient.ts +43 -0
  355. package/src/services/EventService.ts +4 -57
  356. package/src/services/InactivityService.ts +127 -34
  357. package/src/services/OrganisationService.ts +68 -10
  358. package/src/utils/security/secureDataAccess.test.ts +31 -20
  359. package/src/utils/security/secureDataAccess.ts +4 -3
  360. package/dist/chunk-6C4YBBJM.js.map +0 -1
  361. package/dist/chunk-6LTQQAT6.js.map +0 -1
  362. package/dist/chunk-6TQDD426.js.map +0 -1
  363. package/dist/chunk-LOMZXPSN.js.map +0 -1
  364. package/dist/chunk-OETXORNB.js.map +0 -1
  365. package/dist/chunk-ULHIJK66.js.map +0 -1
  366. package/dist/chunk-VKB2CO4Z.js.map +0 -1
  367. package/dist/chunk-VRGWKHDB.js.map +0 -1
  368. package/dist/chunk-XNYQOL3Z.js.map +0 -1
  369. package/dist/chunk-XYXSXPUK.js.map +0 -1
  370. package/scripts/check-pace-core-compliance.js +0 -512
  371. package/src/rbac/hooks/useSuperAdminBypass.ts +0 -126
  372. package/src/utils/context/superAdminOverride.ts +0 -58
  373. /package/dist/{DataTable-WKRZD47S.js.map → DataTable-DQ7RSOHE.js.map} +0 -0
  374. /package/dist/{UnifiedAuthProvider-FTSG5XH7.js.map → UnifiedAuthProvider-ATAP5UTR.js.map} +0 -0
  375. /package/dist/{api-IHKALJZD.js.map → api-N774RPUA.js.map} +0 -0
  376. /package/dist/{chunk-QWWZ5CAQ.js.map → chunk-LXQLPRQ2.js.map} +0 -0
  377. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  378. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  379. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  380. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getAppConfigByName,
3
3
  isSuperAdmin
4
- } from "./chunk-ROXMHMY2.js";
4
+ } from "./chunk-KNC55RTG.js";
5
5
  import {
6
6
  assertOrganisationId,
7
7
  assertUserId
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-PWLANIRT.js";
17
17
 
18
18
  // src/providers/services/UnifiedAuthProvider.tsx
19
- import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef4, useEffect as useEffect10, useState as useState3, useReducer as useReducer5 } from "react";
19
+ import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef8, useEffect as useEffect10, useState as useState3, useReducer as useReducer5 } from "react";
20
20
 
21
21
  // src/providers/services/AuthServiceProvider.tsx
22
22
  import { createContext, useMemo, useEffect, useState } from "react";
@@ -627,6 +627,8 @@ var OrganisationService = class extends BaseService {
627
627
  this._roleMapState = /* @__PURE__ */ new Map();
628
628
  this._isLoading = false;
629
629
  this._error = null;
630
+ this._isSuperAdmin = false;
631
+ // Cache super admin status
630
632
  this._isContextReady = false;
631
633
  this.retryCount = 0;
632
634
  // Dependencies
@@ -667,14 +669,16 @@ var OrganisationService = class extends BaseService {
667
669
  // Additional methods for testing
668
670
  setSelectedOrganisation(organisation) {
669
671
  if (organisation && this._organisations.length > 0) {
670
- const isValidOrg = this._organisations.some((org) => org.id === organisation.id);
671
- if (!isValidOrg) {
672
- logger.warn("OrganisationService", "Attempted to set invalid organisation - not in user's accessible organisations", {
673
- organisationId: organisation.id,
674
- organisationName: organisation.name,
675
- accessibleOrgIds: this._organisations.map((o) => o.id)
676
- });
677
- return;
672
+ if (!this._isSuperAdmin) {
673
+ const isValidOrg = this._organisations.some((org) => org.id === organisation.id);
674
+ if (!isValidOrg) {
675
+ logger.warn("OrganisationService", "Attempted to set invalid organisation - not in user's accessible organisations", {
676
+ organisationId: organisation.id,
677
+ organisationName: organisation.name,
678
+ accessibleOrgIds: this._organisations.map((o) => o.id)
679
+ });
680
+ return;
681
+ }
678
682
  }
679
683
  }
680
684
  this._selectedOrganisation = organisation;
@@ -713,6 +717,9 @@ var OrganisationService = class extends BaseService {
713
717
  updateDependencies(user, session) {
714
718
  const wasAuthenticated = !!(this.user && this.session);
715
719
  const isAuthenticated = !!(user && session);
720
+ if (this.user?.id !== user?.id) {
721
+ this._isSuperAdmin = false;
722
+ }
716
723
  this.user = user;
717
724
  this.session = session;
718
725
  if (wasAuthenticated && !isAuthenticated) {
@@ -936,10 +943,40 @@ var OrganisationService = class extends BaseService {
936
943
  logger.error("OrganisationService", "Error loading organisation roles:", membershipError);
937
944
  throw membershipError;
938
945
  }
946
+ let userIsSuperAdmin = false;
947
+ if (this.user?.id) {
948
+ try {
949
+ userIsSuperAdmin = await isSuperAdmin(this.user.id);
950
+ this._isSuperAdmin = userIsSuperAdmin;
951
+ } catch (error) {
952
+ logger.warn("OrganisationService", "Failed to check super admin status", { error });
953
+ this._isSuperAdmin = false;
954
+ }
955
+ } else {
956
+ this._isSuperAdmin = false;
957
+ }
939
958
  if (!memberships || memberships.length === 0) {
959
+ if (userIsSuperAdmin) {
960
+ this._organisations = [];
961
+ this._userMemberships = [];
962
+ this._isLoading = false;
963
+ this._error = null;
964
+ this._isContextReady = true;
965
+ this.notify();
966
+ return;
967
+ }
940
968
  throw new Error("User has no active organisation memberships");
941
969
  }
942
970
  if (!organisations || organisations.length === 0) {
971
+ if (userIsSuperAdmin) {
972
+ this._organisations = [];
973
+ this._userMemberships = [];
974
+ this._isLoading = false;
975
+ this._error = null;
976
+ this._isContextReady = true;
977
+ this.notify();
978
+ return;
979
+ }
943
980
  throw new Error("No organisations found in role data");
944
981
  }
945
982
  const roleMap = /* @__PURE__ */ new Map();
@@ -949,6 +986,15 @@ var OrganisationService = class extends BaseService {
949
986
  const orgs = organisations;
950
987
  const activeOrgs = orgs.filter((org) => org.is_active);
951
988
  if (activeOrgs.length === 0) {
989
+ if (userIsSuperAdmin) {
990
+ this._organisations = [];
991
+ this._userMemberships = [];
992
+ this._isLoading = false;
993
+ this._error = null;
994
+ this._isContextReady = true;
995
+ this.notify();
996
+ return;
997
+ }
952
998
  throw new Error("User has no access to active organisations");
953
999
  }
954
1000
  this._organisations = activeOrgs;
@@ -1149,10 +1195,6 @@ var EventService = class extends BaseService {
1149
1195
  if (user?.id) {
1150
1196
  try {
1151
1197
  this.isSuperAdmin = await isSuperAdmin(user.id);
1152
- logger.debug("EventService", "Updated super admin status", {
1153
- userId: user.id,
1154
- isSuperAdmin: this.isSuperAdmin
1155
- });
1156
1198
  } catch (error) {
1157
1199
  logger.warn("EventService", "Failed to check super admin status", { error });
1158
1200
  this.isSuperAdmin = false;
@@ -1176,7 +1218,7 @@ var EventService = class extends BaseService {
1176
1218
  }
1177
1219
  // Event state getters
1178
1220
  getEvents() {
1179
- return [...this.events];
1221
+ return this.events;
1180
1222
  }
1181
1223
  getSelectedEvent() {
1182
1224
  return this.selectedEvent;
@@ -1286,31 +1328,16 @@ var EventService = class extends BaseService {
1286
1328
  }
1287
1329
  // Lifecycle methods
1288
1330
  async initialize() {
1289
- logger.debug("EventService", "initialize() called", {
1290
- isInitializedRef: this.isInitializedRef,
1291
- hasUser: !!this.user,
1292
- hasSession: !!this.session,
1293
- appName: this.appName
1294
- });
1295
1331
  await super.initialize();
1296
1332
  }
1297
1333
  cleanup() {
1298
1334
  super.cleanup();
1299
1335
  }
1300
1336
  async doInitialize() {
1301
- logger.debug("EventService", "doInitialize() called", {
1302
- isInitializedRef: this.isInitializedRef,
1303
- isFetchingRef: this.isFetchingRef,
1304
- hasUser: !!this.user,
1305
- hasSession: !!this.session,
1306
- appName: this.appName
1307
- });
1308
1337
  if (this.isInitializedRef) {
1309
- logger.debug("EventService", "Skipping initialization - already initialized");
1310
1338
  return;
1311
1339
  }
1312
1340
  if (this.isFetchingRef) {
1313
- logger.debug("EventService", "Skipping initialization - already fetching");
1314
1341
  return;
1315
1342
  }
1316
1343
  try {
@@ -1321,14 +1348,8 @@ var EventService = class extends BaseService {
1321
1348
  logger.warn("EventService", "Failed to clean up old storage keys:", error);
1322
1349
  }
1323
1350
  if (!this.user) {
1324
- logger.debug("EventService", "Skipping initialization - missing user");
1325
1351
  return;
1326
1352
  }
1327
- logger.debug("EventService", "Initializing - fetching events", {
1328
- userId: this.user.id,
1329
- organisationId: this.selectedOrganisation?.id || "derived-from-event",
1330
- appName: this.appName
1331
- });
1332
1353
  await this.fetchEvents(false);
1333
1354
  this.isInitializedRef = true;
1334
1355
  }
@@ -1336,19 +1357,12 @@ var EventService = class extends BaseService {
1336
1357
  }
1337
1358
  async fetchEvents(skipLoadPersisted = false) {
1338
1359
  if (!this.user || !this.session || !this.supabaseClient || !this.appName) {
1339
- logger.debug("EventService", "Skipping fetchEvents - missing dependencies", {
1340
- hasUser: !!this.user,
1341
- hasSession: !!this.session,
1342
- hasSupabaseClient: !!this.supabaseClient,
1343
- appName: this.appName
1344
- });
1345
1360
  this.notify();
1346
1361
  return;
1347
1362
  }
1348
1363
  this._isLoading = true;
1349
1364
  this.notify();
1350
1365
  if (this.isFetchingRef) {
1351
- logger.debug("EventService", "Skipping fetchEvents - already fetching");
1352
1366
  return;
1353
1367
  }
1354
1368
  this.isFetchingRef = true;
@@ -1370,18 +1384,11 @@ var EventService = class extends BaseService {
1370
1384
  userIsSuperAdmin = await isSuperAdmin(this.user.id);
1371
1385
  if (userIsSuperAdmin) {
1372
1386
  organisationIdForRpc = null;
1373
- logger.debug("EventService", "Super admin detected - fetching all events", {
1374
- userId: this.user.id
1375
- });
1376
1387
  } else {
1377
1388
  if (this.selectedEvent) {
1378
1389
  organisationIdForRpc = this.selectedEvent.organisation_id;
1379
1390
  } else if (this.appConfig?.requires_event === true) {
1380
1391
  organisationIdForRpc = null;
1381
- logger.debug("EventService", "Event-required app: fetching all accessible events (no event selected yet)", {
1382
- userId: this.user.id,
1383
- appName: this.appName
1384
- });
1385
1392
  } else if (this.selectedOrganisation) {
1386
1393
  organisationIdForRpc = this.selectedOrganisation.id;
1387
1394
  } else {
@@ -1405,22 +1412,11 @@ var EventService = class extends BaseService {
1405
1412
  organisationIdForRpc = this.selectedOrganisation.id;
1406
1413
  }
1407
1414
  }
1408
- logger.debug("EventService", "Fetching events via RPC", {
1409
- userId: this.user.id,
1410
- organisationId: organisationIdForRpc,
1411
- appName: this.appName
1412
- });
1413
1415
  let { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
1414
1416
  p_user_id: this.user.id,
1415
1417
  p_organisation_id: organisationIdForRpc,
1416
1418
  p_app_name: this.appName
1417
1419
  });
1418
- logger.debug("EventService", "RPC response received", {
1419
- hasData: !!data,
1420
- dataLength: Array.isArray(data) ? data.length : "not array",
1421
- hasError: !!rpcError,
1422
- error: rpcError
1423
- });
1424
1420
  if (rpcError) {
1425
1421
  logger.error("EventService", "RPC error fetching events:", rpcError);
1426
1422
  throw new Error(rpcError.message || "Failed to fetch events");
@@ -1545,13 +1541,6 @@ function EventServiceProvider({
1545
1541
  const updateAndInitialize = async () => {
1546
1542
  initializingRef.current = true;
1547
1543
  try {
1548
- logger.debug("EventServiceProvider", "Updating dependencies and initializing", {
1549
- hasUser: !!user,
1550
- hasSession: !!session,
1551
- appName,
1552
- hasSelectedOrganisation: !!selectedOrganisation,
1553
- organisationId: selectedOrganisation?.id
1554
- });
1555
1544
  await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
1556
1545
  if (!isMounted) return;
1557
1546
  await eventService.initialize().catch((error) => {
@@ -1694,12 +1683,19 @@ var InactivityService = class extends BaseService {
1694
1683
  if (this.inactivityTracker) {
1695
1684
  this.inactivityTracker.resetActivity();
1696
1685
  }
1686
+ const prevIsIdle = this._isIdle;
1687
+ const prevShowWarning = this._showWarning;
1688
+ const prevShowInactivityWarning = this._showInactivityWarning;
1689
+ const prevInactivityTimeRemaining = this._inactivityTimeRemaining;
1690
+ const prevTimeRemaining = this._timeRemaining;
1697
1691
  this._isIdle = false;
1698
1692
  this._showWarning = false;
1699
1693
  this._showInactivityWarning = false;
1700
1694
  this._inactivityTimeRemaining = 0;
1701
1695
  this._timeRemaining = this.idleTimeoutMs;
1702
- this.notify();
1696
+ if (prevIsIdle !== this._isIdle || prevShowWarning !== this._showWarning || prevShowInactivityWarning !== this._showInactivityWarning || prevInactivityTimeRemaining !== this._inactivityTimeRemaining || prevTimeRemaining !== this._timeRemaining) {
1697
+ this.notify();
1698
+ }
1703
1699
  }
1704
1700
  startTracking() {
1705
1701
  if (this.inactivityTracker) {
@@ -1793,8 +1789,39 @@ var InactivityService = class extends BaseService {
1793
1789
  let idleTimer = null;
1794
1790
  let warningTimer = null;
1795
1791
  let lastActivity = Date.now();
1796
- const resetTimers = () => {
1797
- lastActivity = Date.now();
1792
+ let pollInterval = null;
1793
+ let prevIsIdle = false;
1794
+ let prevShowWarning = false;
1795
+ let prevShowInactivityWarning = false;
1796
+ let prevInactivityTimeRemaining = 0;
1797
+ let prevTimeRemaining = this.idleTimeoutMs;
1798
+ const pollInactivityState = () => {
1799
+ const now = Date.now();
1800
+ const timeSinceActivity = now - lastActivity;
1801
+ const timeUntilIdle = this.idleTimeoutMs - timeSinceActivity;
1802
+ const timeUntilWarning = this.idleTimeoutMs - this.warnBeforeMs - timeSinceActivity;
1803
+ const newIsIdle = timeSinceActivity >= this.idleTimeoutMs - this.warnBeforeMs;
1804
+ const newShowWarning = newIsIdle && timeSinceActivity < this.idleTimeoutMs;
1805
+ const newShowInactivityWarning = newShowWarning;
1806
+ const newInactivityTimeRemaining = newShowWarning ? Math.ceil((this.idleTimeoutMs - timeSinceActivity) / 1e3) : 0;
1807
+ const newTimeRemaining = Math.max(0, timeUntilIdle);
1808
+ const stateChanged = prevIsIdle !== newIsIdle || prevShowWarning !== newShowWarning || prevShowInactivityWarning !== newShowInactivityWarning || prevInactivityTimeRemaining !== newInactivityTimeRemaining || prevTimeRemaining !== newTimeRemaining;
1809
+ if (stateChanged) {
1810
+ this._isIdle = newIsIdle;
1811
+ this._showWarning = newShowWarning;
1812
+ this._showInactivityWarning = newShowInactivityWarning;
1813
+ this._inactivityTimeRemaining = newInactivityTimeRemaining;
1814
+ this._timeRemaining = newTimeRemaining;
1815
+ prevIsIdle = newIsIdle;
1816
+ prevShowWarning = newShowWarning;
1817
+ prevShowInactivityWarning = newShowInactivityWarning;
1818
+ prevInactivityTimeRemaining = newInactivityTimeRemaining;
1819
+ prevTimeRemaining = newTimeRemaining;
1820
+ this.notify();
1821
+ if (newIsIdle && timeSinceActivity >= this.idleTimeoutMs) {
1822
+ this.handleIdleLogout();
1823
+ }
1824
+ }
1798
1825
  if (idleTimer) {
1799
1826
  clearTimeout(idleTimer);
1800
1827
  idleTimer = null;
@@ -1803,42 +1830,48 @@ var InactivityService = class extends BaseService {
1803
1830
  clearTimeout(warningTimer);
1804
1831
  warningTimer = null;
1805
1832
  }
1806
- this._showInactivityWarning = false;
1807
- this._inactivityTimeRemaining = 0;
1808
- this._isIdle = false;
1809
- this._showWarning = false;
1810
- this.notify();
1811
- };
1812
- const startIdleTimer = () => {
1813
- if (idleTimer) {
1814
- clearTimeout(idleTimer);
1833
+ if (!newIsIdle && timeUntilIdle > 0) {
1834
+ idleTimer = setTimeout(() => {
1835
+ pollInactivityState();
1836
+ }, Math.min(1e4, timeUntilIdle));
1815
1837
  }
1816
- idleTimer = setTimeout(() => {
1817
- this._isIdle = true;
1818
- this._showWarning = true;
1819
- this.notify();
1838
+ if (newShowWarning && timeUntilIdle > 0) {
1820
1839
  warningTimer = setTimeout(() => {
1821
1840
  this.handleIdleLogout();
1822
- }, this.warnBeforeMs);
1823
- }, this.idleTimeoutMs - this.warnBeforeMs);
1841
+ }, timeUntilIdle);
1842
+ }
1824
1843
  };
1825
- const startWarningTimer = () => {
1844
+ const resetTimers = () => {
1845
+ lastActivity = Date.now();
1846
+ if (idleTimer) {
1847
+ clearTimeout(idleTimer);
1848
+ idleTimer = null;
1849
+ }
1826
1850
  if (warningTimer) {
1827
1851
  clearTimeout(warningTimer);
1852
+ warningTimer = null;
1828
1853
  }
1829
- warningTimer = setTimeout(() => {
1830
- this.handleIdleLogout();
1831
- }, this.warnBeforeMs);
1854
+ this._showInactivityWarning = false;
1855
+ this._inactivityTimeRemaining = 0;
1856
+ this._isIdle = false;
1857
+ this._showWarning = false;
1858
+ prevIsIdle = false;
1859
+ prevShowWarning = false;
1860
+ prevShowInactivityWarning = false;
1861
+ prevInactivityTimeRemaining = 0;
1862
+ prevTimeRemaining = this.idleTimeoutMs;
1832
1863
  };
1833
1864
  const activityEvents = ["mousedown", "mousemove", "keypress", "scroll", "touchstart", "click"];
1834
1865
  const handleActivity = () => {
1835
1866
  resetTimers();
1836
- startIdleTimer();
1837
1867
  };
1838
1868
  activityEvents.forEach((event) => {
1839
1869
  document.addEventListener(event, handleActivity, true);
1840
1870
  });
1841
- startIdleTimer();
1871
+ pollInterval = setInterval(() => {
1872
+ pollInactivityState();
1873
+ }, 1e4);
1874
+ pollInactivityState();
1842
1875
  this.cleanupHandlers = () => {
1843
1876
  if (idleTimer) {
1844
1877
  clearTimeout(idleTimer);
@@ -1848,6 +1881,10 @@ var InactivityService = class extends BaseService {
1848
1881
  clearTimeout(warningTimer);
1849
1882
  warningTimer = null;
1850
1883
  }
1884
+ if (pollInterval) {
1885
+ clearInterval(pollInterval);
1886
+ pollInterval = null;
1887
+ }
1851
1888
  activityEvents.forEach((event) => {
1852
1889
  document.removeEventListener(event, handleActivity, true);
1853
1890
  });
@@ -1906,29 +1943,61 @@ function InactivityServiceProvider({
1906
1943
  }
1907
1944
 
1908
1945
  // src/hooks/services/useAuthService.ts
1909
- import { useContext, useReducer, useEffect as useEffect5 } from "react";
1946
+ import { useContext, useReducer, useEffect as useEffect5, useRef as useRef4 } from "react";
1910
1947
  function useAuthService() {
1911
1948
  const context = useContext(AuthServiceContext);
1912
1949
  if (!context) {
1913
1950
  throw new Error("useAuthService must be used within AuthServiceProvider");
1914
1951
  }
1915
1952
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
1953
+ const timeoutRef = useRef4(null);
1916
1954
  useEffect5(() => {
1917
- return context.authService.subscribe(() => forceUpdate());
1955
+ const debouncedUpdate = () => {
1956
+ if (timeoutRef.current) {
1957
+ clearTimeout(timeoutRef.current);
1958
+ }
1959
+ timeoutRef.current = setTimeout(() => {
1960
+ forceUpdate();
1961
+ timeoutRef.current = null;
1962
+ }, 50);
1963
+ };
1964
+ const unsubscribe = context.authService.subscribe(debouncedUpdate);
1965
+ return () => {
1966
+ unsubscribe();
1967
+ if (timeoutRef.current) {
1968
+ clearTimeout(timeoutRef.current);
1969
+ }
1970
+ };
1918
1971
  }, [context.authService]);
1919
1972
  return context.authService;
1920
1973
  }
1921
1974
 
1922
1975
  // src/hooks/services/useOrganisationService.ts
1923
- import { useContext as useContext2, useReducer as useReducer2, useEffect as useEffect6 } from "react";
1976
+ import { useContext as useContext2, useReducer as useReducer2, useEffect as useEffect6, useRef as useRef5 } from "react";
1924
1977
  function useOrganisationService() {
1925
1978
  const context = useContext2(OrganisationServiceContext);
1926
1979
  if (!context) {
1927
1980
  throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
1928
1981
  }
1929
1982
  const [, forceUpdate] = useReducer2((x) => x + 1, 0);
1983
+ const timeoutRef = useRef5(null);
1930
1984
  useEffect6(() => {
1931
- return context.organisationService.subscribe(() => forceUpdate());
1985
+ const debouncedUpdate = () => {
1986
+ if (timeoutRef.current) {
1987
+ clearTimeout(timeoutRef.current);
1988
+ }
1989
+ timeoutRef.current = setTimeout(() => {
1990
+ forceUpdate();
1991
+ timeoutRef.current = null;
1992
+ }, 50);
1993
+ };
1994
+ const unsubscribe = context.organisationService.subscribe(debouncedUpdate);
1995
+ return () => {
1996
+ unsubscribe();
1997
+ if (timeoutRef.current) {
1998
+ clearTimeout(timeoutRef.current);
1999
+ }
2000
+ };
1932
2001
  }, [context.organisationService]);
1933
2002
  return context.organisationService;
1934
2003
  }
@@ -1957,29 +2026,61 @@ function useOrganisations() {
1957
2026
  }
1958
2027
 
1959
2028
  // src/hooks/services/useEventService.ts
1960
- import { useContext as useContext3, useReducer as useReducer3, useEffect as useEffect7 } from "react";
2029
+ import { useContext as useContext3, useReducer as useReducer3, useEffect as useEffect7, useRef as useRef6 } from "react";
1961
2030
  function useEventService() {
1962
2031
  const context = useContext3(EventServiceContext);
1963
2032
  if (!context) {
1964
2033
  throw new Error("useEventService must be used within EventServiceProvider");
1965
2034
  }
1966
2035
  const [, forceUpdate] = useReducer3((x) => x + 1, 0);
2036
+ const timeoutRef = useRef6(null);
1967
2037
  useEffect7(() => {
1968
- return context.eventService.subscribe(() => forceUpdate());
2038
+ const debouncedUpdate = () => {
2039
+ if (timeoutRef.current) {
2040
+ clearTimeout(timeoutRef.current);
2041
+ }
2042
+ timeoutRef.current = setTimeout(() => {
2043
+ forceUpdate();
2044
+ timeoutRef.current = null;
2045
+ }, 50);
2046
+ };
2047
+ const unsubscribe = context.eventService.subscribe(debouncedUpdate);
2048
+ return () => {
2049
+ unsubscribe();
2050
+ if (timeoutRef.current) {
2051
+ clearTimeout(timeoutRef.current);
2052
+ }
2053
+ };
1969
2054
  }, [context.eventService]);
1970
2055
  return context.eventService;
1971
2056
  }
1972
2057
 
1973
2058
  // src/hooks/services/useInactivityService.ts
1974
- import { useContext as useContext4, useReducer as useReducer4, useEffect as useEffect8 } from "react";
2059
+ import { useContext as useContext4, useReducer as useReducer4, useEffect as useEffect8, useRef as useRef7 } from "react";
1975
2060
  function useInactivityService() {
1976
2061
  const context = useContext4(InactivityServiceContext);
1977
2062
  if (!context) {
1978
2063
  throw new Error("useInactivityService must be used within InactivityServiceProvider");
1979
2064
  }
1980
2065
  const [, forceUpdate] = useReducer4((x) => x + 1, 0);
2066
+ const timeoutRef = useRef7(null);
1981
2067
  useEffect8(() => {
1982
- return context.inactivityService.subscribe(() => forceUpdate());
2068
+ const debouncedUpdate = () => {
2069
+ if (timeoutRef.current) {
2070
+ clearTimeout(timeoutRef.current);
2071
+ }
2072
+ timeoutRef.current = setTimeout(() => {
2073
+ forceUpdate();
2074
+ timeoutRef.current = null;
2075
+ }, 50);
2076
+ };
2077
+ const unsubscribe = context.inactivityService.subscribe(debouncedUpdate);
2078
+ return () => {
2079
+ unsubscribe();
2080
+ if (timeoutRef.current) {
2081
+ clearTimeout(timeoutRef.current);
2082
+ }
2083
+ };
1983
2084
  }, [context.inactivityService]);
1984
2085
  return context.inactivityService;
1985
2086
  }
@@ -2037,8 +2138,7 @@ var useUnifiedAuth = () => {
2037
2138
  function UnifiedAuthContextProvider({
2038
2139
  children,
2039
2140
  appName,
2040
- appConfig = { requires_event: true },
2041
- // Default to requiring events
2141
+ appConfig: appConfigProp,
2042
2142
  supabaseClient: supabaseClientProp,
2043
2143
  ...props
2044
2144
  }) {
@@ -2058,6 +2158,13 @@ function UnifiedAuthContextProvider({
2058
2158
  restorationComplete,
2059
2159
  restorationError
2060
2160
  }), [isRestoring, restorationComplete, restorationError]);
2161
+ const [appConfigState, setAppConfigState] = useState3(appConfigProp || null);
2162
+ const isResolvingAppConfigRef = useRef8(false);
2163
+ const resolvedAppConfigRef = useRef8(null);
2164
+ const appConfig = useMemo6(() => {
2165
+ if (!appConfigState) return null;
2166
+ return { requires_event: appConfigState.requires_event };
2167
+ }, [appConfigState?.requires_event]);
2061
2168
  let eventService;
2062
2169
  try {
2063
2170
  eventService = useEventService();
@@ -2081,9 +2188,9 @@ function UnifiedAuthContextProvider({
2081
2188
  const isAuth = !!(currentUser && currentSession);
2082
2189
  const supabase = useMemo6(() => supabaseClientProp, [supabaseClientProp]);
2083
2190
  const [appId, setAppId] = useState3(void 0);
2084
- const isResolvingAppIdRef = useRef4(false);
2085
- const resolvedAppIdRef = useRef4(void 0);
2086
- const resolvedUserIdRef = useRef4(void 0);
2191
+ const isResolvingAppIdRef = useRef8(false);
2192
+ const resolvedAppIdRef = useRef8(void 0);
2193
+ const resolvedUserIdRef = useRef8(void 0);
2087
2194
  useEffect10(() => {
2088
2195
  if (!isAuth) {
2089
2196
  resolvedAppIdRef.current = void 0;
@@ -2103,7 +2210,7 @@ function UnifiedAuthContextProvider({
2103
2210
  resolvedUserIdRef.current = currentUserId;
2104
2211
  const userId = currentUserId;
2105
2212
  const appNameValue = appName;
2106
- import("./api-IHKALJZD.js").then(async ({ resolveAppContext, setupRBAC }) => {
2213
+ import("./api-N774RPUA.js").then(async ({ resolveAppContext, setupRBAC }) => {
2107
2214
  try {
2108
2215
  setupRBAC(supabase);
2109
2216
  const result = await resolveAppContext({
@@ -2113,10 +2220,6 @@ function UnifiedAuthContextProvider({
2113
2220
  if (result?.appId) {
2114
2221
  resolvedAppIdRef.current = result.appId;
2115
2222
  setAppId(result.appId);
2116
- logger.debug("UnifiedAuthProvider", "appId resolved on login", {
2117
- appId: result.appId,
2118
- appName: appNameValue
2119
- });
2120
2223
  } else {
2121
2224
  resolvedUserIdRef.current = void 0;
2122
2225
  }
@@ -2137,8 +2240,59 @@ function UnifiedAuthContextProvider({
2137
2240
  });
2138
2241
  }
2139
2242
  }, [isAuth, currentUser?.id, supabase, appName]);
2243
+ useEffect10(() => {
2244
+ if (appConfigProp !== void 0) {
2245
+ setAppConfigState(appConfigProp);
2246
+ resolvedAppConfigRef.current = appConfigProp;
2247
+ return;
2248
+ }
2249
+ if (resolvedAppConfigRef.current !== null || isResolvingAppConfigRef.current) {
2250
+ return;
2251
+ }
2252
+ if (!supabase || !appName) {
2253
+ return;
2254
+ }
2255
+ isResolvingAppConfigRef.current = true;
2256
+ import("./api-N774RPUA.js").then(async ({ getAppConfigByName: getAppConfigByName2 }) => {
2257
+ try {
2258
+ const config = await getAppConfigByName2(appName);
2259
+ const resolvedConfig = config || { requires_event: false };
2260
+ if (resolvedAppConfigRef.current?.requires_event !== resolvedConfig.requires_event) {
2261
+ resolvedAppConfigRef.current = resolvedConfig;
2262
+ setAppConfigState(resolvedConfig);
2263
+ }
2264
+ if (import.meta.env.DEV && appName === "MINT") {
2265
+ logger.debug("UnifiedAuthProvider", "App config loaded", {
2266
+ appName,
2267
+ config: resolvedConfig,
2268
+ requiresEvent: resolvedConfig.requires_event
2269
+ });
2270
+ }
2271
+ } catch (error) {
2272
+ logger.warn("UnifiedAuthProvider", "Failed to load app config, defaulting to organisation-based", {
2273
+ error: error instanceof Error ? error.message : String(error),
2274
+ appName
2275
+ });
2276
+ if (resolvedAppConfigRef.current?.requires_event !== false) {
2277
+ const defaultConfig = { requires_event: false };
2278
+ resolvedAppConfigRef.current = defaultConfig;
2279
+ setAppConfigState(defaultConfig);
2280
+ }
2281
+ } finally {
2282
+ isResolvingAppConfigRef.current = false;
2283
+ }
2284
+ }).catch((importError) => {
2285
+ logger.error("UnifiedAuthProvider", "Failed to import RBAC API for app config", importError);
2286
+ isResolvingAppConfigRef.current = false;
2287
+ if (resolvedAppConfigRef.current?.requires_event !== false) {
2288
+ const defaultConfig = { requires_event: false };
2289
+ resolvedAppConfigRef.current = defaultConfig;
2290
+ setAppConfigState(defaultConfig);
2291
+ }
2292
+ });
2293
+ }, [supabase, appName, appConfigProp]);
2140
2294
  const [, forceUpdate] = useReducer5((x) => x + 1, 0);
2141
- const forceUpdateTimeoutRef = useRef4(null);
2295
+ const forceUpdateTimeoutRef = useRef8(null);
2142
2296
  const debouncedForceUpdate = useCallback(() => {
2143
2297
  if (forceUpdateTimeoutRef.current) {
2144
2298
  clearTimeout(forceUpdateTimeoutRef.current);
@@ -2146,12 +2300,12 @@ function UnifiedAuthContextProvider({
2146
2300
  forceUpdateTimeoutRef.current = setTimeout(() => {
2147
2301
  forceUpdate();
2148
2302
  forceUpdateTimeoutRef.current = null;
2149
- }, 0);
2303
+ }, 100);
2150
2304
  }, [forceUpdate]);
2151
- const authServiceRef = useRef4(authService);
2152
- const organisationServiceRef = useRef4(organisationService);
2153
- const eventServiceRef = useRef4(eventService);
2154
- const inactivityServiceRef = useRef4(inactivityService);
2305
+ const authServiceRef = useRef8(authService);
2306
+ const organisationServiceRef = useRef8(organisationService);
2307
+ const eventServiceRef = useRef8(eventService);
2308
+ const inactivityServiceRef = useRef8(inactivityService);
2155
2309
  useEffect10(() => {
2156
2310
  authServiceRef.current = authService;
2157
2311
  organisationServiceRef.current = organisationService;
@@ -2177,16 +2331,48 @@ function UnifiedAuthContextProvider({
2177
2331
  const orgLoading = organisationService.isLoading();
2178
2332
  const eventLoading = eventService.isLoading();
2179
2333
  const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;
2180
- const totalLoading = restorationLoading || authLoading || orgLoading || eventLoading;
2334
+ const shouldIncludeOrgLoading = appName !== "ADMIN" && appName !== "PORTAL";
2335
+ const totalLoading = restorationLoading || authLoading || (shouldIncludeOrgLoading ? orgLoading : false) || eventLoading;
2181
2336
  const authError = authService.getError();
2182
2337
  const rawSelectedOrganisation = organisationService.getSelectedOrganisation();
2183
- const organisations = organisationService.getOrganisations();
2184
- const userMemberships = organisationService.getUserMemberships();
2185
2338
  const organisationError = organisationService.getError();
2186
- const selectedOrganisation = appConfig?.requires_event ? null : rawSelectedOrganisation;
2339
+ const selectedOrganisation = appConfig !== null && appConfig?.requires_event === true && !rawSelectedOrganisation ? null : rawSelectedOrganisation;
2340
+ useEffect10(() => {
2341
+ if (import.meta.env.DEV && appName === "MINT") {
2342
+ logger.debug("UnifiedAuthProvider", "Organisation state check", {
2343
+ rawSelectedOrganisation: rawSelectedOrganisation?.id || null,
2344
+ rawSelectedOrganisationType: typeof rawSelectedOrganisation,
2345
+ appConfig,
2346
+ appConfigRequiresEvent: appConfig?.requires_event,
2347
+ selectedOrganisation: selectedOrganisation?.id || null,
2348
+ selectedOrganisationId: selectedOrganisation?.id || null,
2349
+ checkResult: appConfig?.requires_event === true
2350
+ });
2351
+ }
2352
+ }, [appName, rawSelectedOrganisation?.id, appConfig?.requires_event, selectedOrganisation?.id]);
2187
2353
  const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();
2188
2354
  const isContextReady = organisationService.isContextReady();
2189
- const events = eventService.getEvents();
2355
+ const rawEvents = eventService.getEvents();
2356
+ const rawOrganisations = organisationService.getOrganisations();
2357
+ const rawUserMemberships = organisationService.getUserMemberships();
2358
+ const events = useMemo6(() => {
2359
+ return rawEvents;
2360
+ }, [
2361
+ // Create dependency string from event IDs - only changes when events actually change
2362
+ rawEvents.map((e) => e.event_id || e.id).join(",")
2363
+ ]);
2364
+ const organisations = useMemo6(() => {
2365
+ return rawOrganisations;
2366
+ }, [
2367
+ // Create dependency string from organisation IDs - only changes when orgs actually change
2368
+ rawOrganisations.map((o) => o.id).join(",")
2369
+ ]);
2370
+ const userMemberships = useMemo6(() => {
2371
+ return rawUserMemberships;
2372
+ }, [
2373
+ // Create dependency string from membership IDs - only changes when memberships actually change
2374
+ rawUserMemberships.map((m) => `${m.organisation_id}-${m.user_id}`).join(",")
2375
+ ]);
2190
2376
  const selectedEvent = eventService.getSelectedEvent();
2191
2377
  const eventError = eventService.getError();
2192
2378
  const showInactivityWarning = inactivityService.getShowInactivityWarning();
@@ -2195,29 +2381,44 @@ function UnifiedAuthContextProvider({
2195
2381
  const timeRemaining = inactivityService.getTimeRemaining();
2196
2382
  const showWarning = inactivityService.isWarningShown();
2197
2383
  const isTracking = inactivityService.isTracking();
2384
+ const inactivityState = useMemo6(() => ({
2385
+ showInactivityWarning,
2386
+ inactivityTimeRemaining,
2387
+ isIdle,
2388
+ timeRemaining,
2389
+ showWarning,
2390
+ isTracking
2391
+ }), [
2392
+ showInactivityWarning,
2393
+ inactivityTimeRemaining,
2394
+ isIdle,
2395
+ timeRemaining,
2396
+ showWarning,
2397
+ isTracking
2398
+ ]);
2198
2399
  const hasErrors = !!(authError || organisationError || eventError || sessionRestoration.restorationError);
2199
- const signIn = useCallback((email, password) => authService.signIn(email, password), [authService]);
2200
- const signUp = useCallback((email, password) => authService.signUp(email, password), [authService]);
2201
- const signOut = useCallback(() => authService.signOut(), [authService]);
2202
- const resetPassword = useCallback((email) => authService.resetPassword(email), [authService]);
2203
- const updatePassword = useCallback((password) => authService.updatePassword(password), [authService]);
2204
- const refreshSession = useCallback(() => authService.refreshSession(), [authService]);
2205
- const switchOrganisation = useCallback((orgId) => organisationService.switchOrganisation(orgId), [organisationService]);
2206
- const getUserRole = useCallback((orgId) => organisationService.getUserRole(orgId), [organisationService]);
2207
- const validateOrganisationAccess = useCallback((orgId) => organisationService.validateOrganisationAccess(orgId), [organisationService]);
2208
- const refreshOrganisations = useCallback(() => organisationService.refreshOrganisations(), [organisationService]);
2209
- const ensureOrganisationContext = useCallback(() => organisationService.ensureOrganisationContext(), [organisationService]);
2210
- const isOrganisationSecure = useCallback(() => organisationService.isOrganisationSecure(), [organisationService]);
2211
- const getPrimaryOrganisation = useCallback(() => organisationService.getPrimaryOrganisation(), [organisationService]);
2212
- const setSelectedEvent = useCallback((event) => eventService.setSelectedEvent(event), [eventService]);
2213
- const refreshEvents = useCallback(() => eventService.refreshEvents(), [eventService]);
2214
- const resetActivity = useCallback(() => inactivityService.resetActivity(), [inactivityService]);
2215
- const startTracking = useCallback(() => inactivityService.startTracking(), [inactivityService]);
2216
- const stopTracking = useCallback(() => inactivityService.stopTracking(), [inactivityService]);
2217
- const handleIdleLogout = useCallback(() => inactivityService.handleIdleLogout(), [inactivityService]);
2218
- const handleStaySignedIn = useCallback(() => inactivityService.handleStaySignedIn(), [inactivityService]);
2219
- const handleSignOutNow = useCallback(() => inactivityService.handleSignOutNow(), [inactivityService]);
2220
- const prevStateRef = useRef4(null);
2400
+ const signIn = (email, password) => authService.signIn(email, password);
2401
+ const signUp = (email, password) => authService.signUp(email, password);
2402
+ const signOut = () => authService.signOut();
2403
+ const resetPassword = (email) => authService.resetPassword(email);
2404
+ const updatePassword = (password) => authService.updatePassword(password);
2405
+ const refreshSession = () => authService.refreshSession();
2406
+ const switchOrganisation = (orgId) => organisationService.switchOrganisation(orgId);
2407
+ const getUserRole = (orgId) => organisationService.getUserRole(orgId);
2408
+ const validateOrganisationAccess = (orgId) => organisationService.validateOrganisationAccess(orgId);
2409
+ const refreshOrganisations = () => organisationService.refreshOrganisations();
2410
+ const ensureOrganisationContext = () => organisationService.ensureOrganisationContext();
2411
+ const isOrganisationSecure = () => organisationService.isOrganisationSecure();
2412
+ const getPrimaryOrganisation = () => organisationService.getPrimaryOrganisation();
2413
+ const setSelectedEvent = (event) => eventService.setSelectedEvent(event);
2414
+ const refreshEvents = () => eventService.refreshEvents();
2415
+ const resetActivity = () => inactivityService.resetActivity();
2416
+ const startTracking = () => inactivityService.startTracking();
2417
+ const stopTracking = () => inactivityService.stopTracking();
2418
+ const handleIdleLogout = () => inactivityService.handleIdleLogout();
2419
+ const handleStaySignedIn = () => inactivityService.handleStaySignedIn();
2420
+ const handleSignOutNow = () => inactivityService.handleSignOutNow();
2421
+ const prevStateRef = useRef8(null);
2221
2422
  const isDev = import.meta.env.DEV || import.meta.env.MODE === "development";
2222
2423
  if (isDev) {
2223
2424
  const currentState = {
@@ -2248,6 +2449,7 @@ function UnifiedAuthContextProvider({
2248
2449
  refreshSession,
2249
2450
  // Organisation state
2250
2451
  selectedOrganisation,
2452
+ selectedOrganisationId: selectedOrganisation?.id || null,
2251
2453
  organisations,
2252
2454
  userMemberships,
2253
2455
  organisationLoading: orgLoading,
@@ -2265,18 +2467,19 @@ function UnifiedAuthContextProvider({
2265
2467
  // Event state
2266
2468
  events,
2267
2469
  selectedEvent,
2470
+ selectedEventId: selectedEvent?.event_id || null,
2268
2471
  eventLoading,
2269
2472
  eventError,
2270
2473
  // Event methods
2271
2474
  setSelectedEvent,
2272
2475
  refreshEvents,
2273
2476
  // Inactivity state
2274
- showInactivityWarning,
2275
- inactivityTimeRemaining,
2276
- isIdle,
2277
- timeRemaining,
2278
- showWarning,
2279
- isTracking,
2477
+ showInactivityWarning: inactivityState.showInactivityWarning,
2478
+ inactivityTimeRemaining: inactivityState.inactivityTimeRemaining,
2479
+ isIdle: inactivityState.isIdle,
2480
+ timeRemaining: inactivityState.timeRemaining,
2481
+ showWarning: inactivityState.showWarning,
2482
+ isTracking: inactivityState.isTracking,
2280
2483
  // Inactivity methods
2281
2484
  resetActivity,
2282
2485
  startTracking,
@@ -2315,12 +2518,8 @@ function UnifiedAuthContextProvider({
2315
2518
  selectedEvent,
2316
2519
  eventLoading,
2317
2520
  eventError,
2318
- showInactivityWarning,
2319
- inactivityTimeRemaining,
2320
- isIdle,
2321
- timeRemaining,
2322
- showWarning,
2323
- isTracking,
2521
+ inactivityState,
2522
+ // Use memoized object instead of individual values
2324
2523
  totalLoading,
2325
2524
  hasErrors,
2326
2525
  appName,
@@ -2363,7 +2562,7 @@ function EventServiceProviderWrapper({
2363
2562
  appConfig
2364
2563
  }) {
2365
2564
  const { selectedOrganisation: rawSelectedOrganisation } = useOrganisations();
2366
- const selectedOrganisation = appConfig?.requires_event ? null : rawSelectedOrganisation;
2565
+ const selectedOrganisation = appConfig !== null && appConfig?.requires_event === true && !rawSelectedOrganisation ? null : rawSelectedOrganisation;
2367
2566
  const setSelectedEventId = useCallback(() => {
2368
2567
  }, []);
2369
2568
  return /* @__PURE__ */ jsx5(
@@ -2459,7 +2658,7 @@ function UnifiedAuthProvider({
2459
2658
  renderInactivityWarning,
2460
2659
  dangerouslyDisableInactivity = false
2461
2660
  }) {
2462
- const clientRef = useRef4(supabaseClient);
2661
+ const clientRef = useRef8(supabaseClient);
2463
2662
  useEffect10(() => {
2464
2663
  if (clientRef.current !== supabaseClient) {
2465
2664
  logger.warn("UnifiedAuthProvider", "Supabase client reference changed - this may indicate multiple client instances are being created", {
@@ -2508,4 +2707,4 @@ export {
2508
2707
  useUnifiedAuth,
2509
2708
  UnifiedAuthProvider
2510
2709
  };
2511
- //# sourceMappingURL=chunk-6LTQQAT6.js.map
2710
+ //# sourceMappingURL=chunk-BYFSK72L.js.map