@jmruthers/pace-core 0.5.189 → 0.5.190

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 (420) hide show
  1. package/core-usage-manifest.json +0 -4
  2. package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
  3. package/dist/{DataTable-GUFUNZ3N.js → DataTable-ON3IXISJ.js} +8 -8
  4. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-C4uxosp6.d.ts} +83 -24
  5. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  6. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-X5NXANVI.js} +4 -2
  7. package/dist/{api-YP7XD5L6.js → api-I6UCQ5S6.js} +4 -2
  8. package/dist/{chunk-DDM4CCYT.js → chunk-4QYC5L4K.js} +60 -35
  9. package/dist/chunk-4QYC5L4K.js.map +1 -0
  10. package/dist/{chunk-IM4QE42D.js → chunk-73HSNNOQ.js} +141 -326
  11. package/dist/chunk-73HSNNOQ.js.map +1 -0
  12. package/dist/{chunk-YHCN776L.js → chunk-DZWK57KZ.js} +2 -75
  13. package/dist/chunk-DZWK57KZ.js.map +1 -0
  14. package/dist/{chunk-3GOZZZYH.js → chunk-HQVPB5MZ.js} +238 -301
  15. package/dist/chunk-HQVPB5MZ.js.map +1 -0
  16. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  17. package/dist/chunk-HW3OVDUF.js.map +1 -0
  18. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  19. package/dist/chunk-I7PSE6JW.js.map +1 -0
  20. package/dist/{chunk-VGZZXKBR.js → chunk-J2XXC7R5.js} +280 -52
  21. package/dist/chunk-J2XXC7R5.js.map +1 -0
  22. package/dist/{chunk-UCQSRW7Z.js → chunk-NIU6J6OX.js} +425 -378
  23. package/dist/chunk-NIU6J6OX.js.map +1 -0
  24. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  25. package/dist/{chunk-HEHYGYOX.js → chunk-RUYZKXOD.js} +401 -46
  26. package/dist/chunk-RUYZKXOD.js.map +1 -0
  27. package/dist/{chunk-2UUZZJFT.js → chunk-SDMHPX3X.js} +176 -160
  28. package/dist/{chunk-2UUZZJFT.js.map → chunk-SDMHPX3X.js.map} +1 -1
  29. package/dist/{chunk-MX64ZF6I.js → chunk-STYK4OH2.js} +11 -11
  30. package/dist/chunk-STYK4OH2.js.map +1 -0
  31. package/dist/{chunk-YGPFYGA6.js → chunk-VVBAW5A5.js} +822 -498
  32. package/dist/chunk-VVBAW5A5.js.map +1 -0
  33. package/dist/chunk-Y4BUBBHD.js +614 -0
  34. package/dist/chunk-Y4BUBBHD.js.map +1 -0
  35. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  36. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  37. package/dist/components.d.ts +3 -4
  38. package/dist/components.js +19 -19
  39. package/dist/components.js.map +1 -1
  40. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  41. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  42. package/dist/hooks.d.ts +10 -5
  43. package/dist/hooks.js +14 -8
  44. package/dist/hooks.js.map +1 -1
  45. package/dist/index.d.ts +13 -11
  46. package/dist/index.js +79 -69
  47. package/dist/index.js.map +1 -1
  48. package/dist/providers.d.ts +3 -3
  49. package/dist/providers.js +3 -1
  50. package/dist/rbac/index.d.ts +76 -12
  51. package/dist/rbac/index.js +12 -9
  52. package/dist/types.d.ts +1 -1
  53. package/dist/types.js +1 -1
  54. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-DxIDS4bC.d.ts} +16 -9
  55. package/dist/utils.js +16 -16
  56. package/docs/README.md +2 -2
  57. package/docs/api/classes/ColumnFactory.md +1 -1
  58. package/docs/api/classes/ErrorBoundary.md +1 -1
  59. package/docs/api/classes/InvalidScopeError.md +2 -2
  60. package/docs/api/classes/Logger.md +1 -1
  61. package/docs/api/classes/MissingUserContextError.md +2 -2
  62. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  63. package/docs/api/classes/PermissionDeniedError.md +1 -1
  64. package/docs/api/classes/RBACAuditManager.md +1 -1
  65. package/docs/api/classes/RBACCache.md +1 -1
  66. package/docs/api/classes/RBACEngine.md +4 -4
  67. package/docs/api/classes/RBACError.md +1 -1
  68. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  69. package/docs/api/classes/SecureSupabaseClient.md +21 -16
  70. package/docs/api/classes/StorageUtils.md +7 -4
  71. package/docs/api/enums/FileCategory.md +1 -1
  72. package/docs/api/enums/LogLevel.md +1 -1
  73. package/docs/api/enums/RBACErrorCode.md +1 -1
  74. package/docs/api/enums/RPCFunction.md +1 -1
  75. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  76. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  77. package/docs/api/interfaces/AggregateConfig.md +1 -1
  78. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  79. package/docs/api/interfaces/AvatarProps.md +1 -1
  80. package/docs/api/interfaces/BadgeProps.md +1 -1
  81. package/docs/api/interfaces/ButtonProps.md +1 -1
  82. package/docs/api/interfaces/CalendarProps.md +20 -6
  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/ComplianceResult.md +1 -1
  87. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  88. package/docs/api/interfaces/DataRecord.md +1 -1
  89. package/docs/api/interfaces/DataTableAction.md +1 -1
  90. package/docs/api/interfaces/DataTableColumn.md +1 -1
  91. package/docs/api/interfaces/DataTableProps.md +1 -1
  92. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  93. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  94. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  95. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  96. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  97. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  98. package/docs/api/interfaces/ExportColumn.md +1 -1
  99. package/docs/api/interfaces/ExportOptions.md +1 -1
  100. package/docs/api/interfaces/FileDisplayProps.md +62 -16
  101. package/docs/api/interfaces/FileMetadata.md +1 -1
  102. package/docs/api/interfaces/FileReference.md +2 -2
  103. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  104. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  105. package/docs/api/interfaces/FileUploadProps.md +30 -19
  106. package/docs/api/interfaces/FooterProps.md +1 -1
  107. package/docs/api/interfaces/FormFieldProps.md +1 -1
  108. package/docs/api/interfaces/FormProps.md +1 -1
  109. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  110. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  111. package/docs/api/interfaces/InputProps.md +1 -1
  112. package/docs/api/interfaces/LabelProps.md +1 -1
  113. package/docs/api/interfaces/LoggerConfig.md +1 -1
  114. package/docs/api/interfaces/LoginFormProps.md +1 -1
  115. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  116. package/docs/api/interfaces/NavigationContextType.md +9 -9
  117. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  118. package/docs/api/interfaces/NavigationItem.md +1 -1
  119. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  120. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  121. package/docs/api/interfaces/Organisation.md +1 -1
  122. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  123. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  124. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  125. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  126. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  127. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  128. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  129. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  130. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  131. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  132. package/docs/api/interfaces/PaletteData.md +1 -1
  133. package/docs/api/interfaces/ParsedAddress.md +1 -1
  134. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  135. package/docs/api/interfaces/ProgressProps.md +3 -11
  136. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  137. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  138. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  139. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  140. package/docs/api/interfaces/QuickFix.md +1 -1
  141. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  142. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  143. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  144. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  145. package/docs/api/interfaces/RBACConfig.md +1 -1
  146. package/docs/api/interfaces/RBACContext.md +1 -1
  147. package/docs/api/interfaces/RBACLogger.md +1 -1
  148. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  149. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  150. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  151. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  152. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  153. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  154. package/docs/api/interfaces/RBACResult.md +1 -1
  155. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  156. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  157. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  158. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  160. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  161. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  162. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  163. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  164. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  165. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  166. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  167. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  168. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  169. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  170. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  171. package/docs/api/interfaces/RouteConfig.md +10 -10
  172. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  173. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  174. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  175. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  176. package/docs/api/interfaces/SetupIssue.md +1 -1
  177. package/docs/api/interfaces/StorageConfig.md +4 -4
  178. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  179. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  180. package/docs/api/interfaces/StorageListOptions.md +22 -9
  181. package/docs/api/interfaces/StorageListResult.md +4 -4
  182. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  183. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  184. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  185. package/docs/api/interfaces/StyleImport.md +1 -1
  186. package/docs/api/interfaces/SwitchProps.md +1 -1
  187. package/docs/api/interfaces/TabsContentProps.md +1 -1
  188. package/docs/api/interfaces/TabsListProps.md +1 -1
  189. package/docs/api/interfaces/TabsProps.md +1 -1
  190. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  191. package/docs/api/interfaces/TextareaProps.md +1 -1
  192. package/docs/api/interfaces/ToastActionElement.md +1 -1
  193. package/docs/api/interfaces/ToastProps.md +1 -1
  194. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  195. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  196. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  197. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  198. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  199. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  200. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  201. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  202. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  203. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  205. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  207. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  208. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  209. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  210. package/docs/api/interfaces/UserEventAccess.md +11 -11
  211. package/docs/api/interfaces/UserMenuProps.md +1 -1
  212. package/docs/api/interfaces/UserProfile.md +1 -1
  213. package/docs/api/modules.md +151 -92
  214. package/docs/api-reference/components.md +15 -7
  215. package/docs/api-reference/providers.md +2 -2
  216. package/docs/api-reference/rpc-functions.md +1 -0
  217. package/docs/best-practices/README.md +1 -1
  218. package/docs/best-practices/deployment.md +8 -8
  219. package/docs/getting-started/examples/README.md +2 -2
  220. package/docs/getting-started/installation-guide.md +4 -4
  221. package/docs/getting-started/quick-start.md +3 -3
  222. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  223. package/docs/rbac/compliance/compliance-guide.md +2 -2
  224. package/docs/rbac/event-based-apps.md +2 -2
  225. package/docs/rbac/getting-started.md +2 -2
  226. package/docs/rbac/quick-start.md +2 -2
  227. package/docs/security/README.md +4 -4
  228. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  229. package/docs/troubleshooting/README.md +2 -2
  230. package/docs/troubleshooting/migration.md +3 -3
  231. package/package.json +1 -3
  232. package/scripts/check-pace-core-compliance.cjs +1 -1
  233. package/scripts/check-pace-core-compliance.js +1 -1
  234. package/src/__tests__/fixtures/supabase.ts +301 -0
  235. package/src/__tests__/public-recipe-view.test.ts +9 -9
  236. package/src/__tests__/rls-policies.test.ts +197 -61
  237. package/src/components/AddressField/AddressField.test.tsx +42 -0
  238. package/src/components/AddressField/AddressField.tsx +71 -60
  239. package/src/components/AddressField/README.md +1 -0
  240. package/src/components/Alert/Alert.test.tsx +50 -10
  241. package/src/components/Alert/Alert.tsx +5 -3
  242. package/src/components/Avatar/Avatar.test.tsx +95 -43
  243. package/src/components/Avatar/Avatar.tsx +16 -16
  244. package/src/components/Button/Button.test.tsx +2 -1
  245. package/src/components/Button/Button.tsx +3 -3
  246. package/src/components/Calendar/Calendar.test.tsx +53 -37
  247. package/src/components/Calendar/Calendar.tsx +409 -82
  248. package/src/components/Card/Card.test.tsx +7 -4
  249. package/src/components/Card/Card.tsx +3 -6
  250. package/src/components/Checkbox/Checkbox.tsx +2 -2
  251. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  252. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  253. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  254. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  255. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  256. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  257. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  258. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  259. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  260. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  261. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  262. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  263. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  264. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  265. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  266. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  267. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  268. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  269. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  270. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  271. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  272. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  273. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  274. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  275. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  276. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  277. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  278. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  280. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  281. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  282. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  283. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  284. package/src/components/Dialog/Dialog.tsx +2 -2
  285. package/src/components/EventSelector/EventSelector.tsx +7 -7
  286. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  287. package/src/components/FileUpload/FileUpload.tsx +7 -4
  288. package/src/components/Header/Header.test.tsx +28 -0
  289. package/src/components/Header/Header.tsx +22 -9
  290. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  291. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  292. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  293. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  294. package/src/components/OrganisationSelector/OrganisationSelector.tsx +8 -8
  295. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  296. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  297. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  298. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  299. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  300. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  301. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  302. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  303. package/src/components/Progress/Progress.test.tsx +18 -19
  304. package/src/components/Progress/Progress.tsx +31 -32
  305. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  306. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  307. package/src/components/Select/Select.tsx +5 -5
  308. package/src/components/Switch/Switch.test.tsx +2 -1
  309. package/src/components/Switch/Switch.tsx +1 -1
  310. package/src/components/Toast/Toast.tsx +1 -1
  311. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  312. package/src/components/UserMenu/UserMenu.tsx +3 -3
  313. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  314. package/src/eslint-rules/pace-core-compliance.js +0 -2
  315. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  316. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  317. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  318. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  319. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  320. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  321. package/src/hooks/__tests__/{usePublicEvent.unit.test.ts → usePublicEvent.test.ts} +28 -1
  322. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  323. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +58 -16
  324. package/src/hooks/index.ts +1 -1
  325. package/src/hooks/public/usePublicEvent.ts +2 -2
  326. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  327. package/src/hooks/useAppConfig.ts +24 -5
  328. package/src/hooks/useFileDisplay.ts +297 -34
  329. package/src/hooks/useFileReference.ts +56 -11
  330. package/src/hooks/useFileUrl.ts +1 -1
  331. package/src/hooks/useInactivityTracker.ts +16 -7
  332. package/src/hooks/usePermissionCache.test.ts +85 -8
  333. package/src/hooks/useQueryCache.ts +21 -0
  334. package/src/hooks/useSecureDataAccess.test.ts +80 -35
  335. package/src/hooks/useSecureDataAccess.ts +80 -37
  336. package/src/providers/services/EventServiceProvider.tsx +37 -17
  337. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  338. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  339. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  340. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  341. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  342. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  343. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  344. package/src/rbac/api.ts +240 -36
  345. package/src/rbac/cache-invalidation.ts +21 -7
  346. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  347. package/src/rbac/components/NavigationGuard.tsx +23 -63
  348. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  349. package/src/rbac/components/NavigationProvider.tsx +13 -11
  350. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  351. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  352. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  353. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  354. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  355. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  356. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  357. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  358. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  359. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  360. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  361. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  362. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  363. package/src/rbac/engine.ts +4 -2
  364. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  365. package/src/rbac/hooks/index.ts +3 -0
  366. package/src/rbac/hooks/useCan.test.ts +101 -53
  367. package/src/rbac/hooks/usePermissions.ts +108 -41
  368. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  369. package/src/rbac/hooks/useRBAC.ts +83 -40
  370. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  371. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  372. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  373. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  374. package/src/rbac/request-deduplication.ts +1 -1
  375. package/src/rbac/secureClient.ts +72 -12
  376. package/src/rbac/security.ts +29 -23
  377. package/src/rbac/types.ts +10 -0
  378. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  379. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  380. package/src/rbac/utils/__tests__/eventContext.test.ts +6 -1
  381. package/src/rbac/utils/contextValidator.ts +288 -0
  382. package/src/rbac/utils/eventContext.ts +48 -2
  383. package/src/services/EventService.ts +165 -21
  384. package/src/services/OrganisationService.ts +37 -2
  385. package/src/services/__tests__/EventService.test.ts +26 -21
  386. package/src/types/file-reference.ts +13 -10
  387. package/src/utils/app/appNameResolver.test.ts +346 -73
  388. package/src/utils/context/superAdminOverride.ts +58 -0
  389. package/src/utils/file-reference/index.ts +61 -33
  390. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  391. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  392. package/src/utils/storage/helpers.test.ts +1 -1
  393. package/src/utils/storage/helpers.ts +38 -19
  394. package/src/utils/storage/types.ts +15 -8
  395. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  396. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  397. package/src/vite-env.d.ts +2 -2
  398. package/dist/chunk-3GOZZZYH.js.map +0 -1
  399. package/dist/chunk-DDM4CCYT.js.map +0 -1
  400. package/dist/chunk-E7UAOUMY.js +0 -75
  401. package/dist/chunk-E7UAOUMY.js.map +0 -1
  402. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  403. package/dist/chunk-HEHYGYOX.js.map +0 -1
  404. package/dist/chunk-IM4QE42D.js.map +0 -1
  405. package/dist/chunk-MX64ZF6I.js.map +0 -1
  406. package/dist/chunk-SAUPYVLF.js.map +0 -1
  407. package/dist/chunk-THRPYOFK.js.map +0 -1
  408. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  409. package/dist/chunk-VGZZXKBR.js.map +0 -1
  410. package/dist/chunk-YGPFYGA6.js.map +0 -1
  411. package/dist/chunk-YHCN776L.js.map +0 -1
  412. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  413. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  414. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -703
  415. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  416. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -428
  417. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-ON3IXISJ.js.map} +0 -0
  418. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-X5NXANVI.js.map} +0 -0
  419. /package/dist/{api-YP7XD5L6.js.map → api-I6UCQ5S6.js.map} +0 -0
  420. /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
