@jmruthers/pace-core 0.5.189 → 0.5.191

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 (438) 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-IVYljGJ6.d.ts → DataTable-Be6dH_dR.d.ts} +1 -1
  4. package/dist/{DataTable-GUFUNZ3N.js → DataTable-WKRZD47S.js} +8 -8
  5. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-ULXC_u6U.d.ts} +84 -25
  6. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  7. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-FTSG5XH7.js} +4 -2
  8. package/dist/{api-YP7XD5L6.js → api-IHKALJZD.js} +4 -2
  9. package/dist/{chunk-VGZZXKBR.js → chunk-6LTQQAT6.js} +351 -157
  10. package/dist/chunk-6LTQQAT6.js.map +1 -0
  11. package/dist/{chunk-MX64ZF6I.js → chunk-6TQDD426.js} +15 -15
  12. package/dist/chunk-6TQDD426.js.map +1 -0
  13. package/dist/{chunk-YHCN776L.js → chunk-G37KK66H.js} +2 -75
  14. package/dist/chunk-G37KK66H.js.map +1 -0
  15. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  16. package/dist/chunk-HW3OVDUF.js.map +1 -0
  17. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  18. package/dist/chunk-I7PSE6JW.js.map +1 -0
  19. package/dist/{chunk-IM4QE42D.js → chunk-LOMZXPSN.js} +141 -326
  20. package/dist/chunk-LOMZXPSN.js.map +1 -0
  21. package/dist/chunk-OETXORNB.js +614 -0
  22. package/dist/chunk-OETXORNB.js.map +1 -0
  23. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  24. package/dist/{chunk-HEHYGYOX.js → chunk-ROXMHMY2.js} +403 -46
  25. package/dist/chunk-ROXMHMY2.js.map +1 -0
  26. package/dist/{chunk-2UUZZJFT.js → chunk-ULHIJK66.js} +228 -177
  27. package/dist/{chunk-2UUZZJFT.js.map → chunk-ULHIJK66.js.map} +1 -1
  28. package/dist/{chunk-YGPFYGA6.js → chunk-VKB2CO4Z.js} +838 -503
  29. package/dist/chunk-VKB2CO4Z.js.map +1 -0
  30. package/dist/{chunk-3GOZZZYH.js → chunk-VRGWKHDB.js} +238 -301
  31. package/dist/chunk-VRGWKHDB.js.map +1 -0
  32. package/dist/{chunk-UCQSRW7Z.js → chunk-XNYQOL3Z.js} +431 -384
  33. package/dist/chunk-XNYQOL3Z.js.map +1 -0
  34. package/dist/{chunk-DDM4CCYT.js → chunk-XYXSXPUK.js} +79 -59
  35. package/dist/chunk-XYXSXPUK.js.map +1 -0
  36. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  37. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  38. package/dist/components.d.ts +5 -6
  39. package/dist/components.js +19 -19
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database.generated-DI89OQeI.d.ts → database.generated-CzIvgcPu.d.ts} +165 -201
  42. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  43. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  44. package/dist/hooks.d.ts +20 -15
  45. package/dist/hooks.js +14 -8
  46. package/dist/hooks.js.map +1 -1
  47. package/dist/index.d.ts +17 -15
  48. package/dist/index.js +86 -81
  49. package/dist/index.js.map +1 -1
  50. package/dist/providers.d.ts +3 -3
  51. package/dist/providers.js +3 -1
  52. package/dist/rbac/index.d.ts +77 -13
  53. package/dist/rbac/index.js +12 -9
  54. package/dist/{types-Bwgl--Xo.d.ts → types-CEpcvwwF.d.ts} +1 -1
  55. package/dist/types.d.ts +3 -3
  56. package/dist/types.js +1 -1
  57. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-TZe0gy-4.d.ts} +17 -10
  58. package/dist/utils.d.ts +8 -8
  59. package/dist/utils.js +16 -16
  60. package/docs/README.md +2 -2
  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 +2 -2
  64. package/docs/api/classes/Logger.md +1 -1
  65. package/docs/api/classes/MissingUserContextError.md +2 -2
  66. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  67. package/docs/api/classes/PermissionDeniedError.md +1 -1
  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 +5 -5
  71. package/docs/api/classes/RBACError.md +1 -1
  72. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  73. package/docs/api/classes/SecureSupabaseClient.md +25 -20
  74. package/docs/api/classes/StorageUtils.md +7 -4
  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 +20 -6
  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 +9 -9
  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 +62 -16
  105. package/docs/api/interfaces/FileMetadata.md +1 -1
  106. package/docs/api/interfaces/FileReference.md +2 -2
  107. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  108. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  109. package/docs/api/interfaces/FileUploadProps.md +30 -19
  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 +10 -10
  120. package/docs/api/interfaces/NavigationContextType.md +9 -9
  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 +7 -7
  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 +8 -8
  133. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  134. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  135. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  136. package/docs/api/interfaces/PaletteData.md +1 -1
  137. package/docs/api/interfaces/ParsedAddress.md +2 -2
  138. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  139. package/docs/api/interfaces/ProgressProps.md +3 -11
  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 +1 -1
  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 +1 -1
  160. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  161. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  162. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  163. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  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 +1 -1
  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 +8 -8
  172. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  173. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  174. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  175. package/docs/api/interfaces/RouteConfig.md +10 -10
  176. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  177. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  178. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  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 +4 -4
  182. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  183. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  184. package/docs/api/interfaces/StorageListOptions.md +22 -9
  185. package/docs/api/interfaces/StorageListResult.md +4 -4
  186. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  187. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  188. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  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 +53 -53
  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 +5 -5
  212. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  213. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  214. package/docs/api/interfaces/UserEventAccess.md +11 -11
  215. package/docs/api/interfaces/UserMenuProps.md +1 -1
  216. package/docs/api/interfaces/UserProfile.md +1 -1
  217. package/docs/api/modules.md +165 -106
  218. package/docs/api-reference/components.md +15 -7
  219. package/docs/api-reference/providers.md +2 -2
  220. package/docs/api-reference/rpc-functions.md +1 -0
  221. package/docs/best-practices/README.md +1 -1
  222. package/docs/best-practices/deployment.md +8 -8
  223. package/docs/getting-started/examples/README.md +2 -2
  224. package/docs/getting-started/installation-guide.md +4 -4
  225. package/docs/getting-started/quick-start.md +3 -3
  226. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  227. package/docs/migration/README.md +18 -0
  228. package/docs/migration/database-changes-december-2025.md +767 -0
  229. package/docs/migration/person-scoped-profiles-migration-guide.md +472 -0
  230. package/docs/rbac/compliance/compliance-guide.md +2 -2
  231. package/docs/rbac/event-based-apps.md +2 -2
  232. package/docs/rbac/getting-started.md +2 -2
  233. package/docs/rbac/quick-start.md +2 -2
  234. package/docs/security/README.md +4 -4
  235. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  236. package/docs/troubleshooting/README.md +2 -2
  237. package/docs/troubleshooting/migration.md +3 -3
  238. package/package.json +1 -3
  239. package/scripts/check-pace-core-compliance.cjs +1 -1
  240. package/scripts/check-pace-core-compliance.js +1 -1
  241. package/src/__tests__/fixtures/supabase.ts +301 -0
  242. package/src/__tests__/public-recipe-view.test.ts +19 -19
  243. package/src/__tests__/rls-policies.test.ts +210 -74
  244. package/src/components/AddressField/AddressField.test.tsx +42 -0
  245. package/src/components/AddressField/AddressField.tsx +71 -60
  246. package/src/components/AddressField/README.md +7 -6
  247. package/src/components/Alert/Alert.test.tsx +50 -10
  248. package/src/components/Alert/Alert.tsx +5 -3
  249. package/src/components/Avatar/Avatar.test.tsx +95 -43
  250. package/src/components/Avatar/Avatar.tsx +16 -16
  251. package/src/components/Button/Button.test.tsx +2 -1
  252. package/src/components/Button/Button.tsx +3 -3
  253. package/src/components/Calendar/Calendar.test.tsx +53 -37
  254. package/src/components/Calendar/Calendar.tsx +409 -82
  255. package/src/components/Card/Card.test.tsx +7 -4
  256. package/src/components/Card/Card.tsx +3 -6
  257. package/src/components/Checkbox/Checkbox.tsx +2 -2
  258. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  259. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  260. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  261. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  262. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  263. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  264. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  265. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  266. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  267. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  268. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  269. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  270. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  271. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  272. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  273. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  274. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  275. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  276. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  277. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  278. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  279. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  280. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  281. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  282. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  284. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  285. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  286. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  287. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  288. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  289. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  290. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  291. package/src/components/Dialog/Dialog.tsx +2 -2
  292. package/src/components/EventSelector/EventSelector.tsx +7 -7
  293. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  294. package/src/components/FileUpload/FileUpload.tsx +7 -4
  295. package/src/components/Header/Header.test.tsx +28 -0
  296. package/src/components/Header/Header.tsx +22 -9
  297. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  298. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  299. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  301. package/src/components/OrganisationSelector/OrganisationSelector.tsx +42 -22
  302. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  303. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  304. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  305. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  306. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  307. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  308. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  309. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  310. package/src/components/Progress/Progress.test.tsx +18 -19
  311. package/src/components/Progress/Progress.tsx +31 -32
  312. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  313. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  314. package/src/components/Select/Select.test.tsx +4 -1
  315. package/src/components/Select/Select.tsx +65 -20
  316. package/src/components/Switch/Switch.test.tsx +2 -1
  317. package/src/components/Switch/Switch.tsx +1 -1
  318. package/src/components/Toast/Toast.tsx +1 -1
  319. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  320. package/src/components/UserMenu/UserMenu.tsx +3 -3
  321. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  322. package/src/eslint-rules/pace-core-compliance.js +0 -2
  323. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  324. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  325. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  326. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  327. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  328. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  329. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -1
  330. package/src/hooks/__tests__/usePublicEvent.test.ts +608 -0
  331. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  332. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +67 -24
  333. package/src/hooks/index.ts +1 -1
  334. package/src/hooks/public/usePublicEvent.ts +10 -10
  335. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  336. package/src/hooks/useAppConfig.ts +24 -5
  337. package/src/hooks/useFileDisplay.ts +298 -36
  338. package/src/hooks/useFileReference.ts +56 -11
  339. package/src/hooks/useFileUrl.ts +1 -1
  340. package/src/hooks/useInactivityTracker.ts +16 -7
  341. package/src/hooks/usePermissionCache.test.ts +85 -8
  342. package/src/hooks/useQueryCache.ts +27 -6
  343. package/src/hooks/useSecureDataAccess.test.ts +87 -42
  344. package/src/hooks/useSecureDataAccess.ts +95 -48
  345. package/src/providers/__tests__/OrganisationProvider.test.tsx +27 -21
  346. package/src/providers/services/EventServiceProvider.tsx +37 -17
  347. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  348. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  349. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  350. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  351. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  352. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  353. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  354. package/src/rbac/api.ts +240 -36
  355. package/src/rbac/cache-invalidation.ts +21 -7
  356. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  357. package/src/rbac/components/NavigationGuard.tsx +23 -63
  358. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  359. package/src/rbac/components/NavigationProvider.tsx +13 -11
  360. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  361. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  362. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  363. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  364. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  365. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  366. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  367. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  368. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  369. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  370. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  371. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  372. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  373. package/src/rbac/engine.ts +4 -2
  374. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  375. package/src/rbac/hooks/index.ts +3 -0
  376. package/src/rbac/hooks/useCan.test.ts +101 -53
  377. package/src/rbac/hooks/usePermissions.ts +108 -41
  378. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  379. package/src/rbac/hooks/useRBAC.ts +83 -40
  380. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  381. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  382. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  383. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  384. package/src/rbac/request-deduplication.ts +1 -1
  385. package/src/rbac/secureClient.ts +72 -12
  386. package/src/rbac/security.ts +29 -23
  387. package/src/rbac/types.ts +10 -0
  388. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  389. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  390. package/src/rbac/utils/__tests__/eventContext.test.ts +8 -3
  391. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +74 -12
  392. package/src/rbac/utils/contextValidator.ts +288 -0
  393. package/src/rbac/utils/eventContext.ts +52 -3
  394. package/src/services/AuthService.ts +37 -8
  395. package/src/services/EventService.ts +165 -21
  396. package/src/services/OrganisationService.ts +125 -137
  397. package/src/services/__tests__/EventService.test.ts +26 -21
  398. package/src/services/__tests__/OrganisationService.pagination.test.ts +34 -8
  399. package/src/services/__tests__/OrganisationService.test.ts +218 -86
  400. package/src/types/database.generated.ts +166 -201
  401. package/src/types/file-reference.ts +13 -10
  402. package/src/types/supabase.ts +2 -2
  403. package/src/utils/__tests__/secureDataAccess.unit.test.ts +3 -2
  404. package/src/utils/app/appNameResolver.test.ts +346 -73
  405. package/src/utils/context/superAdminOverride.ts +58 -0
  406. package/src/utils/file-reference/index.ts +65 -37
  407. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  408. package/src/utils/google-places/googlePlacesUtils.ts +1 -1
  409. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  410. package/src/utils/google-places/types.ts +1 -1
  411. package/src/utils/request-deduplication.ts +4 -4
  412. package/src/utils/security/secureDataAccess.test.ts +1 -1
  413. package/src/utils/security/secureDataAccess.ts +7 -4
  414. package/src/utils/storage/README.md +1 -1
  415. package/src/utils/storage/helpers.test.ts +1 -1
  416. package/src/utils/storage/helpers.ts +38 -19
  417. package/src/utils/storage/types.ts +15 -8
  418. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  419. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  420. package/src/vite-env.d.ts +2 -2
  421. package/dist/chunk-3GOZZZYH.js.map +0 -1
  422. package/dist/chunk-DDM4CCYT.js.map +0 -1
  423. package/dist/chunk-E7UAOUMY.js +0 -75
  424. package/dist/chunk-E7UAOUMY.js.map +0 -1
  425. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  426. package/dist/chunk-HEHYGYOX.js.map +0 -1
  427. package/dist/chunk-IM4QE42D.js.map +0 -1
  428. package/dist/chunk-MX64ZF6I.js.map +0 -1
  429. package/dist/chunk-SAUPYVLF.js.map +0 -1
  430. package/dist/chunk-THRPYOFK.js.map +0 -1
  431. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  432. package/dist/chunk-VGZZXKBR.js.map +0 -1
  433. package/dist/chunk-YGPFYGA6.js.map +0 -1
  434. package/dist/chunk-YHCN776L.js.map +0 -1
  435. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-WKRZD47S.js.map} +0 -0
  436. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-FTSG5XH7.js.map} +0 -0
  437. /package/dist/{api-YP7XD5L6.js.map → api-IHKALJZD.js.map} +0 -0
  438. /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