@@ -1,23 +1,25 @@
1
1
  import {
2
- createScopeFromEvent,
3
2
  scopeEqual,
4
3
  useAccessLevel,
5
4
  useCan,
6
5
  useMultiplePermissions
7
- } from "./chunk-3GOZZZYH.js";
6
+ } from "./chunk-HQVPB5MZ.js";
7
+ import {
8
+ useSecureDataAccess
9
+ } from "./chunk-4QYC5L4K.js";
10
+ import {
11
+ useResolvedScope
12
+ } from "./chunk-Y4BUBBHD.js";
13
+ import {
14
+ useUnifiedAuth
15
+ } from "./chunk-J2XXC7R5.js";
8
16
  import {
9
17
  RBACCache,
10
18
  RBACNotInitializedError,
11
19
  getRBACConfig,
12
20
  getRBACLogger,
13
21
  rbacCache
14
- } from "./chunk-HEHYGYOX.js";
15
- import {
16
- useSecureDataAccess
17
- } from "./chunk-DDM4CCYT.js";
18
- import {
19
- useUnifiedAuth
20
- } from "./chunk-VGZZXKBR.js";
22
+ } from "./chunk-RUYZKXOD.js";
21
23
  import {
22
24
  createLogger,
23
25
  logger
@@ -74,17 +76,15 @@ function PagePermissionProvider({
74
76
  onStrictModeViolation,
75
77
  maxHistorySize = 1e3
76
78
  }) {
77
- const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
79
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
78
80
  const [pageAccessHistory, setPageAccessHistory] = useState([]);
79
81
  const [isEnabled, setIsEnabled] = useState(true);
80
- const currentScope = useMemo(() => {
81
- if (!selectedOrganisation) return null;
82
- return {
83
- organisationId: selectedOrganisation.id,
84
- eventId: selectedEvent?.event_id || void 0,
85
- appId: void 0
86
- };
87
- }, [selectedOrganisation, selectedEvent]);
82
+ const { resolvedScope } = useResolvedScope({
83
+ supabase,
84
+ selectedOrganisationId: selectedOrganisation?.id || null,
85
+ selectedEventId: selectedEvent?.event_id || null
86
+ });
87
+ const currentScope = resolvedScope;
88
88
  const hasPagePermission = useCallback((pageName, operation, pageId, scope) => {
89
89
  if (!isEnabled) return true;
90
90
  if (!user?.id) return false;
@@ -175,156 +175,28 @@ var PagePermissionGuardComponent = ({
175
175
  const renderCountRef = useRef(0);
176
176
  renderCountRef.current += 1;
177
177
  const instanceId = useMemo2(() => Math.random().toString(36).substr(2, 9), []);
178
- const { user, selectedOrganisation, selectedEvent, supabase, appId: contextAppId } = useUnifiedAuth();
178
+ const { user, selectedOrganisation, selectedEvent, supabase, appId: contextAppId, appName } = useUnifiedAuth();
179
179
  const [hasChecked, setHasChecked] = useState2(false);
180
- const [checkError, setCheckError] = useState2(null);
181
- const [resolvedScope, setResolvedScope] = useState2(null);
182
- const scopeResolutionAbortRef = useRef(null);
183
- const supabaseRef = useRef(supabase);
184
- supabaseRef.current = supabase;
185
- useEffect2(() => {
186
- const abortController = new AbortController();
187
- scopeResolutionAbortRef.current?.abort();
188
- scopeResolutionAbortRef.current = abortController;
189
- const { signal } = abortController;
190
- const safeSetResolvedScope = (value) => {
191
- if (!signal.aborted) {
192
- setResolvedScope(value);
193
- }
194
- };
195
- const safeSetCheckError = (value) => {
196
- if (!signal.aborted) {
197
- setCheckError(value);
198
- }
199
- };
200
- const resolveScope = async () => {
201
- if (signal.aborted) {
202
- return;
203
- }
204
- if (scope) {
205
- safeSetResolvedScope(scope);
206
- safeSetCheckError(null);
207
- return;
208
- }
209
- const appId = contextAppId;
210
- if (signal.aborted) {
211
- return;
212
- }
213
- if (selectedOrganisation && selectedEvent) {
214
- if (!appId) {
215
- const logger3 = getRBACLogger();
216
- if (import.meta.env.MODE === "test") {
217
- logger3.warn("App ID not resolved in test environment, proceeding without it");
218
- } else {
219
- logger3.error("CRITICAL: App ID not resolved. Check console for details.");
220
- safeSetCheckError(new Error("App ID not resolved. Check console for database errors."));
221
- safeSetResolvedScope(null);
222
- return;
223
- }
224
- }
225
- if (import.meta.env.MODE === "production" && appId) {
226
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
227
- if (!uuidRegex.test(appId)) {
228
- const logger3 = getRBACLogger();
229
- logger3.error("CRITICAL: App ID is not a valid UUID:", appId);
230
- safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
231
- safeSetResolvedScope(null);
232
- return;
233
- }
234
- }
235
- const resolvedContext = {
236
- organisationId: selectedOrganisation.id,
237
- eventId: selectedEvent.event_id,
238
- appId
239
- };
240
- safeSetResolvedScope(resolvedContext);
241
- safeSetCheckError(null);
242
- return;
243
- }
244
- if (signal.aborted) {
245
- return;
246
- }
247
- if (selectedOrganisation) {
248
- if (!appId) {
249
- const logger3 = getRBACLogger();
250
- if (import.meta.env.MODE === "test") {
251
- logger3.warn("App ID not resolved in test environment, proceeding without it");
252
- } else {
253
- logger3.error("CRITICAL: App ID not resolved. Check console for details.");
254
- safeSetCheckError(new Error("App ID not resolved. Check console for database errors."));
255
- safeSetResolvedScope(null);
256
- return;
257
- }
258
- }
259
- if (import.meta.env.MODE === "production" && appId) {
260
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
261
- if (!uuidRegex.test(appId)) {
262
- const logger3 = getRBACLogger();
263
- logger3.error("CRITICAL: App ID is not a valid UUID:", appId);
264
- safeSetCheckError(new Error(`Invalid app ID format: ${appId}. Expected UUID.`));
265
- safeSetResolvedScope(null);
266
- return;
267
- }
268
- }
269
- const resolvedContext = {
270
- organisationId: selectedOrganisation.id,
271
- eventId: selectedEvent?.event_id || void 0,
272
- appId
273
- };
274
- safeSetResolvedScope(resolvedContext);
275
- safeSetCheckError(null);
276
- return;
277
- }
278
- if (signal.aborted) {
279
- return;
280
- }
281
- if (selectedEvent && supabaseRef.current) {
282
- try {
283
- const eventScope = await createScopeFromEvent(supabaseRef.current, selectedEvent.event_id);
284
- if (signal.aborted) {
285
- return;
286
- }
287
- if (!eventScope) {
288
- safeSetCheckError(new Error("Could not resolve organization from event context"));
289
- safeSetResolvedScope(null);
290
- return;
291
- }
292
- safeSetResolvedScope({
293
- ...eventScope,
294
- appId: appId || eventScope.appId
295
- });
296
- safeSetCheckError(null);
297
- } catch (error2) {
298
- if (signal.aborted) {
299
- return;
300
- }
301
- safeSetCheckError(error2);
302
- safeSetResolvedScope(null);
303
- }
304
- return;
305
- }
306
- if (signal.aborted) {
307
- return;
308
- }
309
- const errorMessage = !selectedOrganisation && !selectedEvent ? "Either organisation context or event context is required for page permission checking" : "Insufficient context for permission checking. Please ensure you are properly authenticated and have selected an organisation or event.";
310
- const logger2 = getRBACLogger();
311
- logger2.error("Context resolution failed:", {
312
- selectedOrganisation: selectedOrganisation ? selectedOrganisation.id : null,
313
- selectedEvent: selectedEvent ? selectedEvent.event_id : null,
314
- appId,
315
- error: errorMessage
316
- });
317
- safeSetCheckError(new Error(errorMessage));
318
- safeSetResolvedScope(null);
319
- };
320
- resolveScope();
321
- return () => {
322
- abortController.abort();
323
- if (scopeResolutionAbortRef.current === abortController) {
324
- scopeResolutionAbortRef.current = null;
325
- }
326
- };
327
- }, [scope, selectedOrganisation, selectedEvent]);
180
+ const { resolvedScope: hookResolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
181
+ supabase,
182
+ selectedOrganisationId: selectedOrganisation?.id || null,
183
+ selectedEventId: selectedEvent?.event_id || null
184
+ });
185
+ const allowsOptionalContexts = appName === "PORTAL" || appName === "ADMIN";
186
+ const effectiveScope = scope || (hookResolvedScope ? {
187
+ ...hookResolvedScope,
188
+ appId: hookResolvedScope.appId || (allowsOptionalContexts ? contextAppId : void 0)
189
+ } : allowsOptionalContexts && contextAppId ? {
190
+ organisationId: void 0,
191
+ eventId: void 0,
192
+ appId: contextAppId
193
+ } : selectedEvent?.event_id ? {
194
+ organisationId: void 0,
195
+ // Will be derived from event
196
+ eventId: selectedEvent.event_id,
197
+ appId: contextAppId || void 0
198
+ } : null);
199
+ const checkError = scopeError;
328
200
  const effectivePageId = useMemo2(() => {
329
201
  return pageId || pageName;
330
202
  }, [pageId, pageName]);
@@ -333,36 +205,52 @@ var PagePermissionGuardComponent = ({
333
205
  }, [operation, pageName]);
334
206
  const prevScopeRef = useRef(null);
335
207
  const stableScope = useMemo2(() => {
336
- const newScope = resolvedScope && resolvedScope.organisationId ? {
337
- organisationId: resolvedScope.organisationId,
338
- appId: resolvedScope.appId || void 0,
339
- eventId: resolvedScope.eventId || void 0
340
- } : { organisationId: void 0, appId: void 0, eventId: void 0 };
208
+ if (allowsOptionalContexts && effectiveScope) {
209
+ const newScope2 = {
210
+ organisationId: effectiveScope.organisationId,
211
+ appId: effectiveScope.appId || contextAppId || void 0,
212
+ eventId: effectiveScope.eventId
213
+ };
214
+ if (scopeEqual(prevScopeRef.current, newScope2)) {
215
+ return prevScopeRef.current;
216
+ }
217
+ prevScopeRef.current = newScope2;
218
+ return newScope2;
219
+ }
220
+ const newScope = effectiveScope && effectiveScope.organisationId ? {
221
+ organisationId: effectiveScope.organisationId,
222
+ appId: effectiveScope.appId || contextAppId || void 0,
223
+ eventId: effectiveScope.eventId || void 0
224
+ } : {
225
+ organisationId: effectiveScope?.organisationId || void 0,
226
+ appId: effectiveScope?.appId || contextAppId || void 0,
227
+ eventId: effectiveScope?.eventId || selectedEvent?.event_id || void 0
228
+ };
341
229
  if (scopeEqual(prevScopeRef.current, newScope)) {
342
230
  return prevScopeRef.current;
343
231
  }
344
232
  prevScopeRef.current = newScope;
345
233
  return newScope;
346
- }, [resolvedScope]);
234
+ }, [effectiveScope, appName, contextAppId, selectedEvent?.event_id]);
347
235
  const { can, isLoading: canIsLoading, error: canError } = useCan(
348
236
  user?.id || "",
349
237
  stableScope,
350
238
  permission,
351
239
  effectivePageId,
352
- true
240
+ true,
353
241
  // Use cache
242
+ appName
243
+ // Pass appName for PORTAL/ADMIN special case
354
244
  );
355
- const isLoading = !resolvedScope || canIsLoading;
245
+ const isLoading = scopeLoading || canIsLoading;
356
246
  const error = checkError || canError;
357
247
  useEffect2(() => {
358
248
  if (!isLoading && !error) {
359
249
  setHasChecked(true);
360
- setCheckError(null);
361
250
  if (!can && onDenied) {
362
251
  onDenied(pageName, operation);
363
252
  }
364
253
  } else if (error) {
365
- setCheckError(error);
366
254
  setHasChecked(true);
367
255
  }
368
256
  }, [can, isLoading, error, pageName, operation, onDenied]);
@@ -373,12 +261,12 @@ var PagePermissionGuardComponent = ({
373
261
  pageName,
374
262
  operation,
375
263
  userId: user?.id,
376
- scope: resolvedScope,
264
+ scope: effectiveScope,
377
265
  allowed: can,
378
266
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
379
267
  });
380
268
  }
381
- }, [auditLog, hasChecked, isLoading, pageName, operation, user?.id, resolvedScope, can]);
269
+ }, [auditLog, hasChecked, isLoading, pageName, operation, user?.id, effectiveScope, can]);
382
270
  useEffect2(() => {
383
271
  if (strictMode && hasChecked && !isLoading && !can) {
384
272
  const logger2 = getRBACLogger();
@@ -388,22 +276,23 @@ var PagePermissionGuardComponent = ({
388
276
  permission: `${operation}:page.${pageName}`,
389
277
  pageId: effectivePageId,
390
278
  userId: user?.id,
391
- scope: resolvedScope,
392
- scopeValid: resolvedScope && resolvedScope.organisationId ? true : false,
279
+ scope: effectiveScope,
280
+ scopeValid: allowsOptionalContexts ? true : effectiveScope !== null,
281
+ // PORTAL/ADMIN allow scope without org/event
393
282
  checkError,
394
283
  canError,
395
284
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
396
285
  });
397
286
  }
398
- }, [strictMode, hasChecked, isLoading, can, pageName, operation, effectivePageId, user?.id, resolvedScope, checkError, canError]);
399
- const hasValidScope = resolvedScope && resolvedScope.organisationId;
287
+ }, [strictMode, hasChecked, isLoading, can, pageName, operation, effectivePageId, user?.id, effectiveScope, allowsOptionalContexts, checkError, canError]);
288
+ const hasValidScopeForPagePermissions = allowsOptionalContexts ? true : effectiveScope !== null;
400
289
  const hasValidUser = user && user.id;
401
290
  const isPermissionCheckComplete = hasChecked && !isLoading;
402
- const shouldShowAccessDenied = isPermissionCheckComplete && hasValidScope && hasValidUser && !checkError && !can;
403
- const shouldShowContent = isPermissionCheckComplete && hasValidScope && hasValidUser && !checkError && can;
404
- const scopeKey = resolvedScope ? `${resolvedScope.organisationId}-${resolvedScope.eventId}-${resolvedScope.appId}` : "no-scope";
291
+ const shouldShowAccessDenied = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError && !can;
292
+ const shouldShowContent = isPermissionCheckComplete && hasValidScopeForPagePermissions && hasValidUser && !checkError && can;
293
+ const scopeKey = effectiveScope ? `${effectiveScope.organisationId}-${effectiveScope.eventId}-${effectiveScope.appId}` : "no-scope";
405
294
  const permissionKey = `${scopeKey}-${can}-${isLoading}-${!!checkError}-${hasChecked}`;
406
- if (isLoading || !hasValidScope || !hasValidUser || !hasChecked) {
295
+ if (isLoading || !hasValidUser || !hasChecked) {
407
296
  return loading || /* @__PURE__ */ jsx2("div", { children: "Checking permissions..." });
408
297
  }
409
298
  if (checkError && !can) {
@@ -434,7 +323,7 @@ function DefaultAccessDenied() {
434
323
  }
435
324
  function DefaultLoading() {
436
325
  return /* @__PURE__ */ jsx2("div", { className: "flex items-center justify-center min-h-[200px] p-8", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
437
- /* @__PURE__ */ jsx2("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-600" }),
326
+ /* @__PURE__ */ jsx2("div", { className: "animate-spin rounded-full size-8 border-b-2 border-main-600" }),
438
327
  /* @__PURE__ */ jsx2("span", { className: "text-sec-600", children: "Checking permissions..." })
439
328
  ] }) });