@@ -1,4 +1,15 @@
1
1
  import {
2
+ useAppConfig,
3
+ useEvents,
4
+ useResolvedScope,
5
+ useSuperAdminBypass
6
+ } from "./chunk-OETXORNB.js";
7
+ import {
8
+ useOrganisations,
9
+ useUnifiedAuth
10
+ } from "./chunk-6LTQQAT6.js";
11
+ import {
12
+ ContextValidator,
2
13
  OrganisationContextRequiredError,
3
14
  getAccessLevel,
4
15
  getPermissionMap,
@@ -7,32 +18,22 @@ import {
7
18
  isPermitted,
8
19
  isPermittedCached,
9
20
  resolveAppContext
10
- } from "./chunk-HEHYGYOX.js";
11
- import {
12
- useEvents,
13
- useOrganisations
14
- } from "./chunk-E7UAOUMY.js";
15
- import {
16
- useUnifiedAuth
17
- } from "./chunk-VGZZXKBR.js";
18
- import {
19
- getCurrentAppName
20
- } from "./chunk-F2IMUDXZ.js";
21
+ } from "./chunk-ROXMHMY2.js";
21
22
  import {
22
- createLogger,
23
23
  logger
24
24
  } from "./chunk-PWLANIRT.js";
25
25
 
26
26
  // src/rbac/secureClient.ts