440
329
  }
@@ -453,18 +342,16 @@ function SecureDataProvider({
453
342
  maxHistorySize = 1e3,
454
343
  enforceRLS = true
455
344
  }) {
456
- const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
345
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
457
346
  const { validateContext } = useSecureDataAccess();
458
347
  const [dataAccessHistory, setDataAccessHistory] = useState3([]);
459
348
  const [isEnabled, setIsEnabled] = useState3(true);
460
- const currentScope = useMemo3(() => {
461
- if (!selectedOrganisation) return null;
462
- return {
463
- organisationId: selectedOrganisation.id,
464
- eventId: selectedEvent?.event_id || void 0,
465
- appId: void 0
466
- };
467
- }, [selectedOrganisation, selectedEvent]);
349
+ const { resolvedScope } = useResolvedScope({
350
+ supabase,
351
+ selectedOrganisationId: selectedOrganisation?.id || null,
352
+ selectedEventId: selectedEvent?.event_id || null
353
+ });
354
+ const currentScope = resolvedScope;
468
355
  const isDataAccessAllowed = useCallback3((table, operation, scope) => {
469
356
  if (!isEnabled) return true;
470
357
  if (!user?.id) return false;
@@ -579,54 +466,22 @@ function PermissionEnforcer({
579
466
  }) {
580
467
  const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
581
468
  const [hasChecked, setHasChecked] = useState4(false);
582
- const [checkError, setCheckError] = useState4(null);
583
- const [resolvedScope, setResolvedScope] = useState4(null);
584
- useEffect4(() => {
585
- const resolveScope = async () => {
586
- if (scope) {
587
- setResolvedScope(scope);
588
- return;
589
- }
590
- if (selectedOrganisation && selectedEvent) {
591
- setResolvedScope({
592
- organisationId: selectedOrganisation.id,
593
- eventId: selectedEvent.event_id,
594
- appId: void 0
595
- });
596
- return;
597
- }
598
- if (selectedOrganisation) {
599
- setResolvedScope({
600
- organisationId: selectedOrganisation.id,
601
- eventId: selectedEvent?.event_id || void 0,
602
- appId: void 0
603
- });
604
- return;
605
- }
606
- if (selectedEvent && supabase) {
607
- try {
608
- const eventScope = await createScopeFromEvent(supabase, selectedEvent.event_id);
609
- if (!eventScope) {
610
- setCheckError(new Error("Could not resolve organization from event context"));
611
- return;
612
- }
613
- setResolvedScope(eventScope);
614
- } catch (error2) {
615
- setCheckError(error2);
616
- }
617
- return;
618
- }
619
- setCheckError(new Error("Either organisation context or event context is required for permission checking"));
620
- };
621
- resolveScope();
622
- }, [scope, selectedOrganisation, selectedEvent, supabase]);
623
- const { results: permissionResults, isLoading, error } = useMultiplePermissions(
469
+ const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
470
+ supabase,
471
+ selectedOrganisationId: selectedOrganisation?.id || null,
472
+ selectedEventId: selectedEvent?.event_id || null
473
+ });
474
+ const effectiveScope = scope || resolvedScope;
475
+ const checkError = scopeError;
476
+ const { results: permissionResults, isLoading: permissionsLoading, error: permissionsError } = useMultiplePermissions(
624
477
  user?.id || "",
625
- resolvedScope || { eventId: selectedEvent?.event_id || void 0 },
478
+ effectiveScope || { eventId: selectedEvent?.event_id || void 0 },
626
479
  permissions,
627
480
  true
628
481
  // Use cache
629
482
  );
483
+ const isLoading = scopeLoading || permissionsLoading;
484
+ const error = checkError || permissionsError;
630
485
  const hasRequiredPermissions = useMemo4(() => {
631
486
  if (permissions.length === 0) return true;
632
487
  if (!permissionResults || Object.keys(permissionResults).length === 0) {
@@ -641,12 +496,10 @@ function PermissionEnforcer({
641
496
  useEffect4(() => {
642
497
  if (!isLoading && !error) {
643
498
  setHasChecked(true);
644
- setCheckError(null);
645
499
  if (!hasRequiredPermissions && onDenied) {
646
500
  onDenied(permissions, operation);
647
501
  }
648
502
  } else if (error) {
649
- setCheckError(error);
650
503
  setHasChecked(true);
651
504
  }
652
505
  }, [hasRequiredPermissions, isLoading, error, permissions, operation, onDenied]);
@@ -656,13 +509,13 @@ function PermissionEnforcer({
656
509
  permissions,
657
510
  operation,
658
511
  userId: user?.id,
659
- scope: resolvedScope,
512
+ scope: effectiveScope,
660
513
  allowed: hasRequiredPermissions,
661
514
  requireAll,
662
515
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
663
516
  });
664
517
  }
665
- }, [auditLog, hasChecked, isLoading, permissions, operation, user?.id, resolvedScope, hasRequiredPermissions, requireAll]);
518
+ }, [auditLog, hasChecked, isLoading, permissions, operation, user?.id, effectiveScope, hasRequiredPermissions, requireAll]);
666
519
  useEffect4(() => {
667
520
  if (strictMode && hasChecked && !isLoading && !hasRequiredPermissions) {
668
521
  const logger2 = getRBACLogger();
@@ -670,12 +523,12 @@ function PermissionEnforcer({
670
523
  permissions,
671
524
  operation,
672
525
  userId: user?.id,
673
- scope: resolvedScope,
526
+ scope: effectiveScope,
674
527
  requireAll,
675
528
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
676
529
  });
677
530
  }
678
- }, [strictMode, hasChecked, isLoading, hasRequiredPermissions, permissions, operation, user?.id, resolvedScope, requireAll]);
531
+ }, [strictMode, hasChecked, isLoading, hasRequiredPermissions, permissions, operation, user?.id, effectiveScope, requireAll]);
679
532
  if (isLoading || !hasChecked) {
680
533
  return /* @__PURE__ */ jsx4(Fragment2, { children: loading });
681
534
  }
@@ -706,7 +559,7 @@ function DefaultAccessDenied2() {
706
559
  }
707
560
  function DefaultLoading2() {
708
561
  return /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center min-h-[200px] p-8", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center space-x-2", children: [
709
- /* @__PURE__ */ jsx4("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-600" }),
562
+ /* @__PURE__ */ jsx4("div", { className: "animate-spin rounded-full size-8 border-b-2 border-main-600" }),
710
563
  /* @__PURE__ */ jsx4("span", { className: "text-sec-600", children: "Checking permissions..." })
711
564
  ] }) });
712
565
  }
@@ -727,19 +580,17 @@ function RoleBasedRouter({
727
580
  maxHistorySize = 1e3,
728
581
  unauthorizedComponent: UnauthorizedComponent = DefaultUnauthorizedComponent
729
582
  }) {
730
- const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
583
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
731
584
  const location = useLocation();
732
585
  const navigate = useNavigate();
733
586
  const [routeAccessHistory, setRouteAccessHistory] = useState5([]);
734
587
  const [currentRoute, setCurrentRoute] = useState5("");
735
- const currentScope = useMemo5(() => {
736
- if (!selectedOrganisation) return null;
737
- return {
738
- organisationId: selectedOrganisation.id,
739
- eventId: selectedEvent?.event_id || void 0,
740
- appId: void 0
741
- };
742
- }, [selectedOrganisation, selectedEvent]);
588
+ const { resolvedScope } = useResolvedScope({
589
+ supabase,
590
+ selectedOrganisationId: selectedOrganisation?.id || null,
591
+ selectedEventId: selectedEvent?.event_id || null
592
+ });
593
+ const currentScope = resolvedScope;
743
594
  const currentRouteConfig = useMemo5(() => {
744
595
  const currentPath = location.pathname;
745
596
  return routes.find((route) => route.path === currentPath) || null;
@@ -846,7 +697,7 @@ function RoleBasedRouter({
846
697
  ]);
847
698
  if (finalLoading && !isPublicRoute) {
848
699
  return /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
849
- /* @__PURE__ */ jsx5("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-600 mx-auto mb-4" }),
700
+ /* @__PURE__ */ jsx5("div", { className: "animate-spin rounded-full size-8 border-b-2 border-main-600 mx-auto mb-4" }),
850
701
  /* @__PURE__ */ jsx5("p", { className: "text-sec-600", children: "Checking permissions..." })
851
702
  ] }) });