27
27
  import { createClient } from "@supabase/supabase-js";
28
28
  var SecureSupabaseClient = class _SecureSupabaseClient {
29
- constructor(supabaseUrl, supabaseKey, organisationId, eventId, appId) {
29
+ constructor(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin = false) {
30
30
  this.edgeFunctionClient = null;
31
31
  this.supabaseUrl = supabaseUrl;
32
32
  this.supabaseKey = supabaseKey;
33
33
  this.organisationId = organisationId;
34
34
  this.eventId = eventId;
35
35
  this.appId = appId;
36
+ this.isSuperAdmin = isSuperAdmin;
36
37
  this.supabase = createClient(supabaseUrl, supabaseKey, {
37
38
  global: {
38
39
  headers: {
@@ -53,7 +54,8 @@ var SecureSupabaseClient = class _SecureSupabaseClient {
53
54
  this.supabase.from = (table) => {
54
55
  this.validateContext();
55
56
  const query = originalFrom(table);
56
- return this.injectContext(query);
57
+ query._tableName = table;
58
+ return this.injectContext(query, table);
57
59
  };
58
60
  const originalRpc = this.supabase.rpc.bind(this.supabase);
59
61
  this.supabase.rpc = (fn, args, options) => {
@@ -90,33 +92,60 @@ var SecureSupabaseClient = class _SecureSupabaseClient {
90
92
  /**
91
93
  * Inject organisation context into a query
92
94
  */
93
- injectContext(query) {
95
+ injectContext(query, tableName) {
94
96
  const originalSelect = query.select.bind(query);
95
97
  const originalInsert = query.insert.bind(query);
96
98
  const originalUpdate = query.update.bind(query);
97
99
  const originalDelete = query.delete.bind(query);
98
100
  query.select = (columns) => {
99
101
  const result = originalSelect(columns);
100
- return this.addOrganisationFilter(result);
102
+ return this.addOrganisationFilter(result, tableName);
101
103
  };
102
104
  query.insert = (values) => {
105
+ if (tableName === "rbac_user_profiles") {
106
+ if (this.isSuperAdmin) {
107
+ return originalInsert(values);
108
+ }
109
+ const contextValues2 = Array.isArray(values) ? values.map((v) => ({ ...v, organisation_id: this.organisationId })) : { ...values, organisation_id: this.organisationId };
110
+ return originalInsert(contextValues2);
111
+ }
103
112
  const contextValues = Array.isArray(values) ? values.map((v) => ({ ...v, organisation_id: this.organisationId })) : { ...values, organisation_id: this.organisationId };
104
113
  return originalInsert(contextValues);
105
114
  };
106
115
  query.update = (values) => {
107
116
  const result = originalUpdate(values);
108
- return this.addOrganisationFilter(result);
117
+ return this.addOrganisationFilter(result, tableName);
109
118
  };
110
119
  query.delete = () => {
111
120
  const result = originalDelete();
112
- return this.addOrganisationFilter(result);
121
+ return this.addOrganisationFilter(result, tableName);
113
122
  };
114
123
  return query;
115
124
  }
116
125
  /**
117
126
  * Add organisation filter to a query
127
+ *
128
+ * Defense in depth strategy:
129
+ * - RLS policies are the primary security layer (cannot be bypassed)
130
+ * - Application-level filtering adds an additional layer of protection
131
+ *
132
+ * For rbac_user_profiles:
133
+ * - Super admins: No org filter (see all users) - RLS will allow access
134
+ * - Non-super-admins: Apply org filter as defense in depth - RLS will also filter
135
+ *
136
+ * For other tables:
137
+ * - Always apply org filter unless super admin bypasses it
118
138
  */
119
- addOrganisationFilter(query) {
139
+ addOrganisationFilter(query, tableName) {
140
+ if (tableName === "rbac_user_profiles") {
141
+ if (this.isSuperAdmin) {
142
+ return query;
143
+ }
144
+ return query.eq("organisation_id", this.organisationId);
145
+ }
146
+ if (this.isSuperAdmin) {
147
+ return query.eq("organisation_id", this.organisationId);
148
+ }
120
149
  return query.eq("organisation_id", this.organisationId);
121
150
  }
122
151
  /**
@@ -154,7 +183,8 @@ var SecureSupabaseClient = class _SecureSupabaseClient {
154
183
  this.supabaseKey,
155
184
  updates.organisationId || this.organisationId,
156
185
  updates.eventId !== void 0 ? updates.eventId : this.eventId,
157
- updates.appId !== void 0 ? updates.appId : this.appId
186
+ updates.appId !== void 0 ? updates.appId : this.appId,
187
+ updates.isSuperAdmin !== void 0 ? updates.isSuperAdmin : this.isSuperAdmin
158
188
  );
159
189
  }
160
190
  /**
@@ -172,8 +202,8 @@ var SecureSupabaseClient = class _SecureSupabaseClient {
172
202
  });
173
203
  }
174
204
  };
175
- function createSecureClient(supabaseUrl, supabaseKey, organisationId, eventId, appId) {
176
- return new SecureSupabaseClient(supabaseUrl, supabaseKey, organisationId, eventId, appId);
205
+ function createSecureClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin = false) {
206
+ return new SecureSupabaseClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin);
177
207
  }
178
208
  function fromSupabaseClient(client, organisationId, eventId, appId) {
179
209
  throw new Error("fromSupabaseClient is not supported. Use createSecureClient instead.");
@@ -201,15 +231,16 @@ function useRBAC(pageId) {
201
231
  const {
202
232
  user,
203
233
  session,
234
+ supabase,
204
235
  appName,
205
236
  appConfig,
237
+ appId: contextAppId,
206
238
  selectedOrganisation,
207
239
  isContextReady: orgContextReady,
208
240
  organisationLoading: orgLoading,
209
241
  selectedEvent,
210
242
  eventLoading
211
243
  } = useUnifiedAuth();
212
- const requiresEvent = appConfig?.requires_event ?? (appConfig === null ? true : false);
213
244
  const [globalRole, setGlobalRole] = useState(null);
214
245
  const [organisationRole, setOrganisationRole] = useState(null);
215
246
  const [eventAppRole, setEventAppRole] = useState(null);
@@ -230,59 +261,91 @@ function useRBAC(pageId) {
230
261
  setIsLoading(false);
231
262
  return;
232
263
  }
233
- if (orgLoading || !orgContextReady || !selectedOrganisation?.id) {
264
+ const initialScope = {
265
+ organisationId: appConfig?.requires_event ? selectedEvent?.organisation_id || selectedOrganisation?.id : selectedOrganisation?.id,
266
+ eventId: selectedEvent?.event_id || void 0,
267
+ appId: void 0
268
+ };
269
+ const contextReady = ContextValidator.isContextReady(
270
+ initialScope,
271
+ appConfig,
272
+ appName,
273
+ !!selectedEvent,
274
+ !!selectedOrganisation
275
+ );
276
+ if (appName !== "PORTAL" && appName !== "ADMIN" && !contextReady) {
234
277
  setIsLoading(true);
235
278
  return;
236
279
  }
237
- if (requiresEvent) {
238
- if (eventLoading || !selectedEvent) {
239
- setIsLoading(true);
240
- return;
241
- }
242
- }
243
280
  setIsLoading(true);
244
281
  setError(null);
245
282
  logger2.debug("[useRBAC] Loading RBAC context", {
246
283
  appName,
247
- requiresEvent,
284
+ appConfig,
248
285
  hasSelectedEvent: !!selectedEvent,
249
286
  selectedEventId: selectedEvent?.event_id,
250
287
  organisationId: selectedOrganisation?.id
251
288
  });
252
289
  try {
253
- let appId;
254
- if (appName) {
290
+ let appId = contextAppId;
291
+ if (appName && !appId) {
255
292
  try {
256
293
  const resolved = await resolveAppContext({ userId: user.id, appName });
257
- if (!resolved || !resolved.hasAccess) {
294
+ if (!resolved) {
295
+ if (appName === "PORTAL" || appName === "ADMIN") {
296
+ logger2.debug(`[useRBAC] ${appName} app context not resolved, attempting direct lookup`);
297
+ try {
298
+ const { getAppConfigByName } = await import("./api-IHKALJZD.js");
299
+ const config = await getAppConfigByName(appName);
300
+ logger2.debug(`[useRBAC] ${appName} app - proceeding without appId for page-level permissions`);
301
+ } catch (err) {
302
+ logger2.debug(`[useRBAC] ${appName} app - proceeding without appId for page-level permissions`);
303
+ }
304
+ } else {
305
+ throw new Error(`User does not have access to app "${appName}"`);
306
+ }
307
+ } else if (!resolved.hasAccess && appName !== "PORTAL" && appName !== "ADMIN") {
258
308
  throw new Error(`User does not have access to app "${appName}"`);
309
+ } else {
310
+ appId = resolved.appId;
259
311
  }
260
- appId = resolved.appId;
261
312
  } catch (rpcError) {
262
313
  if (rpcError?.message?.includes("NetworkError") || rpcError?.message?.includes("fetch")) {
263
314
  logger2.warn("[useRBAC] NetworkError resolving app context - may be timing issue, will retry when context is ready", {
264
315
  appName,
265
316
  error: rpcError.message,
266
- requiresEvent,
267
317
  eventLoading,
268
318
  hasSelectedEvent: !!selectedEvent
269
319
  });
270
320
  setIsLoading(false);
271
321
  return;
272
322
  }
273
- throw rpcError;
323
+ if (appName === "PORTAL" || appName === "ADMIN") {
324
+ logger2.debug(`[useRBAC] ${appName} app - allowing access despite app context resolution failure`);
325
+ } else {
326
+ throw rpcError;
327
+ }
274
328
  }
275
329
  }
276
330
  const scope = {
277
- organisationId: selectedOrganisation?.id,
278
- eventId: selectedEvent?.event_id || void 0,
279
- appId
331
+ ...initialScope,
332
+ appId: appId || contextAppId
280
333
  };
281
- setCurrentScope(scope);
334
+ const validation = await ContextValidator.resolveRequiredContext(
335
+ scope,
336
+ appConfig,
337
+ appName,
338
+ supabase || null
339
+ );
340
+ if (!validation.isValid || !validation.resolvedScope) {
341
+ throw validation.error || new Error("Context validation failed");
342
+ }
343
+ const resolvedScope = validation.resolvedScope;
344
+ setCurrentScope(resolvedScope);
282
345
  const [map, roleContext, accessLevel] = await Promise.all([
283
- getPermissionMap({ userId: user.id, scope }),
284
- getRoleContext({ userId: user.id, scope }),
285
- getAccessLevel({ userId: user.id, scope })
346
+ getPermissionMap({ userId: user.id, scope: resolvedScope }, appConfig, appName),
347
+ getRoleContext({ userId: user.id, scope: resolvedScope }, appConfig, appName),
348
+ getAccessLevel({ userId: user.id, scope: resolvedScope }, appConfig, appName)
286
349
  ]);
287
350
  setPermissionMap(map);
288
351
  setGlobalRole(roleContext.globalRole);
@@ -292,8 +355,8 @@ function useRBAC(pageId) {
292
355
  if (permissionCount === 0) {
293
356
  logger2.warn("[useRBAC] RBAC context loaded but returned 0 permissions", {
294
357
  appName,
295
- organisationId: selectedOrganisation.id,
296
- eventId: selectedEvent?.event_id
358
+ organisationId: resolvedScope.organisationId,
359
+ eventId: resolvedScope.eventId
297
360
  });
298
361
  }
299
362
  } catch (err) {
@@ -304,7 +367,7 @@ function useRBAC(pageId) {
304
367
  } finally {
305
368
  setIsLoading(false);
306
369
  }
307
- }, [appName, logger2, resetState, selectedEvent?.event_id, selectedOrganisation?.id, session, user, requiresEvent, eventLoading, appConfig, orgContextReady, orgLoading]);
370
+ }, [appName, logger2, resetState, selectedEvent?.event_id, selectedOrganisation?.id, session, user, eventLoading, appConfig, orgContextReady, orgLoading]);
308
371
  const hasGlobalPermission = useCallback(
309
372
  (permission) => {
310
373
  if (globalRole === "super_admin" || permissionMap["*"]) {
@@ -327,7 +390,7 @@ function useRBAC(pageId) {
327
390
  const canManageEvent = useMemo(() => isSuperAdmin || eventAppRole === "event_admin", [isSuperAdmin, eventAppRole]);
328
391
  useEffect(() => {
329
392
  loadRBACContext();
330
- }, [loadRBACContext, appName, requiresEvent, eventLoading, selectedEvent?.event_id, user, session, selectedOrganisation?.id, orgContextReady, orgLoading]);
393
+ }, [loadRBACContext, appName, appConfig, eventLoading, selectedEvent?.event_id, user, session, selectedOrganisation?.id, orgContextReady, orgLoading]);
331
394
  return {
332
395
  user,
333
396
  globalRole,
@@ -344,176 +407,8 @@ function useRBAC(pageId) {
344
407
  };
345
408
  }
346
409
 
347
- // src/rbac/hooks/useResolvedScope.ts
348
- import { useEffect as useEffect2, useState as useState2, useRef } from "react";
349
-
350
- // src/rbac/utils/eventContext.ts
351
- async function getOrganisationFromEvent(supabase, eventId) {
352
- const { data, error } = await supabase.from("event").select("organisation_id").eq("event_id", eventId).single();
353
- if (error || !data) {
354
- return null;
355
- }
356
- return data.organisation_id;
357
- }
358
- async function createScopeFromEvent(supabase, eventId, appId) {
359
- const organisationId = await getOrganisationFromEvent(supabase, eventId);
360
- if (!organisationId) {
361
- return null;
362
- }
363
- return {
364
- organisationId,
365
- eventId,
366
- appId
367
- };
368
- }
369
-
370
- // src/rbac/hooks/useResolvedScope.ts
371
- var log = createLogger("useResolvedScope");
372
- function useResolvedScope({
373
- supabase,
374
- selectedOrganisationId,
375
- selectedEventId
376
- }) {
377
- const [resolvedScope, setResolvedScope] = useState2(null);
378
- const [isLoading, setIsLoading] = useState2(true);
379
- const [error, setError] = useState2(null);
380
- const stableScopeRef = useRef({
381
- organisationId: "",
382
- appId: "",
383
- eventId: void 0
384
- });
385
- useEffect2(() => {
386
- if (resolvedScope && resolvedScope.organisationId) {
387
- const newScope = {
388
- organisationId: resolvedScope.organisationId,
389
- appId: resolvedScope.appId,
390
- eventId: resolvedScope.eventId
391
- };
392
- if (stableScopeRef.current.organisationId !== newScope.organisationId || stableScopeRef.current.eventId !== newScope.eventId || stableScopeRef.current.appId !== newScope.appId) {
393
- stableScopeRef.current = {
394
- organisationId: newScope.organisationId,
395
- appId: newScope.appId || "",
396
- eventId: newScope.eventId
397
- };
398
- }
399
- } else if (!resolvedScope) {
400
- stableScopeRef.current = { organisationId: "", appId: "", eventId: void 0 };
401
- }
402
- }, [resolvedScope]);
403
- const stableScope = stableScopeRef.current;
404
- useEffect2(() => {
405
- let cancelled = false;
406
- const resolveScope = async () => {
407
- if (!supabase && !selectedOrganisationId && !selectedEventId) {
408
- if (!cancelled) {
409
- setResolvedScope(null);
410
- setIsLoading(false);
411
- setError(null);
412
- }
413
- return;
414
- }
415
- setIsLoading(true);
416
- setError(null);
417
- try {
418
- let appId = void 0;
419
- if (supabase) {
420
- const appName = getCurrentAppName();
421
- if (appName) {
422
- try {
423
- const { data: app, error: error2 } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName).eq("is_active", true).single();
424
- if (error2) {
425
- const { data: inactiveApp } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName).single();
426
- if (inactiveApp) {
427
- log.error(`App "${appName}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
428
- } else {
429
- log.error(`App "${appName}" not found in rbac_apps table`);
430
- }
431
- } else if (app) {
432
- appId = app.id;
433
- }
434
- } catch (error2) {
435
- log.error("Unexpected error resolving app ID:", error2);
436
- }
437
- }
438
- }
439
- if (selectedOrganisationId && selectedEventId) {
440
- if (!cancelled) {
441
- setResolvedScope({
442
- organisationId: selectedOrganisationId,
443
- eventId: selectedEventId,
444
- appId
445
- });
446
- setIsLoading(false);
447
- }
448
- return;
449
- }
450
- if (selectedOrganisationId) {
451
- if (!cancelled) {
452
- setResolvedScope({
453
- organisationId: selectedOrganisationId,
454
- eventId: selectedEventId || void 0,
455
- appId
456
- });
457
- setIsLoading(false);
458
- }
459
- return;
460
- }
461
- if (selectedEventId && supabase) {
462
- try {
463
- const eventScope = await createScopeFromEvent(supabase, selectedEventId, appId);
464
- if (!eventScope) {
465
- log.error("Could not resolve organization from event context");
466
- if (!cancelled) {
467
- setResolvedScope(null);
468
- setError(new Error("Could not resolve organisation from event context"));
469
- setIsLoading(false);
470
- }
471
- return;
472
- }
473
- if (!cancelled) {
474
- setResolvedScope({
475
- ...eventScope,
476
- appId: appId || eventScope.appId
477
- });
478
- setIsLoading(false);
479
- }
480
- } catch (err) {
481
- log.error("Error resolving scope from event:", err);
482
- if (!cancelled) {
483
- setResolvedScope(null);
484
- setError(err);
485
- setIsLoading(false);
486
- }
487
- }
488
- return;
489
- }
490
- log.error("No organisation or event context available");
491
- if (!cancelled) {
492
- setResolvedScope(null);
493
- setError(new Error("No organisation or event context available"));
494
- setIsLoading(false);
495
- }
496
- } catch (err) {
497
- if (!cancelled) {
498
- setError(err);
499
- setIsLoading(false);
500
- }
501
- }
502
- };
503
- resolveScope();
504
- return () => {
505
- cancelled = true;
506
- };
507
- }, [selectedOrganisationId, selectedEventId, supabase]);
508
- return {
509
- resolvedScope: stableScope.organisationId ? stableScope : null,
510
- isLoading,
511
- error
512
- };
513
- }
514
-
515
410
  // src/rbac/hooks/usePermissions.ts
516
- import { useState as useState3, useEffect as useEffect3, useCallback as useCallback2, useMemo as useMemo2, useRef as useRef2 } from "react";
411
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useMemo as useMemo2, useRef } from "react";
517
412
 
518
413
  // src/rbac/utils/deep-equal.ts
519
414
  function scopeEqual(a, b) {
@@ -528,15 +423,15 @@ function scopeEqual(a, b) {
528
423
 
529
424
  // src/rbac/hooks/usePermissions.ts
530
425
  function usePermissions(userId, organisationId, eventId, appId) {
531
- const [permissions, setPermissions] = useState3({});
532
- const [isLoading, setIsLoading] = useState3(true);
533
- const [error, setError] = useState3(null);
534
- const [fetchTrigger, setFetchTrigger] = useState3(0);
535
- const isFetchingRef = useRef2(false);
426
+ const [permissions, setPermissions] = useState2({});
427
+ const [isLoading, setIsLoading] = useState2(true);
428
+ const [error, setError] = useState2(null);
429
+ const [fetchTrigger, setFetchTrigger] = useState2(0);
430
+ const isFetchingRef = useRef(false);
536
431
  const logger2 = getRBACLogger();
537
- const prevValuesRef = useRef2({ userId, organisationId, eventId, appId });
432
+ const prevValuesRef = useRef({ userId, organisationId, eventId, appId });
538
433
  const orgId = organisationId || "";
539
- useEffect3(() => {
434
+ useEffect2(() => {
540
435
  if (!userId) {
541
436
  return;
542
437
  }
@@ -550,19 +445,21 @@ function usePermissions(userId, organisationId, eventId, appId) {
550
445
  if (error?.message === "Organisation context is required for permission checks") {
551
446
  setError(null);
552
447
  }
553
- }, [userId, organisationId, error]);
554
- const paramsChanged = prevValuesRef.current.userId !== userId || prevValuesRef.current.organisationId !== organisationId || prevValuesRef.current.eventId !== eventId || prevValuesRef.current.appId !== appId;
555
- if (paramsChanged) {
556
- if (prevValuesRef.current.appId !== appId) {
557
- logger2.debug("[usePermissions] AppId changed - triggering fetch", {
558
- prevAppId: prevValuesRef.current.appId,
559
- newAppId: appId
560
- });
448
+ }, [userId, organisationId, error, orgId]);
449
+ useEffect2(() => {
450
+ const paramsChanged = prevValuesRef.current.userId !== userId || prevValuesRef.current.organisationId !== organisationId || prevValuesRef.current.eventId !== eventId || prevValuesRef.current.appId !== appId;
451
+ if (paramsChanged) {
452
+ if (prevValuesRef.current.appId !== appId) {
453
+ logger2.debug("[usePermissions] AppId changed - triggering fetch", {
454
+ prevAppId: prevValuesRef.current.appId,
455
+ newAppId: appId
456
+ });
457
+ }
458
+ prevValuesRef.current = { userId, organisationId, eventId, appId };
459
+ setFetchTrigger((prev) => prev + 1);
561
460
  }
562
- prevValuesRef.current = { userId, organisationId, eventId, appId };
563
- setFetchTrigger((prev) => prev + 1);
564
- }
565
- useEffect3(() => {
461
+ }, [userId, organisationId, eventId, appId, logger2]);
462
+ useEffect2(() => {
566
463
  const fetchPermissions = async () => {
567
464
  if (isFetchingRef.current) {
568
465
  return;
@@ -671,16 +568,18 @@ function usePermissions(userId, organisationId, eventId, appId) {
671
568
  refetch
672
569
  }), [permissions, isLoading, error, hasPermission, hasAnyPermission, hasAllPermissions, refetch]);
673
570
  }
674
- function useCan(userId, scope, permission, pageId, useCache = true) {
675
- const [can, setCan] = useState3(false);
676
- const [isLoading, setIsLoading] = useState3(true);
677
- const [error, setError] = useState3(null);
571
+ function useCan(userId, scope, permission, pageId, useCache = true, appName) {
572
+ const [can, setCan] = useState2(false);
573
+ const [isLoading, setIsLoading] = useState2(true);
574
+ const [error, setError] = useState2(null);
678
575
  const isValidScope = scope && typeof scope === "object";
679
576
  const organisationId = isValidScope ? scope.organisationId : void 0;
680
577
  const eventId = isValidScope ? scope.eventId : void 0;
681
578
  const appId = isValidScope ? scope.appId : void 0;
682
- useEffect3(() => {
683
- if (!isValidScope || !organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "") {
579
+ useEffect2(() => {
580
+ const isPagePermission = permission.includes(":page.") || !!pageId;
581
+ const requiresOrgId = !isPagePermission;
582
+ if (requiresOrgId && (!isValidScope || !organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "")) {
684
583
  const timeoutId = setTimeout(() => {
685
584
  setError(new Error("Organisation context is required for permission checks"));
686
585
  setIsLoading(false);
@@ -691,12 +590,12 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
691
590
  if (error?.message === "Organisation context is required for permission checks") {
692
591
  setError(null);
693
592
  }
694
- }, [isValidScope, organisationId, error]);
695
- const lastUserIdRef = useRef2(null);
696
- const lastScopeRef = useRef2(null);
697
- const lastPermissionRef = useRef2(null);
698
- const lastPageIdRef = useRef2(null);
699
- const lastUseCacheRef = useRef2(null);
593
+ }, [isValidScope, organisationId, error, permission, pageId]);
594
+ const lastUserIdRef = useRef(null);
595
+ const lastScopeRef = useRef(null);
596
+ const lastPermissionRef = useRef(null);
597
+ const lastPageIdRef = useRef(null);
598
+ const lastUseCacheRef = useRef(null);
700
599
  const stableScope = useMemo2(() => {
701
600
  if (!isValidScope) {
702
601
  return null;
@@ -707,8 +606,8 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
707
606
  appId
708
607
  };
709
608
  }, [isValidScope, organisationId, eventId, appId]);
710
- const prevScopeRef = useRef2(null);
711
- useEffect3(() => {
609
+ const prevScopeRef = useRef(null);
610
+ useEffect2(() => {
712
611
  const scopeChanged = !scopeEqual(prevScopeRef.current, stableScope);
713
612
  if (lastUserIdRef.current !== userId || scopeChanged || lastPermissionRef.current !== permission || lastPageIdRef.current !== pageId || lastUseCacheRef.current !== useCache) {
714
613
  lastUserIdRef.current = userId;
@@ -728,7 +627,17 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
728
627
  setError(null);
729
628
  return;
730
629
  }
731
- if (!organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "") {
630
+ const isPagePermission = permission.includes(":page.") || !!pageId;
631
+ const requiresOrgId = !isPagePermission;
632
+ const isPageName = pageId && typeof pageId === "string" && !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(pageId);
633
+ const needsAppIdForPageName = isPagePermission && isPageName;
634
+ if (requiresOrgId && (!organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "")) {
635
+ setIsLoading(true);
636
+ setCan(false);
637
+ setError(null);
638
+ return;
639
+ }
640
+ if (needsAppIdForPageName && (!appId || appId === null || typeof appId === "string" && appId.trim() === "")) {
732
641
  setIsLoading(true);
733
642
  setCan(false);
734
643
  setError(null);
@@ -738,11 +647,11 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
738
647
  setIsLoading(true);
739
648
  setError(null);
740
649
  const validScope = {
741
- organisationId,
650
+ ...organisationId ? { organisationId } : {},
742
651
  ...eventId ? { eventId } : {},
743
652
  ...appId ? { appId } : {}
744
653
  };
745
- const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }) : await isPermitted({ userId, scope: validScope, permission, pageId });
654
+ const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, void 0, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, void 0, appName);
746
655
  setCan(result);
747
656
  } catch (err) {
748
657
  const logger2 = getRBACLogger();
@@ -755,7 +664,7 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
755
664
  };
756
665
  checkPermission();
757
666
  }
758
- }, [userId, stableScope, permission, pageId, useCache]);
667
+ }, [userId, stableScope, permission, pageId, useCache, appName]);
759
668
  const refetch = useCallback2(async () => {
760
669
  if (!userId) {
761
670
  setCan(false);
@@ -768,7 +677,9 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
768
677
  setError(null);
769
678
  return;
770
679
  }
771
- if (!organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "") {
680
+ const isPagePermission = permission.includes(":page.") || !!pageId;
681
+ const requiresOrgId = !isPagePermission;
682
+ if (requiresOrgId && (!organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "")) {
772
683
  setCan(false);
773
684
  setIsLoading(true);
774
685
  setError(null);
@@ -778,11 +689,11 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
778
689
  setIsLoading(true);
779
690
  setError(null);
780
691
  const validScope = {
781
- organisationId,
692
+ ...organisationId ? { organisationId } : {},
782
693
  ...eventId ? { eventId } : {},
783
694
  ...appId ? { appId } : {}
784
695
  };
785
- const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }) : await isPermitted({ userId, scope: validScope, permission, pageId });
696
+ const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, void 0, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, void 0, appName);
786
697
  setCan(result);
787
698
  } catch (err) {
788
699
  setError(err instanceof Error ? err : new Error("Failed to check permission"));
@@ -790,7 +701,7 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
790
701
  } finally {
791
702
  setIsLoading(false);
792
703
  }
793
- }, [userId, isValidScope, organisationId, eventId, appId, permission, pageId, useCache]);
704
+ }, [userId, isValidScope, organisationId, eventId, appId, permission, pageId, useCache, appName]);
794
705
  return useMemo2(() => ({
795
706
  can,
796
707
  isLoading,
@@ -799,9 +710,15 @@ function useCan(userId, scope, permission, pageId, useCache = true) {
799
710
  }), [can, isLoading, error, refetch]);
800
711
  }
801
712
  function useAccessLevel(userId, scope) {
802
- const [accessLevel, setAccessLevel] = useState3("viewer");
803
- const [isLoading, setIsLoading] = useState3(true);
804
- const [error, setError] = useState3(null);
713
+ const [accessLevel, setAccessLevel] = useState2("viewer");
714
+ const [isLoading, setIsLoading] = useState2(true);
715
+ const [error, setError] = useState2(null);
716
+ let appName;
717
+ try {
718
+ const { appName: contextAppName } = useAppConfig();
719
+ appName = contextAppName;
720
+ } catch {
721
+ }
805
722
  const fetchAccessLevel = useCallback2(async () => {
806
723
  if (!userId) {
807
724
  setAccessLevel("viewer");
@@ -811,16 +728,31 @@ function useAccessLevel(userId, scope) {
811
728
  try {
812
729
  setIsLoading(true);
813
730
  setError(null);
814
- const level = await getAccessLevel({ userId, scope });
731
+ const { isSuperAdmin: checkSuperAdmin } = await import("./api-IHKALJZD.js");
732
+ const isSuperAdminUser = await checkSuperAdmin(userId);
733
+ if (isSuperAdminUser) {
734
+ setAccessLevel("super");
735
+ setIsLoading(false);
736
+ return;
737
+ }
738
+ if (appName !== "PORTAL" && appName !== "ADMIN" && !scope.organisationId && !scope.eventId) {
739
+ const orgError = new OrganisationContextRequiredError();
740
+ setError(orgError);
741
+ setAccessLevel("viewer");
742
+ setIsLoading(false);
743
+ return;
744
+ }
745
+ const level = await getAccessLevel({ userId, scope }, null, appName);
815
746
  setAccessLevel(level);
816
747
  } catch (err) {
817
- setError(err instanceof Error ? err : new Error("Failed to fetch access level"));
748
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch access level");
749
+ setError(error2);
818
750
  setAccessLevel("viewer");
819
751
  } finally {
820
752
  setIsLoading(false);
821
753
  }
822
- }, [userId, scope.organisationId, scope.eventId, scope.appId]);
823
- useEffect3(() => {
754
+ }, [userId, scope.organisationId, scope.eventId, scope.appId, appName]);
755
+ useEffect2(() => {
824
756
  fetchAccessLevel();
825
757
  }, [fetchAccessLevel]);
826
758
  return useMemo2(() => ({
@@ -831,9 +763,9 @@ function useAccessLevel(userId, scope) {
831
763
  }), [accessLevel, isLoading, error, fetchAccessLevel]);
832
764
  }
833
765
  function useMultiplePermissions(userId, scope, permissions, useCache = true) {
834
- const [results, setResults] = useState3({});
835
- const [isLoading, setIsLoading] = useState3(true);
836
- const [error, setError] = useState3(null);
766
+ const [results, setResults] = useState2({});
767
+ const [isLoading, setIsLoading] = useState2(true);
768
+ const [error, setError] = useState2(null);
837
769
  const checkPermissions = useCallback2(async () => {
838
770
  if (!userId || permissions.length === 0) {
839
771
  setResults({});
@@ -856,7 +788,7 @@ function useMultiplePermissions(userId, scope, permissions, useCache = true) {
856
788
  setIsLoading(false);
857
789
  }
858
790
  }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
859
- useEffect3(() => {
791
+ useEffect2(() => {
860
792
  checkPermissions();
861
793
  }, [checkPermissions]);
862
794
  return useMemo2(() => ({
@@ -867,9 +799,9 @@ function useMultiplePermissions(userId, scope, permissions, useCache = true) {
867
799
  }), [results, isLoading, error, checkPermissions]);
868
800
  }
869
801
  function useHasAnyPermission(userId, scope, permissions, useCache = true) {
870
- const [hasAny, setHasAny] = useState3(false);
871
- const [isLoading, setIsLoading] = useState3(true);
872
- const [error, setError] = useState3(null);
802
+ const [hasAny, setHasAny] = useState2(false);
803
+ const [isLoading, setIsLoading] = useState2(true);
804
+ const [error, setError] = useState2(null);
873
805
  const checkAnyPermission = useCallback2(async () => {
874
806
  if (!userId || permissions.length === 0) {
875
807
  setHasAny(false);
@@ -895,7 +827,7 @@ function useHasAnyPermission(userId, scope, permissions, useCache = true) {
895
827
  setIsLoading(false);
896
828
  }
897
829
  }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
898
- useEffect3(() => {
830
+ useEffect2(() => {
899
831
  checkAnyPermission();
900
832
  }, [checkAnyPermission]);
901
833
  return useMemo2(() => ({
@@ -906,9 +838,9 @@ function useHasAnyPermission(userId, scope, permissions, useCache = true) {
906
838
  }), [hasAny, isLoading, error, checkAnyPermission]);
907
839
  }
908
840
  function useHasAllPermissions(userId, scope, permissions, useCache = true) {
909
- const [hasAll, setHasAll] = useState3(false);
910
- const [isLoading, setIsLoading] = useState3(true);
911
- const [error, setError] = useState3(null);
841
+ const [hasAll, setHasAll] = useState2(false);
842
+ const [isLoading, setIsLoading] = useState2(true);
843
+ const [error, setError] = useState2(null);
912
844
  const checkAllPermissions = useCallback2(async () => {
913
845
  if (!userId || permissions.length === 0) {
914
846
  setHasAll(false);
@@ -934,7 +866,7 @@ function useHasAllPermissions(userId, scope, permissions, useCache = true) {
934
866
  setIsLoading(false);
935
867
  }
936
868
  }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
937
- useEffect3(() => {
869
+ useEffect2(() => {
938
870
  checkAllPermissions();
939
871
  }, [checkAllPermissions]);
940
872
  return useMemo2(() => ({
@@ -945,9 +877,9 @@ function useHasAllPermissions(userId, scope, permissions, useCache = true) {
945
877
  }), [hasAll, isLoading, error, checkAllPermissions]);
946
878
  }
947
879
  function useCachedPermissions(userId, scope) {
948
- const [permissions, setPermissions] = useState3({});
949
- const [isLoading, setIsLoading] = useState3(true);
950
- const [error, setError] = useState3(null);
880
+ const [permissions, setPermissions] = useState2({});
881
+ const [isLoading, setIsLoading] = useState2(true);
882
+ const [error, setError] = useState2(null);
951
883
  const fetchCachedPermissions = useCallback2(async () => {
952
884
  if (!userId) {
953
885
  setPermissions({});
@@ -968,7 +900,7 @@ function useCachedPermissions(userId, scope) {
968
900
  const invalidateCache = useCallback2(() => {
969
901
  fetchCachedPermissions();
970
902
  }, [fetchCachedPermissions]);
971
- useEffect3(() => {
903
+ useEffect2(() => {
972
904
  fetchCachedPermissions();
973
905
  }, [fetchCachedPermissions]);
974
906
  return useMemo2(() => ({
@@ -1095,11 +1027,11 @@ function useResourcePermissions(resource, options = {}) {
1095
1027
  }
1096
1028
 
1097
1029
  // src/rbac/hooks/useRoleManagement.ts
1098
- import { useState as useState4, useCallback as useCallback3 } from "react";
1030
+ import { useState as useState3, useCallback as useCallback3 } from "react";
1099
1031
  function useRoleManagement() {
1100
1032
  const { user, supabase } = useUnifiedAuth();
1101
- const [isLoading, setIsLoading] = useState4(false);
1102
- const [error, setError] = useState4(null);
1033
+ const [isLoading, setIsLoading] = useState3(false);
1034
+ const [error, setError] = useState3(null);
1103
1035
  if (!supabase) {
1104
1036
  throw new Error("useRoleManagement requires a Supabase client. Ensure UnifiedAuthProvider is configured.");
1105
1037
  }
@@ -1369,11 +1301,11 @@ function useRoleManagement() {
1369
1301
  }
1370
1302
 
1371
1303
  // src/rbac/hooks/useSecureSupabase.ts
1372
- import { useMemo as useMemo4, useRef as useRef3 } from "react";
1304
+ import { useMemo as useMemo4, useRef as useRef2 } from "react";
1373
1305
  var secureClientCache = /* @__PURE__ */ new Map();
1374
1306
  var MAX_CACHE_SIZE = 5;
1375
- function getCacheKey(organisationId, eventId, appId) {
1376
- return `${organisationId}-${eventId || "no-event"}-${appId || "no-app"}`;
1307
+ function getCacheKey(organisationId, eventId, appId, isSuperAdmin) {
1308
+ return `${organisationId}-${eventId || "no-event"}-${appId || "no-app"}-${isSuperAdmin ? "super" : "regular"}`;
1377
1309
  }
1378
1310
  function getSupabaseConfig() {
1379
1311
  const getEnvVar = (key) => {
@@ -1386,7 +1318,7 @@ function getSupabaseConfig() {
1386
1318
  return void 0;
1387
1319
  };
1388
1320
  const supabaseUrl = getEnvVar("VITE_SUPABASE_URL") || getEnvVar("NEXT_PUBLIC_SUPABASE_URL") || null;
1389
- const supabaseKey = getEnvVar("VITE_SUPABASE_ANON_KEY") || getEnvVar("NEXT_PUBLIC_SUPABASE_ANON_KEY") || null;
1321
+ const supabaseKey = getEnvVar("VITE_SUPABASE_PUBLISHABLE_KEY") || getEnvVar("NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY") || null;
1390
1322
  if (!supabaseUrl || !supabaseKey) {
1391
1323
  return null;
1392
1324
  }
@@ -1398,12 +1330,15 @@ function useSecureSupabase(baseClient) {
1398
1330
  const eventsContext = useEvents();
1399
1331
  const { selectedEvent } = eventsContext;
1400
1332
  const eventLoading = "eventLoading" in eventsContext ? eventsContext.eventLoading : false;
1333
+ const { isSuperAdmin: verifiedIsSuperAdmin, isLoading: isVerifyingSuperAdmin } = useSuperAdminBypass();
1334
+ const metadataHint = Boolean(user?.app_metadata?.is_super_admin) || Boolean(user?.user_metadata?.is_super_admin);
1335
+ const isSuperAdmin = verifiedIsSuperAdmin || isVerifyingSuperAdmin && metadataHint;
1401
1336
  const { resolvedScope } = useResolvedScope({
1402
1337
  supabase: authSupabase || null,
1403
1338
  selectedOrganisationId: selectedOrganisation?.id || null,
1404
1339
  selectedEventId: selectedEvent?.event_id || null
1405
1340
  });
1406
- const prevContextRef = useRef3({
1341
+ const prevContextRef = useRef2({
1407
1342
  organisationId: void 0,
1408
1343
  eventId: void 0,
1409
1344
  appId: void 0
@@ -1412,12 +1347,12 @@ function useSecureSupabase(baseClient) {
1412
1347
  if (eventLoading) {
1413
1348
  return baseClient || authSupabase || null;
1414
1349
  }
1415
- if (selectedOrganisation?.id && user?.id) {
1416
- const organisationId = selectedOrganisation.id;
1417
- const eventId = selectedEvent?.event_id;
1418
- const appId = resolvedScope?.appId;
1350
+ const organisationId = resolvedScope?.organisationId;
1351
+ const eventId = resolvedScope?.eventId || selectedEvent?.event_id;
1352
+ const appId = resolvedScope?.appId;
1353
+ if (organisationId && user?.id) {
1419
1354
  prevContextRef.current = { organisationId, eventId, appId };
1420
- const cacheKey = getCacheKey(organisationId, eventId, appId);
1355
+ const cacheKey = getCacheKey(organisationId, eventId, appId, isSuperAdmin);
1421
1356
  const cachedClient = secureClientCache.get(cacheKey);
1422
1357
  if (cachedClient) {
1423
1358
  return cachedClient.getClient();
@@ -1425,7 +1360,7 @@ function useSecureSupabase(baseClient) {
1425
1360
  const config = getSupabaseConfig();
1426
1361
  if (!config || !config.url || !config.key) {
1427
1362
  logger.warn("useSecureSupabase", "Missing Supabase environment variables. Falling back to base client.", {
1428
- note: "Ensure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in your environment."
1363
+ note: "Ensure VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY are set in your environment."
1429
1364
  });
1430
1365
  return baseClient || authSupabase || null;
1431
1366
  }
@@ -1436,8 +1371,10 @@ function useSecureSupabase(baseClient) {
1436
1371
  organisationId,
1437
1372
  // organisationId is string, UUID is string alias
1438
1373
  eventId,
1439
- appId
1374
+ appId,
1440
1375
  // appId is string | undefined, UUID is string alias
1376
+ isSuperAdmin
1377
+ // Pass super admin status for conditional filtering
1441
1378
  );
1442
1379
  secureClientCache.set(cacheKey, secureClient);
1443
1380
  if (secureClientCache.size > MAX_CACHE_SIZE) {
@@ -1454,11 +1391,13 @@ function useSecureSupabase(baseClient) {
1454
1391
  }
1455
1392
  return baseClient || authSupabase || null;
1456
1393
  }, [
1457
- selectedOrganisation?.id,
1394
+ resolvedScope?.organisationId,
1395
+ resolvedScope?.eventId,
1396
+ resolvedScope?.appId,
1458
1397
  selectedEvent?.event_id,
1459
1398
  user?.id,
1460
1399
  eventLoading,
1461
- resolvedScope?.appId,
1400
+ isSuperAdmin,
1462
1401
  baseClient,
1463
1402
  authSupabase
1464
1403
  ]);
@@ -1469,8 +1408,6 @@ export {
1469
1408
  createSecureClient,
1470
1409
  fromSupabaseClient,
1471
1410
  useRBAC,
1472
- createScopeFromEvent,
1473
- useResolvedScope,
1474
1411
  scopeEqual,
1475
1412
  usePermissions,
1476
1413
  useCan,
@@ -1483,4 +1420,4 @@ export {
1483
1420
  useRoleManagement,
1484
1421
  useSecureSupabase
1485
1422
  };
1486
- //# sourceMappingURL=chunk-3GOZZZYH.js.map
1423
+ //# sourceMappingURL=chunk-VRGWKHDB.js.map