852
703
  }
@@ -906,17 +757,15 @@ function NavigationProvider({
906
757
  onStrictModeViolation,
907
758
  maxHistorySize = 1e3
908
759
  }) {
909
- const { user, selectedOrganisation, selectedEvent } = useUnifiedAuth();
760
+ const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
910
761
  const [navigationAccessHistory, setNavigationAccessHistory] = useState6([]);
911
762
  const [isEnabled, setIsEnabled] = useState6(true);
912
- const currentScope = useMemo6(() => {
913
- if (!selectedOrganisation) return null;
914
- return {
915
- organisationId: selectedOrganisation.id,
916
- eventId: selectedEvent?.event_id || void 0,
917
- appId: void 0
918
- };
919
- }, [selectedOrganisation, selectedEvent]);
763
+ const { resolvedScope } = useResolvedScope({
764
+ supabase,
765
+ selectedOrganisationId: selectedOrganisation?.id || null,
766
+ selectedEventId: selectedEvent?.event_id || null
767
+ });
768
+ const currentScope = resolvedScope;
920
769
  const hasNavigationPermission = useCallback6((item) => {
921
770
  if (!isEnabled) return true;
922
771
  if (!user?.id) return false;
@@ -1029,54 +878,22 @@ function NavigationGuard({
1029
878
  }) {
1030
879
  const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
1031
880
  const [hasChecked, setHasChecked] = useState7(false);
1032
- const [checkError, setCheckError] = useState7(null);
1033
- const [resolvedScope, setResolvedScope] = useState7(null);
1034
- useEffect7(() => {
1035
- const resolveScope = async () => {
1036
- if (scope) {
1037
- setResolvedScope(scope);
1038
- return;
1039
- }
1040
- if (selectedOrganisation && selectedEvent) {
1041
- setResolvedScope({
1042
- organisationId: selectedOrganisation.id,
1043
- eventId: selectedEvent.event_id,
1044
- appId: void 0
1045
- });
1046
- return;
1047
- }
1048
- if (selectedOrganisation) {
1049
- setResolvedScope({
1050
- organisationId: selectedOrganisation.id,
1051
- eventId: selectedEvent?.event_id || void 0,
1052
- appId: void 0
1053
- });
1054
- return;
1055
- }
1056
- if (selectedEvent && supabase) {
1057
- try {
1058
- const eventScope = await createScopeFromEvent(supabase, selectedEvent.event_id);
1059
- if (!eventScope) {
1060
- setCheckError(new Error("Could not resolve organization from event context"));
1061
- return;
1062
- }
1063
- setResolvedScope(eventScope);
1064
- } catch (error2) {
1065
- setCheckError(error2);
1066
- }
1067
- return;
1068
- }
1069
- setCheckError(new Error("Either organisation context or event context is required for navigation permission checking"));
1070
- };
1071
- resolveScope();
1072
- }, [scope, selectedOrganisation, selectedEvent, supabase]);
1073
- const { results: permissionResults, isLoading, error } = useMultiplePermissions(
881
+ const { resolvedScope: hookResolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
882
+ supabase,
883
+ selectedOrganisationId: selectedOrganisation?.id || null,
884
+ selectedEventId: selectedEvent?.event_id || null
885
+ });
886
+ const effectiveScope = scope || hookResolvedScope;
887
+ const checkError = scopeError;
888
+ const { results: permissionResults, isLoading: permissionsLoading, error: permissionsError } = useMultiplePermissions(
1074
889
  user?.id || "",
1075
- resolvedScope || { eventId: selectedEvent?.event_id || void 0 },
890
+ effectiveScope || { eventId: selectedEvent?.event_id || void 0 },
1076
891
  navigationItem.permissions || [],
1077
892
  true
1078
893
  // Use cache
1079
894
  );
895
+ const isLoading = scopeLoading || permissionsLoading;
896
+ const error = checkError || permissionsError;
1080
897
  const hasRequiredPermissions = useMemo7(() => {
1081
898
  if (!navigationItem.permissions || navigationItem.permissions.length === 0) return true;
1082
899
  if (requireAll) {
@@ -1088,12 +905,10 @@ function NavigationGuard({
1088
905
  useEffect7(() => {
1089
906
  if (!isLoading && !error) {
1090
907
  setHasChecked(true);
1091
- setCheckError(null);
1092
908
  if (!hasRequiredPermissions && onDenied) {
1093
909
  onDenied(navigationItem);
1094
910
  }
1095
911
  } else if (error) {
1096
- setCheckError(error);
1097
912
  setHasChecked(true);
1098
913
  }
1099
914
  }, [hasRequiredPermissions, isLoading, error, navigationItem, onDenied]);
@@ -1104,13 +919,13 @@ function NavigationGuard({
1104
919
  navigationItem: navigationItem.id,
1105
920
  permissions: navigationItem.permissions,
1106
921
  userId: user?.id,
1107
- scope: resolvedScope,
922
+ scope: effectiveScope,
1108
923
  allowed: hasRequiredPermissions,
1109
924
  requireAll,
1110
925
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1111
926
  });
1112
927
  }
1113
- }, [auditLog, hasChecked, isLoading, navigationItem, user?.id, resolvedScope, hasRequiredPermissions, requireAll]);
928
+ }, [auditLog, hasChecked, isLoading, navigationItem, user?.id, effectiveScope, hasRequiredPermissions, requireAll]);
1114
929
  useEffect7(() => {
1115
930
  if (strictMode && hasChecked && !isLoading && !hasRequiredPermissions) {
1116
931
  const logger2 = getRBACLogger();
@@ -1118,13 +933,13 @@ function NavigationGuard({
1118
933
  navigationItem: navigationItem.id,
1119
934
  permissions: navigationItem.permissions,
1120
935
  userId: user?.id,
1121
- scope: resolvedScope,
936
+ scope: effectiveScope,
1122
937
  requireAll,
1123
938
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1124
939
  });
1125
940
  }
1126
- }, [strictMode, hasChecked, isLoading, hasRequiredPermissions, navigationItem, user?.id, resolvedScope, requireAll]);
1127
- if (isLoading || !resolvedScope || !hasChecked) {
941
+ }, [strictMode, hasChecked, isLoading, hasRequiredPermissions, navigationItem, user?.id, effectiveScope, requireAll]);
942
+ if (isLoading || !effectiveScope || !hasChecked) {
1128
943
  return /* @__PURE__ */ jsx7(Fragment3, { children: loading });
1129
944
  }
1130
945
  if (checkError) {
@@ -1145,7 +960,7 @@ function DefaultAccessDenied3() {
1145
960
  }
1146
961
  function DefaultLoading3() {
1147
962
  return /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center p-2", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center space-x-2", children: [
1148
- /* @__PURE__ */ jsx7("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-main-600" }),
963
+ /* @__PURE__ */ jsx7("div", { className: "animate-spin rounded-full size-4 border-b-2 border-main-600" }),
1149
964
  /* @__PURE__ */ jsx7("span", { className: "text-sm text-sec-600", children: "Checking..." })
1150
965
  ] }) });
1151
966
  }
@@ -1432,7 +1247,7 @@ function withPermissionGuard(config, handler) {
1432
1247
  if (!userId || !organisationId) {
1433
1248
  throw new Error("User context required for permission check");
1434
1249
  }
1435
- const { isPermitted: isPermitted2 } = await import("./api-YP7XD5L6.js");
1250
+ const { isPermitted: isPermitted2 } = await import("./api-I6UCQ5S6.js");
1436
1251
  const hasPermission2 = await isPermitted2({
1437
1252
  userId,
1438
1253
  scope: { organisationId, eventId, appId },
@@ -1455,7 +1270,7 @@ function withAccessLevelGuard(minLevel, handler) {
1455
1270
  if (!userId || !organisationId) {
1456
1271
  throw new Error("User context required for access level check");
1457
1272
  }
1458
- const { getAccessLevel: getAccessLevel2 } = await import("./api-YP7XD5L6.js");
1273
+ const { getAccessLevel: getAccessLevel2 } = await import("./api-I6UCQ5S6.js");
1459
1274
  const accessLevel = await getAccessLevel2({
1460
1275
  userId,
1461
1276
  scope: { organisationId, eventId, appId }
@@ -1480,7 +1295,7 @@ function withRoleGuard(config, handler) {
1480
1295
  throw new Error("User context required for role check");
1481
1296
  }
1482
1297
  if (config.globalRoles && config.globalRoles.length > 0) {
1483
- const { isSuperAdmin } = await import("./api-YP7XD5L6.js");
1298
+ const { isSuperAdmin } = await import("./api-I6UCQ5S6.js");
1484
1299
  const isSuper = await isSuperAdmin(userId);
1485
1300
  if (isSuper) {
1486
1301
  if (organisationId) {
@@ -1506,14 +1321,14 @@ function withRoleGuard(config, handler) {
1506
1321
  }
1507
1322
  }
1508
1323
  if (config.organisationRoles && config.organisationRoles.length > 0) {
1509
- const { isOrganisationAdmin } = await import("./api-YP7XD5L6.js");
1324
+ const { isOrganisationAdmin } = await import("./api-I6UCQ5S6.js");
1510
1325
  const isOrgAdmin = await isOrganisationAdmin(userId, organisationId);
1511
1326
  if (!isOrgAdmin && config.requireAll !== false) {
1512
1327
  throw new Error(`Organisation admin role required`);
1513
1328
  }
1514
1329
  }
1515
1330
  if (config.eventAppRoles && config.eventAppRoles.length > 0 && eventId && appId) {
1516
- const { isEventAdmin } = await import("./api-YP7XD5L6.js");
1331
+ const { isEventAdmin } = await import("./api-I6UCQ5S6.js");
1517
1332
  const isEventAdminUser = await isEventAdmin(userId, { organisationId, eventId, appId });
1518
1333
  if (!isEventAdminUser && config.requireAll !== false) {
1519
1334
  throw new Error(`Event admin role required`);
@@ -1553,7 +1368,7 @@ function createRBACMiddleware(config) {
1553
1368
  );
1554
1369
  if (protectedRoute) {
1555
1370
  try {
1556
- const { isPermitted: isPermitted2 } = await import("./api-YP7XD5L6.js");
1371
+ const { isPermitted: isPermitted2 } = await import("./api-I6UCQ5S6.js");
1557
1372
  const hasPermission2 = await isPermitted2({
1558
1373
  userId,
1559
1374
  scope: { organisationId },
@@ -1580,7 +1395,7 @@ function createRBACExpressMiddleware(config) {
1580
1395
  return res.status(401).json({ error: "User context required" });
1581
1396
  }
1582
1397
  try {
1583
- const { isPermitted: isPermitted2 } = await import("./api-YP7XD5L6.js");
1398
+ const { isPermitted: isPermitted2 } = await import("./api-I6UCQ5S6.js");
1584
1399
  const hasPermission2 = await isPermitted2({
1585
1400
  userId,
1586
1401
  scope: { organisationId, eventId, appId },
@@ -1984,7 +1799,7 @@ export const supabase = createClient(url, key);
1984
1799
  // src/lib/supabase.ts
1985
1800
  export const supabase = createClient(
1986
1801
  import.meta.env.VITE_SUPABASE_URL,
1987
- import.meta.env.VITE_SUPABASE_ANON_KEY
1802
+ import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY
1988
1803
  );
1989
1804
 
1990
1805
  // src/utils/api.ts
@@ -2109,4 +1924,4 @@ export {
2109
1924
  getDirectSupabaseAuthFixes,
2110
1925
  getQuickFixes
2111
1926
  };
2112
- //# sourceMappingURL=chunk-IM4QE42D.js.map
1927
+ //# sourceMappingURL=chunk-73HSNNOQ.js.map