@jmruthers/pace-core 0.6.5 → 0.6.7

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 (473) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/audit-tool/00-dependencies.cjs +394 -0
  4. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  5. package/audit-tool/audits/02-project-structure.cjs +255 -0
  6. package/audit-tool/audits/03-architecture.cjs +196 -0
  7. package/audit-tool/audits/04-code-quality.cjs +149 -0
  8. package/audit-tool/audits/05-styling.cjs +224 -0
  9. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  10. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  11. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  12. package/audit-tool/audits/09-operations.cjs +208 -0
  13. package/audit-tool/index.cjs +291 -0
  14. package/audit-tool/utils/code-utils.cjs +218 -0
  15. package/audit-tool/utils/file-utils.cjs +230 -0
  16. package/audit-tool/utils/report-utils.cjs +241 -0
  17. package/core-usage-manifest.json +93 -0
  18. package/cursor-rules/00-standards-overview.mdc +156 -0
  19. package/cursor-rules/01-pace-core-compliance.mdc +586 -0
  20. package/cursor-rules/02-project-structure.mdc +42 -4
  21. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
  22. package/cursor-rules/04-code-quality.mdc +419 -0
  23. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
  24. package/cursor-rules/06-security-rbac.mdc +518 -0
  25. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  26. package/cursor-rules/08-testing-documentation.mdc +324 -0
  27. package/cursor-rules/09-operations.mdc +365 -0
  28. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  29. package/dist/DataTable-7PMH7XN7.js +15 -0
  30. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  31. package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
  32. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  33. package/dist/api-Y4MQWOFW.js +4 -0
  34. package/dist/audit-MYQXYZFU.js +3 -0
  35. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  36. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  37. package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
  38. package/dist/chunk-6F3IILHI.js +62 -0
  39. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  40. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  41. package/dist/{chunk-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
  42. package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
  43. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  44. package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
  45. package/dist/chunk-C7NSAPTL.js +1 -0
  46. package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
  47. package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
  48. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  49. package/dist/chunk-GHYHJTYV.js +994 -0
  50. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  51. package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
  52. package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
  53. package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
  54. package/dist/chunk-MBADTM7L.js +64 -0
  55. package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
  56. package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
  57. package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
  58. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  59. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  60. package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
  61. package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
  62. package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
  63. package/dist/components.d.ts +7 -5
  64. package/dist/components.js +46 -257
  65. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  66. package/dist/eslint-rules/index.cjs +35 -0
  67. package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
  68. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  69. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  70. package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
  71. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  72. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  73. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  74. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  75. package/dist/hooks.d.ts +6 -6
  76. package/dist/hooks.js +62 -172
  77. package/dist/icons/index.d.ts +1 -0
  78. package/dist/icons/index.js +1 -0
  79. package/dist/index.d.ts +12 -11
  80. package/dist/index.js +67 -660
  81. package/dist/providers.d.ts +2 -2
  82. package/dist/providers.js +8 -35
  83. package/dist/rbac/eslint-rules.d.ts +46 -44
  84. package/dist/rbac/eslint-rules.js +7 -4
  85. package/dist/rbac/index.d.ts +109 -586
  86. package/dist/rbac/index.js +14 -207
  87. package/dist/styles/index.js +2 -12
  88. package/dist/theming/runtime.d.ts +14 -1
  89. package/dist/theming/runtime.js +3 -19
  90. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  91. package/dist/{types-CkbwOr4Y.d.ts → types-DXstZpNI.d.ts} +4 -17
  92. package/dist/types-t9H8qKRw.d.ts +55 -0
  93. package/dist/types.d.ts +1 -1
  94. package/dist/types.js +7 -94
  95. package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
  96. package/dist/utils.d.ts +24 -117
  97. package/dist/utils.js +54 -392
  98. package/docs/README.md +17 -7
  99. package/docs/api/README.md +4 -402
  100. package/docs/api/modules.md +301 -871
  101. package/docs/api-reference/components.md +21 -21
  102. package/docs/api-reference/deprecated.md +31 -6
  103. package/docs/api-reference/hooks.md +80 -80
  104. package/docs/api-reference/rpc-functions.md +78 -3
  105. package/docs/api-reference/types.md +1 -1
  106. package/docs/api-reference/utilities.md +1 -1
  107. package/docs/architecture/README.md +1 -1
  108. package/docs/core-concepts/events.md +3 -3
  109. package/docs/core-concepts/organisations.md +6 -6
  110. package/docs/core-concepts/permissions.md +6 -6
  111. package/docs/documentation-index.md +12 -18
  112. package/docs/getting-started/cursor-rules.md +3 -23
  113. package/docs/getting-started/dependencies.md +650 -0
  114. package/docs/getting-started/documentation-index.md +1 -1
  115. package/docs/getting-started/examples/README.md +4 -4
  116. package/docs/getting-started/examples/full-featured-app.md +1 -1
  117. package/docs/getting-started/faq.md +2 -2
  118. package/docs/getting-started/installation-guide.md +20 -7
  119. package/docs/getting-started/quick-reference.md +4 -4
  120. package/docs/getting-started/quick-start.md +23 -12
  121. package/docs/implementation-guides/authentication.md +15 -15
  122. package/docs/implementation-guides/component-styling.md +1 -1
  123. package/docs/implementation-guides/data-tables.md +126 -33
  124. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  125. package/docs/implementation-guides/dynamic-colors.md +3 -3
  126. package/docs/implementation-guides/file-upload-storage.md +2 -2
  127. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  128. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  129. package/docs/implementation-guides/large-datasets.md +3 -2
  130. package/docs/implementation-guides/organisation-security.md +2 -2
  131. package/docs/implementation-guides/performance.md +2 -2
  132. package/docs/implementation-guides/permission-enforcement.md +5 -1
  133. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  134. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  135. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  136. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  137. package/docs/rbac/README.md +17 -8
  138. package/docs/rbac/advanced-patterns.md +6 -6
  139. package/docs/rbac/api-reference.md +20 -20
  140. package/docs/rbac/edge-functions-guide.md +376 -0
  141. package/docs/rbac/event-based-apps.md +3 -3
  142. package/docs/rbac/examples.md +41 -41
  143. package/docs/rbac/getting-started.md +37 -37
  144. package/docs/rbac/performance.md +1 -1
  145. package/docs/rbac/quick-start.md +52 -52
  146. package/docs/rbac/secure-client-protection.md +1 -35
  147. package/docs/rbac/troubleshooting.md +1 -1
  148. package/docs/security/README.md +5 -5
  149. package/docs/standards/0-standards-overview.md +220 -0
  150. package/docs/standards/1-pace-core-compliance-standards.md +986 -0
  151. package/docs/standards/2-project-structure-standards.md +949 -0
  152. package/docs/standards/3-architecture-standards.md +606 -0
  153. package/docs/standards/4-code-quality-standards.md +728 -0
  154. package/docs/standards/5-styling-standards.md +348 -0
  155. package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
  156. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  157. package/docs/standards/8-testing-documentation-standards.md +401 -0
  158. package/docs/standards/9-operations-standards.md +1102 -0
  159. package/docs/standards/README.md +185 -57
  160. package/docs/troubleshooting/README.md +4 -4
  161. package/docs/troubleshooting/common-issues.md +2 -2
  162. package/docs/troubleshooting/debugging.md +9 -9
  163. package/docs/troubleshooting/migration.md +4 -4
  164. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  165. package/eslint-config-pace-core.cjs +33 -6
  166. package/package.json +35 -23
  167. package/scripts/install-cursor-rules.cjs +25 -6
  168. package/scripts/install-eslint-config.cjs +284 -0
  169. package/src/__tests__/fixtures/supabase.ts +1 -1
  170. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
  171. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  172. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  173. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  174. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
  175. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  176. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  177. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  178. package/src/__tests__/public-recipe-view.test.ts +38 -9
  179. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  180. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  181. package/src/__tests__/templates/component.test.template.tsx +18 -15
  182. package/src/components/Button/Button.tsx +5 -1
  183. package/src/components/Calendar/Calendar.tsx +201 -47
  184. package/src/components/ContextSelector/ContextSelector.tsx +106 -119
  185. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  186. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  187. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  188. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  189. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  190. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  191. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  192. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  193. package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
  194. package/src/components/DataTable/components/EditFields.tsx +23 -3
  195. package/src/components/DataTable/components/EditableRow.tsx +12 -9
  196. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  197. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  198. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  199. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  200. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  201. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  202. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  203. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  204. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  205. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  206. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  207. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  208. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  209. package/src/components/DataTable/components/index.ts +2 -1
  210. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  212. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  213. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  214. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  215. package/src/components/DataTable/types.ts +5 -18
  216. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  217. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  218. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  219. package/src/components/DateTimeField/DateTimeField.tsx +10 -9
  220. package/src/components/Dialog/Dialog.test.tsx +128 -104
  221. package/src/components/Dialog/Dialog.tsx +742 -24
  222. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  223. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
  224. package/src/components/FileDisplay/FileDisplay.tsx +23 -17
  225. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  226. package/src/components/FileUpload/FileUpload.tsx +112 -130
  227. package/src/components/Form/Form.test.tsx +6 -8
  228. package/src/components/Form/Form.tsx +365 -4
  229. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  230. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  231. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  232. package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
  233. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  234. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  235. package/src/components/Progress/Progress.tsx +2 -4
  236. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  237. package/src/components/Select/Select.tsx +109 -98
  238. package/src/components/Select/types.ts +4 -1
  239. package/src/components/UserMenu/UserMenu.tsx +9 -6
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
  242. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  243. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  244. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  245. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  246. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  247. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  248. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  249. package/src/hooks/public/usePublicEvent.ts +67 -195
  250. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  251. package/src/hooks/public/usePublicEventLogo.ts +24 -14
  252. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  253. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  254. package/src/hooks/useAppConfig.ts +28 -26
  255. package/src/hooks/useEventTheme.test.ts +217 -239
  256. package/src/hooks/useEventTheme.ts +16 -28
  257. package/src/hooks/useFileDisplay.ts +2 -2
  258. package/src/hooks/useOrganisationPermissions.ts +5 -7
  259. package/src/hooks/useQueryCache.ts +0 -1
  260. package/src/hooks/useSessionDraft.ts +380 -0
  261. package/src/hooks/useSessionRestoration.ts +3 -1
  262. package/src/icons/index.ts +27 -0
  263. package/src/index.ts +5 -0
  264. package/src/providers/OrganisationProvider.tsx +23 -14
  265. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  266. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  267. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  268. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  269. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  270. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  271. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  272. package/src/providers/services/EventServiceProvider.tsx +1 -24
  273. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  274. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  275. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
  276. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  277. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  278. package/src/rbac/adapters.tsx +7 -295
  279. package/src/rbac/api.test.ts +44 -56
  280. package/src/rbac/api.ts +10 -17
  281. package/src/rbac/cache-invalidation.ts +0 -1
  282. package/src/rbac/compliance/index.ts +10 -0
  283. package/src/rbac/compliance/pattern-detector.ts +553 -0
  284. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  285. package/src/rbac/components/AccessDenied.tsx +150 -0
  286. package/src/rbac/components/NavigationGuard.tsx +12 -20
  287. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  289. package/src/rbac/components/index.ts +3 -41
  290. package/src/rbac/eslint-rules.js +1 -1
  291. package/src/rbac/hooks/index.ts +0 -3
  292. package/src/rbac/hooks/permissions/index.ts +0 -3
  293. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  294. package/src/rbac/hooks/usePermissions.ts +0 -3
  295. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  296. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  297. package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
  298. package/src/rbac/hooks/useResourcePermissions.ts +139 -48
  299. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  300. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  301. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  302. package/src/rbac/index.ts +7 -9
  303. package/src/rbac/utils/contextValidator.ts +9 -7
  304. package/src/services/AuthService.ts +130 -18
  305. package/src/services/EventService.ts +4 -97
  306. package/src/services/InactivityService.ts +16 -0
  307. package/src/services/OrganisationService.ts +7 -44
  308. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  309. package/src/services/base/BaseService.ts +0 -3
  310. package/src/styles/core.css +7 -0
  311. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  312. package/src/theming/parseEventColours.ts +22 -10
  313. package/src/types/database.generated.ts +4733 -3809
  314. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  315. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  316. package/src/utils/context/organisationContext.test.ts +13 -28
  317. package/src/utils/context/organisationContext.ts +21 -52
  318. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  319. package/src/utils/file-reference/index.ts +39 -15
  320. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  321. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  322. package/src/utils/index.ts +4 -1
  323. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  324. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  325. package/src/utils/persistence/keyDerivation.ts +304 -0
  326. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  327. package/src/utils/security/secureStorage.ts +5 -5
  328. package/src/utils/storage/README.md +1 -1
  329. package/src/utils/storage/helpers.ts +3 -3
  330. package/src/utils/supabase/createBaseClient.ts +147 -0
  331. package/src/utils/timezone/timezone.test.ts +1 -2
  332. package/src/utils/timezone/timezone.ts +1 -1
  333. package/src/utils/validation/csrf.ts +4 -4
  334. package/cursor-rules/00-pace-core-compliance.mdc +0 -331
  335. package/cursor-rules/01-standards-compliance.mdc +0 -244
  336. package/cursor-rules/04-testing-standards.mdc +0 -268
  337. package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
  338. package/cursor-rules/06-code-quality.mdc +0 -309
  339. package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
  340. package/cursor-rules/CHANGELOG.md +0 -119
  341. package/cursor-rules/README.md +0 -192
  342. package/dist/DataTable-AOVNCPTX.js +0 -175
  343. package/dist/DataTable-AOVNCPTX.js.map +0 -1
  344. package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
  345. package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
  346. package/dist/api-O6HTBX5Y.js +0 -52
  347. package/dist/api-O6HTBX5Y.js.map +0 -1
  348. package/dist/audit-V53FV5AG.js +0 -17
  349. package/dist/audit-V53FV5AG.js.map +0 -1
  350. package/dist/chunk-5DRSZLL2.js.map +0 -1
  351. package/dist/chunk-63FOKYGO.js.map +0 -1
  352. package/dist/chunk-6COVEUS7.js.map +0 -1
  353. package/dist/chunk-AFVQODI2.js +0 -263
  354. package/dist/chunk-AFVQODI2.js.map +0 -1
  355. package/dist/chunk-DGUM43GV.js.map +0 -1
  356. package/dist/chunk-E66EQZE6.js.map +0 -1
  357. package/dist/chunk-EFN2EIMK.js.map +0 -1
  358. package/dist/chunk-FFQEQTNW.js.map +0 -1
  359. package/dist/chunk-FMUCXFII.js.map +0 -1
  360. package/dist/chunk-G37KK66H.js.map +0 -1
  361. package/dist/chunk-G7QEZTYQ.js +0 -2053
  362. package/dist/chunk-G7QEZTYQ.js.map +0 -1
  363. package/dist/chunk-HU2C6SSC.js.map +0 -1
  364. package/dist/chunk-IHB5DR3H.js.map +0 -1
  365. package/dist/chunk-IVOFDYWT.js.map +0 -1
  366. package/dist/chunk-J36DSWQK.js.map +0 -1
  367. package/dist/chunk-JGRYX5UX.js.map +0 -1
  368. package/dist/chunk-KQCRWDSA.js +0 -1
  369. package/dist/chunk-KQCRWDSA.js.map +0 -1
  370. package/dist/chunk-L4OXEN46.js.map +0 -1
  371. package/dist/chunk-LMC26NLJ.js +0 -84
  372. package/dist/chunk-LMC26NLJ.js.map +0 -1
  373. package/dist/chunk-M43Y4SSO.js.map +0 -1
  374. package/dist/chunk-M7MPQISP.js.map +0 -1
  375. package/dist/chunk-NTM7ZSB6.js.map +0 -1
  376. package/dist/chunk-PWLANIRT.js.map +0 -1
  377. package/dist/chunk-QXHPKYJV.js.map +0 -1
  378. package/dist/chunk-RGAWHO7N.js.map +0 -1
  379. package/dist/chunk-UPPMRMYG.js.map +0 -1
  380. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  381. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  382. package/dist/components.js.map +0 -1
  383. package/dist/contextValidator-5OGXSPKS.js +0 -9
  384. package/dist/contextValidator-5OGXSPKS.js.map +0 -1
  385. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  386. package/dist/hooks.js.map +0 -1
  387. package/dist/index.js.map +0 -1
  388. package/dist/providers.js.map +0 -1
  389. package/dist/rbac/eslint-rules.js.map +0 -1
  390. package/dist/rbac/index.js.map +0 -1
  391. package/dist/styles/index.js.map +0 -1
  392. package/dist/theming/runtime.js.map +0 -1
  393. package/dist/types.js.map +0 -1
  394. package/dist/utils.js.map +0 -1
  395. package/docs/best-practices/README.md +0 -472
  396. package/docs/best-practices/accessibility.md +0 -601
  397. package/docs/best-practices/common-patterns.md +0 -516
  398. package/docs/best-practices/deployment.md +0 -1103
  399. package/docs/best-practices/performance.md +0 -1328
  400. package/docs/best-practices/security.md +0 -940
  401. package/docs/best-practices/testing.md +0 -1034
  402. package/docs/rbac/compliance/compliance-guide.md +0 -544
  403. package/docs/standards/01-architecture-standard.md +0 -44
  404. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  405. package/docs/standards/03-component-standard.md +0 -32
  406. package/docs/standards/04-code-style-standard.md +0 -32
  407. package/docs/standards/05-security-standard.md +0 -44
  408. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  409. package/docs/standards/pace-core-compliance.md +0 -432
  410. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  411. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  412. package/scripts/audit/core/checks/bundle.cjs +0 -142
  413. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  414. package/scripts/audit/core/checks/config.cjs +0 -54
  415. package/scripts/audit/core/checks/coverage.cjs +0 -84
  416. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  417. package/scripts/audit/core/checks/documentation.cjs +0 -268
  418. package/scripts/audit/core/checks/environment.cjs +0 -116
  419. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  420. package/scripts/audit/core/checks/forms.cjs +0 -172
  421. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  422. package/scripts/audit/core/checks/hooks.cjs +0 -334
  423. package/scripts/audit/core/checks/imports.cjs +0 -244
  424. package/scripts/audit/core/checks/performance.cjs +0 -325
  425. package/scripts/audit/core/checks/routes.cjs +0 -117
  426. package/scripts/audit/core/checks/state.cjs +0 -130
  427. package/scripts/audit/core/checks/structure.cjs +0 -65
  428. package/scripts/audit/core/checks/style.cjs +0 -584
  429. package/scripts/audit/core/checks/testing.cjs +0 -122
  430. package/scripts/audit/core/checks/typescript.cjs +0 -61
  431. package/scripts/audit/core/scanner.cjs +0 -199
  432. package/scripts/audit/core/utils.cjs +0 -137
  433. package/scripts/audit/index.cjs +0 -223
  434. package/scripts/audit/reporters/console.cjs +0 -151
  435. package/scripts/audit/reporters/json.cjs +0 -54
  436. package/scripts/audit/reporters/markdown.cjs +0 -124
  437. package/scripts/audit-consuming-app.cjs +0 -86
  438. package/src/components/DataTable/components/DataTableBody.tsx +0 -454
  439. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  440. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  441. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  442. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  443. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  444. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  445. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  446. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  447. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  448. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  449. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  450. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  451. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  452. package/src/components/DataTable/utils/debugTools.ts +0 -514
  453. package/src/eslint-rules/pace-core-compliance.js +0 -638
  454. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  455. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  456. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  457. package/src/rbac/components/NavigationProvider.tsx +0 -345
  458. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  459. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  460. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  461. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  462. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  463. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  464. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  465. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  466. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  467. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  468. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  469. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  470. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  471. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  472. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  473. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -1,33 +1,172 @@
1
- import {
2
- useAppConfig,
3
- useEvents,
4
- useOrganisationSecurity
5
- } from "./chunk-NTM7ZSB6.js";
6
- import {
7
- useOrganisations,
8
- useUnifiedAuth
9
- } from "./chunk-IHB5DR3H.js";
10
- import {
11
- getAccessLevel,
12
- getPageScopeType,
13
- getPermissionMap,
14
- getRBACLogger,
15
- getRoleContext,
16
- isPermitted,
17
- isPermittedCached,
18
- resolveAppContext
19
- } from "./chunk-EFN2EIMK.js";
20
- import {
21
- ContextValidator,
22
- OrganisationContextRequiredError
23
- } from "./chunk-AFVQODI2.js";
24
- import {
25
- getCurrentAppName
26
- } from "./chunk-M7MPQISP.js";
27
- import {
28
- createLogger,
29
- logger
30
- } from "./chunk-PWLANIRT.js";
1
+ import { useAppConfig, useOrganisationSecurity } from './chunk-VBCS3DUA.js';
2
+ import { useEventService, useUnifiedAuth, useOrganisations } from './chunk-FTCRZOG2.js';
3
+ import { OrganisationContextRequiredError, getRBACLogger, resolveAppContext, getPageScopeType, ContextValidator, getPermissionMap, getRoleContext, getAccessLevel, isPermittedCached, isPermitted, isSuperAdmin } from './chunk-ZFYPMX46.js';
4
+ import { getCurrentAppName } from './chunk-OJ4SKRSV.js';
5
+ import { cn } from './chunk-7ILTDCL2.js';
6
+ import { createLogger, logger } from './chunk-TTRFSOKR.js';
7
+ import * as React2 from 'react';
8
+ import { useRef, useMemo, useState, useCallback, useEffect } from 'react';
9
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
10
+ import { jsx, jsxs } from 'react/jsx-runtime';
11
+ import { Slot } from '@radix-ui/react-slot';
12
+ import { createClient } from '@supabase/supabase-js';
13
+
14
+ function useEvents() {
15
+ const eventService = useEventService();
16
+ const rawEvents = eventService.getEvents();
17
+ const selectedEvent = eventService.getSelectedEvent();
18
+ const isLoading = eventService.isLoading();
19
+ const error = eventService.getError();
20
+ const prevEventsRef = useRef([]);
21
+ const prevEventsIdsRef = useRef("");
22
+ const currentEventsIds = rawEvents.map((e) => e.event_id || e.id).join(",");
23
+ const eventsChanged = currentEventsIds !== prevEventsIdsRef.current;
24
+ if (eventsChanged) {
25
+ prevEventsRef.current = rawEvents;
26
+ prevEventsIdsRef.current = currentEventsIds;
27
+ }
28
+ const events = useMemo(() => {
29
+ return prevEventsRef.current;
30
+ }, [currentEventsIds]);
31
+ const setSelectedEventCallback = useMemo(
32
+ () => (event) => eventService.setSelectedEvent(event),
33
+ [eventService]
34
+ );
35
+ const refreshEventsCallback = useMemo(
36
+ () => () => eventService.refreshEvents(),
37
+ [eventService]
38
+ );
39
+ const clearEventSelectionCallback = useMemo(
40
+ () => () => eventService.clearEventSelection(),
41
+ [eventService]
42
+ );
43
+ return useMemo(() => ({
44
+ events,
45
+ selectedEvent,
46
+ isLoading,
47
+ error,
48
+ setSelectedEvent: setSelectedEventCallback,
49
+ refreshEvents: refreshEventsCallback,
50
+ clearEventSelection: clearEventSelectionCallback
51
+ }), [events, selectedEvent?.event_id, isLoading, error?.message, setSelectedEventCallback, refreshEventsCallback, clearEventSelectionCallback]);
52
+ }
53
+ var TooltipProvider = TooltipPrimitive.Provider;
54
+ var TooltipRoot = TooltipPrimitive.Root;
55
+ var TooltipTrigger = TooltipPrimitive.Trigger;
56
+ var TooltipContent = React2.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
57
+ TooltipPrimitive.Content,
58
+ {
59
+ ref,
60
+ sideOffset,
61
+ className: cn(
62
+ "z-50 overflow-hidden rounded-md border bg-main-500 px-3 py-1.5 text-sm text-main-50 shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
63
+ className
64
+ ),
65
+ ...props
66
+ }
67
+ ));
68
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
69
+ var Tooltip = React2.forwardRef(({ children, content, delayDuration = 200 }, ref) => /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(TooltipRoot, { delayDuration, children: [
70
+ /* @__PURE__ */ jsx(TooltipTrigger, { ref, asChild: true, children: /* @__PURE__ */ jsx("span", { children }) }),
71
+ /* @__PURE__ */ jsx(TooltipContent, { children: content })
72
+ ] }) }));
73
+ Tooltip.displayName = "Tooltip";
74
+ function getButtonClasses(variant = "default", size = "default") {
75
+ const baseClasses = "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50";
76
+ const variantClasses = {
77
+ default: "bg-main-600 text-main-50 shadow hover:bg-acc-400",
78
+ destructive: "bg-acc-600 text-acc-50 shadow-sm hover:bg-acc-400",
79
+ outline: "border border-main-300 bg-background shadow-sm hover:bg-acc-400",
80
+ secondary: "bg-sec-100 text-sec-900 shadow-sm hover:bg-acc-400",
81
+ ghost: "hover:bg-acc-400",
82
+ link: "text-main-700 underline-offset-4 hover:underline hover:drop-shadow-lg hover:drop-shadow-acc-400"
83
+ };
84
+ const sizeClasses = {
85
+ default: "h-9 px-4 py-2",
86
+ sm: "h-8 rounded-md px-3 text-xs",
87
+ lg: "h-10 rounded-md px-8",
88
+ icon: "size-8"
89
+ };
90
+ return `${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`;
91
+ }
92
+ var Button = React2.forwardRef(
93
+ ({ className, variant, size, asChild = false, type = "button", disabled, ...props }, ref) => {
94
+ const Comp = asChild ? Slot : "button";
95
+ return /* @__PURE__ */ jsx(
96
+ Comp,
97
+ {
98
+ className: cn(getButtonClasses(variant, size), className),
99
+ ref,
100
+ type: !asChild ? type : void 0,
101
+ disabled,
102
+ "aria-disabled": disabled ? "true" : void 0,
103
+ ...props
104
+ }
105
+ );
106
+ }
107
+ );
108
+ Button.displayName = "Button";
109
+ function ButtonGroup({
110
+ children,
111
+ orientation = "horizontal",
112
+ variant,
113
+ size,
114
+ className,
115
+ spacing = "sm"
116
+ }) {
117
+ const spacingClasses = {
118
+ none: "",
119
+ sm: orientation === "horizontal" ? "space-x-1" : "space-y-1",
120
+ md: orientation === "horizontal" ? "space-x-2" : "space-y-2",
121
+ lg: orientation === "horizontal" ? "space-x-4" : "space-y-4"
122
+ };
123
+ return /* @__PURE__ */ jsx(
124
+ "fieldset",
125
+ {
126
+ className: cn(
127
+ "flex",
128
+ orientation === "horizontal" ? "flex-row items-center" : "flex-col",
129
+ spacingClasses[spacing],
130
+ className
131
+ ),
132
+ role: "group",
133
+ children: React2.Children.map(children, (child) => {
134
+ if (React2.isValidElement(child) && child.type) {
135
+ const componentType = child.type;
136
+ if (componentType.displayName === "Button") {
137
+ const childProps = child.props;
138
+ return React2.cloneElement(child, {
139
+ variant: childProps.variant || variant,
140
+ size: childProps.size || size,
141
+ ...childProps
142
+ });
143
+ }
144
+ }
145
+ return child;
146
+ })
147
+ }
148
+ );
149
+ }
150
+ var IconButton = React2.forwardRef(
151
+ ({ icon, className, size = "icon", "aria-label": ariaLabel, tooltip, ...props }, ref) => {
152
+ const button = /* @__PURE__ */ jsx(
153
+ Button,
154
+ {
155
+ ref,
156
+ size,
157
+ className: cn("shrink-0", className),
158
+ "aria-label": ariaLabel,
159
+ ...props,
160
+ children: icon
161
+ }
162
+ );
163
+ if (tooltip) {
164
+ return /* @__PURE__ */ jsx(Tooltip, { content: tooltip, children: button });
165
+ }
166
+ return button;
167
+ }
168
+ );
169
+ IconButton.displayName = "IconButton";
31
170
 
32
171
  // src/rbac/utils/clientSecurity.ts
33
172
  var SECURE_CLIENT_SYMBOL = Symbol("pace-core-secure-client");
@@ -61,11 +200,8 @@ See: https://github.com/jmruthers/pace-core/blob/main/packages/core/docs/rbac/ge
61
200
  function markClientAsSecure(client) {
62
201
  client[SECURE_CLIENT_SYMBOL] = true;
63
202
  }
64
-
65
- // src/rbac/secureClient.ts
66
- import { createClient } from "@supabase/supabase-js";
67
203
  var _SecureSupabaseClient = class _SecureSupabaseClient {
68
- constructor(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin = false, existingClient) {
204
+ constructor(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin2 = false, existingClient) {
69
205
  this.edgeFunctionClient = null;
70
206
  this.usesExistingClient = false;
71
207
  this.supabaseUrl = supabaseUrl;
@@ -73,7 +209,7 @@ var _SecureSupabaseClient = class _SecureSupabaseClient {
73
209
  this.organisationId = organisationId;
74
210
  this.eventId = eventId;
75
211
  this.appId = appId;
76
- this.isSuperAdmin = isSuperAdmin;
212
+ this.isSuperAdmin = isSuperAdmin2;
77
213
  if (existingClient) {
78
214
  this.supabase = existingClient;
79
215
  this.usesExistingClient = true;
@@ -422,200 +558,12 @@ _SecureSupabaseClient.GLOBAL_RPC_ALLOWLIST = /* @__PURE__ */ new Set([
422
558
  "data_rbac_apps_list"
423
559
  ]);
424
560
  var SecureSupabaseClient = _SecureSupabaseClient;
425
- function createSecureClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin = false) {
426
- return new SecureSupabaseClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin);
561
+ function createSecureClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin2 = false) {
562
+ return new SecureSupabaseClient(supabaseUrl, supabaseKey, organisationId, eventId, appId, isSuperAdmin2);
427
563
  }
428
- function fromSupabaseClient(client, organisationId, eventId, appId, isSuperAdmin = false) {
429
- return new SecureSupabaseClient("", "", organisationId, eventId, appId, isSuperAdmin, client);
564
+ function fromSupabaseClient(client, organisationId, eventId, appId, isSuperAdmin2 = false) {
565
+ return new SecureSupabaseClient("", "", organisationId, eventId, appId, isSuperAdmin2, client);
430
566
  }
431
-
432
- // src/rbac/hooks/useResolvedScope.ts
433
- import { useEffect, useState, useRef, useMemo } from "react";
434
- var log = createLogger("useResolvedScope");
435
- var appIdCache = /* @__PURE__ */ new Map();
436
- var CACHE_TTL = 5 * 60 * 1e3;
437
- function useResolvedScope({
438
- supabase,
439
- selectedOrganisationId,
440
- selectedEventId
441
- }) {
442
- const [resolvedScope, setResolvedScope] = useState(null);
443
- const [isLoading, setIsLoading] = useState(true);
444
- const [error, setError] = useState(null);
445
- const stableScopeRef = useRef({
446
- organisationId: "",
447
- appId: "",
448
- eventId: void 0
449
- });
450
- useEffect(() => {
451
- if (resolvedScope) {
452
- const newScope = {
453
- organisationId: resolvedScope.organisationId || "",
454
- appId: resolvedScope.appId || "",
455
- eventId: resolvedScope.eventId
456
- };
457
- if (stableScopeRef.current.organisationId !== newScope.organisationId || stableScopeRef.current.eventId !== newScope.eventId || stableScopeRef.current.appId !== newScope.appId) {
458
- stableScopeRef.current = {
459
- organisationId: newScope.organisationId,
460
- appId: newScope.appId,
461
- eventId: newScope.eventId
462
- };
463
- }
464
- } else {
465
- stableScopeRef.current = { organisationId: "", appId: "", eventId: void 0 };
466
- }
467
- }, [resolvedScope]);
468
- const appName = getCurrentAppName();
469
- const stableScope = stableScopeRef.current;
470
- useEffect(() => {
471
- let cancelled = false;
472
- const resolveScope = async () => {
473
- if (!supabase && !selectedOrganisationId && !selectedEventId) {
474
- if (!cancelled) {
475
- setResolvedScope(null);
476
- setIsLoading(false);
477
- setError(null);
478
- }
479
- return;
480
- }
481
- setIsLoading(true);
482
- setError(null);
483
- try {
484
- const appName2 = getCurrentAppName();
485
- let appId = void 0;
486
- if (supabase && appName2) {
487
- try {
488
- const { data: session } = await supabase.auth.getSession();
489
- if (!session?.session) {
490
- log.debug(`Skipping app resolution for "${appName2}" - user not authenticated`);
491
- } else {
492
- const cached = appIdCache.get(appName2);
493
- const now = Date.now();
494
- if (cached && now - cached.timestamp < CACHE_TTL) {
495
- appId = cached.appId;
496
- } else {
497
- const { data: app, error: error2 } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName2).eq("is_active", true).single();
498
- if (error2) {
499
- if (error2.code === "406" || error2.code === "PGRST116" || error2.message?.includes("406")) {
500
- log.debug(`App resolution blocked by RLS for "${appName2}" - user may not be authenticated`);
501
- appId = void 0;
502
- } else {
503
- const { data: inactiveApp } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName2).single();
504
- if (inactiveApp) {
505
- log.error(`App "${appName2}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
506
- appId = void 0;
507
- } else {
508
- log.error(`App "${appName2}" not found in rbac_apps table`, { error: error2 });
509
- appId = void 0;
510
- }
511
- }
512
- } else if (app) {
513
- appId = app.id;
514
- appIdCache.set(appName2, { appId, timestamp: now });
515
- }
516
- }
517
- }
518
- } catch (error2) {
519
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
520
- if (!errorMessage.includes("406") && !errorMessage.includes("PGRST116")) {
521
- log.error("Unexpected error resolving app ID:", error2);
522
- } else {
523
- log.debug("App resolution skipped - authentication required");
524
- }
525
- }
526
- }
527
- const initialScope = {
528
- organisationId: selectedOrganisationId || void 0,
529
- eventId: selectedEventId || void 0,
530
- appId
531
- };
532
- if (appName2 === "PORTAL" || appName2 === "ADMIN") {
533
- if (!cancelled) {
534
- const optionalContextScope = {
535
- organisationId: void 0,
536
- eventId: void 0,
537
- appId: appId || void 0
538
- };
539
- setResolvedScope(optionalContextScope);
540
- setError(null);
541
- setIsLoading(false);
542
- }
543
- return;
544
- }
545
- const { ContextValidator: ContextValidator2 } = await import("./contextValidator-5OGXSPKS.js");
546
- const validation = await ContextValidator2.resolveScopeForPage(
547
- initialScope,
548
- "organisation",
549
- // Default to organisation scope when no page context
550
- appName2 || void 0,
551
- supabase
552
- );
553
- if (!validation.isValid) {
554
- if (selectedEventId) {
555
- if (!cancelled) {
556
- const eventScope = {
557
- organisationId: void 0,
558
- // Will be derived from event during permission check
559
- eventId: selectedEventId,
560
- appId: appId || void 0
561
- };
562
- setResolvedScope(eventScope);
563
- setError(null);
564
- setIsLoading(false);
565
- }
566
- return;
567
- }
568
- if (!cancelled) {
569
- setResolvedScope(null);
570
- setError(validation.error || new Error("Context validation failed"));
571
- setIsLoading(false);
572
- }
573
- return;
574
- }
575
- if (!cancelled) {
576
- setResolvedScope(validation.resolvedScope);
577
- setError(null);
578
- setIsLoading(false);
579
- }
580
- } catch (err) {
581
- if (!cancelled) {
582
- setError(err);
583
- setIsLoading(false);
584
- }
585
- }
586
- };
587
- resolveScope();
588
- return () => {
589
- cancelled = true;
590
- };
591
- }, [selectedOrganisationId, selectedEventId, supabase]);
592
- const allowsOptionalContexts = appName === "PORTAL" || appName === "ADMIN";
593
- const hasValidScope = allowsOptionalContexts ? true : stableScope.appId || stableScope.organisationId;
594
- const finalScope = useMemo(() => {
595
- if (!hasValidScope) {
596
- return allowsOptionalContexts ? {} : null;
597
- }
598
- const scope = {};
599
- if (stableScope.organisationId) {
600
- scope.organisationId = stableScope.organisationId;
601
- }
602
- if (stableScope.eventId) {
603
- scope.eventId = stableScope.eventId;
604
- }
605
- if (stableScope.appId) {
606
- scope.appId = stableScope.appId;
607
- }
608
- return scope;
609
- }, [hasValidScope, allowsOptionalContexts, stableScope.organisationId, stableScope.eventId, stableScope.appId]);
610
- return {
611
- resolvedScope: finalScope,
612
- isLoading,
613
- error
614
- };
615
- }
616
-
617
- // src/rbac/hooks/useRBAC.ts
618
- import { useState as useState2, useEffect as useEffect2, useCallback, useMemo as useMemo2 } from "react";
619
567
  function mapAccessLevelToEventRole(level) {
620
568
  switch (level) {
621
569
  case "viewer":
@@ -645,13 +593,13 @@ function useRBAC(pageId) {
645
593
  selectedEvent,
646
594
  eventLoading
647
595
  } = useUnifiedAuth();
648
- const [globalRole, setGlobalRole] = useState2(null);
649
- const [organisationRole, setOrganisationRole] = useState2(null);
650
- const [eventAppRole, setEventAppRole] = useState2(null);
651
- const [permissionMap, setPermissionMap] = useState2({});
652
- const [currentScope, setCurrentScope] = useState2(null);
653
- const [isLoading, setIsLoading] = useState2(false);
654
- const [error, setError] = useState2(null);
596
+ const [globalRole, setGlobalRole] = useState(null);
597
+ const [organisationRole, setOrganisationRole] = useState(null);
598
+ const [eventAppRole, setEventAppRole] = useState(null);
599
+ const [permissionMap, setPermissionMap] = useState({});
600
+ const [currentScope, setCurrentScope] = useState(null);
601
+ const [isLoading, setIsLoading] = useState(false);
602
+ const [error, setError] = useState(null);
655
603
  const resetState = useCallback(() => {
656
604
  setGlobalRole(null);
657
605
  setOrganisationRole(null);
@@ -777,12 +725,12 @@ function useRBAC(pageId) {
777
725
  },
778
726
  [globalRole, organisationRole, permissionMap]
779
727
  );
780
- const isSuperAdmin = useMemo2(() => globalRole === "super_admin" || permissionMap["*"] === true, [globalRole, permissionMap]);
781
- const isOrgAdmin = useMemo2(() => organisationRole === "org_admin" || isSuperAdmin, [organisationRole, isSuperAdmin]);
782
- const isEventAdmin = useMemo2(() => eventAppRole === "event_admin" || isSuperAdmin, [eventAppRole, isSuperAdmin]);
783
- const canManageOrganisation = useMemo2(() => isSuperAdmin || organisationRole === "org_admin", [isSuperAdmin, organisationRole]);
784
- const canManageEvent = useMemo2(() => isSuperAdmin || eventAppRole === "event_admin", [isSuperAdmin, eventAppRole]);
785
- useEffect2(() => {
728
+ const isSuperAdmin2 = useMemo(() => globalRole === "super_admin" || permissionMap["*"] === true, [globalRole, permissionMap]);
729
+ const isOrgAdmin = useMemo(() => organisationRole === "org_admin" || isSuperAdmin2, [organisationRole, isSuperAdmin2]);
730
+ const isEventAdmin = useMemo(() => eventAppRole === "event_admin" || isSuperAdmin2, [eventAppRole, isSuperAdmin2]);
731
+ const canManageOrganisation = useMemo(() => isSuperAdmin2 || organisationRole === "org_admin", [isSuperAdmin2, organisationRole]);
732
+ const canManageEvent = useMemo(() => isSuperAdmin2 || eventAppRole === "event_admin", [isSuperAdmin2, eventAppRole]);
733
+ useEffect(() => {
786
734
  loadRBACContext();
787
735
  }, [loadRBACContext, appName, eventLoading, selectedEvent?.event_id, user, session, selectedOrganisation?.id, orgContextReady, orgLoading]);
788
736
  return {
@@ -791,7 +739,7 @@ function useRBAC(pageId) {
791
739
  organisationRole,
792
740
  eventAppRole,
793
741
  hasGlobalPermission,
794
- isSuperAdmin,
742
+ isSuperAdmin: isSuperAdmin2,
795
743
  isOrgAdmin,
796
744
  isEventAdmin,
797
745
  canManageOrganisation,
@@ -800,20 +748,131 @@ function useRBAC(pageId) {
800
748
  error
801
749
  };
802
750
  }
803
-
804
- // src/rbac/hooks/permissions/useAccessLevel.ts
805
- import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
751
+ var log = createLogger("useResolvedScope");
752
+ var appIdCache = /* @__PURE__ */ new Map();
753
+ var CACHE_TTL = 5 * 60 * 1e3;
754
+ function useResolvedScope({
755
+ supabase,
756
+ selectedOrganisationId,
757
+ selectedEventId,
758
+ selectedEventOrganisationId
759
+ }) {
760
+ const immediateOrganisationId = selectedEventOrganisationId || selectedOrganisationId || void 0;
761
+ const immediateEventId = selectedEventId || void 0;
762
+ const [appId, setAppId] = useState(void 0);
763
+ const [isResolvingAppId, setIsResolvingAppId] = useState(false);
764
+ const [error, setError] = useState(null);
765
+ const appName = getCurrentAppName();
766
+ useEffect(() => {
767
+ let cancelled = false;
768
+ const resolveAppId = async () => {
769
+ if (!supabase && !selectedOrganisationId && !selectedEventId) {
770
+ if (!cancelled) {
771
+ setAppId(void 0);
772
+ setIsResolvingAppId(false);
773
+ setError(null);
774
+ }
775
+ return;
776
+ }
777
+ setIsResolvingAppId(true);
778
+ setError(null);
779
+ try {
780
+ const appName2 = getCurrentAppName();
781
+ let resolvedAppId = void 0;
782
+ if (supabase && appName2) {
783
+ try {
784
+ const { data: session } = await supabase.auth.getSession();
785
+ if (!session?.session) {
786
+ log.debug(`Skipping app resolution for "${appName2}" - user not authenticated`);
787
+ } else {
788
+ const cached = appIdCache.get(appName2);
789
+ const now = Date.now();
790
+ if (cached && now - cached.timestamp < CACHE_TTL) {
791
+ resolvedAppId = cached.appId;
792
+ } else {
793
+ const { data: app, error: error2 } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName2).eq("is_active", true).single();
794
+ if (error2) {
795
+ if (error2.code === "406" || error2.code === "PGRST116" || error2.message?.includes("406")) {
796
+ log.debug(`App resolution blocked by RLS for "${appName2}" - user may not be authenticated`);
797
+ resolvedAppId = void 0;
798
+ } else {
799
+ const { data: inactiveApp } = await supabase.from("rbac_apps").select("id, name, is_active").eq("name", appName2).single();
800
+ if (inactiveApp) {
801
+ log.error(`App "${appName2}" exists but is inactive (is_active: ${inactiveApp.is_active})`);
802
+ resolvedAppId = void 0;
803
+ } else {
804
+ log.error(`App "${appName2}" not found in rbac_apps table`, { error: error2 });
805
+ resolvedAppId = void 0;
806
+ }
807
+ }
808
+ } else if (app) {
809
+ resolvedAppId = app.id;
810
+ appIdCache.set(appName2, { appId: resolvedAppId, timestamp: now });
811
+ }
812
+ }
813
+ }
814
+ } catch (error2) {
815
+ const errorMessage = error2 instanceof Error ? error2.message : String(error2);
816
+ if (!errorMessage.includes("406") && !errorMessage.includes("PGRST116")) {
817
+ log.error("Unexpected error resolving app ID:", error2);
818
+ } else {
819
+ log.debug("App resolution skipped - authentication required");
820
+ }
821
+ }
822
+ }
823
+ if (!cancelled) {
824
+ setAppId(resolvedAppId);
825
+ setIsResolvingAppId(false);
826
+ setError(null);
827
+ }
828
+ } catch (err) {
829
+ if (!cancelled) {
830
+ setError(err);
831
+ setIsResolvingAppId(false);
832
+ }
833
+ }
834
+ };
835
+ resolveAppId();
836
+ return () => {
837
+ cancelled = true;
838
+ };
839
+ }, [supabase, selectedOrganisationId, selectedEventId]);
840
+ const immediateScope = useMemo(() => {
841
+ if (appName === "PORTAL" || appName === "ADMIN") {
842
+ return {
843
+ organisationId: void 0,
844
+ eventId: void 0,
845
+ appId: appId || void 0
846
+ };
847
+ }
848
+ const scope = {};
849
+ if (immediateOrganisationId) {
850
+ scope.organisationId = immediateOrganisationId;
851
+ }
852
+ if (immediateEventId) {
853
+ scope.eventId = immediateEventId;
854
+ }
855
+ if (appId) {
856
+ scope.appId = appId;
857
+ }
858
+ if (!scope.organisationId && !scope.appId) {
859
+ return null;
860
+ }
861
+ return scope;
862
+ }, [immediateOrganisationId, immediateEventId, appId, appName]);
863
+ return {
864
+ resolvedScope: immediateScope,
865
+ isLoading: isResolvingAppId,
866
+ // Only true while appId resolves
867
+ error
868
+ };
869
+ }
806
870
  function useAccessLevel(userId, scope) {
807
- const [accessLevel, setAccessLevel] = useState3("viewer");
808
- const [isLoading, setIsLoading] = useState3(true);
809
- const [error, setError] = useState3(null);
810
- let appName;
811
- try {
812
- const { appName: contextAppName } = useAppConfig();
813
- appName = contextAppName;
814
- } catch {
815
- }
816
- const fetchAccessLevel = useCallback2(async () => {
871
+ const [accessLevel, setAccessLevel] = useState("viewer");
872
+ const [isLoading, setIsLoading] = useState(true);
873
+ const [error, setError] = useState(null);
874
+ const { appName } = useAppConfig();
875
+ const fetchAccessLevel = useCallback(async () => {
817
876
  if (!userId) {
818
877
  setAccessLevel("viewer");
819
878
  setIsLoading(false);
@@ -822,7 +881,7 @@ function useAccessLevel(userId, scope) {
822
881
  try {
823
882
  setIsLoading(true);
824
883
  setError(null);
825
- const { isSuperAdmin: checkSuperAdmin } = await import("./api-O6HTBX5Y.js");
884
+ const { isSuperAdmin: checkSuperAdmin } = await import('./api-Y4MQWOFW.js');
826
885
  const isSuperAdminUser = await checkSuperAdmin(userId);
827
886
  if (isSuperAdminUser) {
828
887
  setAccessLevel("super");
@@ -846,10 +905,10 @@ function useAccessLevel(userId, scope) {
846
905
  setIsLoading(false);
847
906
  }
848
907
  }, [userId, scope.organisationId, scope.eventId, scope.appId, appName]);
849
- useEffect3(() => {
908
+ useEffect(() => {
850
909
  fetchAccessLevel();
851
910
  }, [fetchAccessLevel]);
852
- return useMemo3(() => ({
911
+ return useMemo(() => ({
853
912
  accessLevel,
854
913
  isLoading,
855
914
  error,
@@ -857,47 +916,6 @@ function useAccessLevel(userId, scope) {
857
916
  }), [accessLevel, isLoading, error, fetchAccessLevel]);
858
917
  }
859
918
 
860
- // src/rbac/hooks/permissions/useCachedPermissions.ts
861
- import { useCallback as useCallback3, useEffect as useEffect4, useMemo as useMemo4, useState as useState4 } from "react";
862
- function useCachedPermissions(userId, scope) {
863
- const [permissions, setPermissions] = useState4({});
864
- const [isLoading, setIsLoading] = useState4(true);
865
- const [error, setError] = useState4(null);
866
- const fetchCachedPermissions = useCallback3(async () => {
867
- if (!userId) {
868
- setPermissions({});
869
- setIsLoading(false);
870
- return;
871
- }
872
- try {
873
- setIsLoading(true);
874
- setError(null);
875
- const permissionMap = await getPermissionMap({ userId, scope });
876
- setPermissions(permissionMap);
877
- } catch (err) {
878
- setError(err instanceof Error ? err : new Error("Failed to fetch cached permissions"));
879
- } finally {
880
- setIsLoading(false);
881
- }
882
- }, [userId, scope.organisationId, scope.eventId, scope.appId]);
883
- const invalidateCache = useCallback3(() => {
884
- fetchCachedPermissions();
885
- }, [fetchCachedPermissions]);
886
- useEffect4(() => {
887
- fetchCachedPermissions();
888
- }, [fetchCachedPermissions]);
889
- return useMemo4(() => ({
890
- permissions,
891
- isLoading,
892
- error,
893
- invalidateCache,
894
- refetch: fetchCachedPermissions
895
- }), [permissions, isLoading, error, invalidateCache, fetchCachedPermissions]);
896
- }
897
-
898
- // src/rbac/hooks/permissions/useCan.ts
899
- import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo5, useRef as useRef2, useState as useState5 } from "react";
900
-
901
919
  // src/rbac/utils/deep-equal.ts
902
920
  function scopeEqual(a, b) {
903
921
  if (a === b) {
@@ -911,27 +929,27 @@ function scopeEqual(a, b) {
911
929
 
912
930
  // src/rbac/hooks/permissions/useCan.ts
913
931
  function useCan(userId, scope, permission, pageId, useCache = true, precomputedSuperAdmin = null, appName) {
914
- const [isSuperAdmin, setIsSuperAdmin] = useState5(precomputedSuperAdmin ?? null);
932
+ const [isSuperAdmin2, setIsSuperAdmin] = useState(precomputedSuperAdmin ?? null);
915
933
  const initialCan = precomputedSuperAdmin === true ? true : false;
916
934
  const initialIsLoading = precomputedSuperAdmin === true ? false : true;
917
- const [can, setCan] = useState5(initialCan);
918
- const [isLoading, setIsLoading] = useState5(initialIsLoading);
919
- const [error, setError] = useState5(null);
935
+ const [can, setCan] = useState(initialCan);
936
+ const [isLoading, setIsLoading] = useState(initialIsLoading);
937
+ const [error, setError] = useState(null);
920
938
  const isValidScope = scope && typeof scope === "object";
921
939
  const organisationId = isValidScope ? scope.organisationId : void 0;
922
940
  const eventId = isValidScope ? scope.eventId : void 0;
923
941
  const appId = isValidScope ? scope.appId : void 0;
924
- useEffect5(() => {
925
- if (precomputedSuperAdmin === true && isSuperAdmin !== true) {
942
+ useEffect(() => {
943
+ if (precomputedSuperAdmin === true && isSuperAdmin2 !== true) {
926
944
  setIsSuperAdmin(true);
927
945
  setCan(true);
928
946
  setIsLoading(false);
929
947
  setError(null);
930
- } else if (precomputedSuperAdmin === false && isSuperAdmin !== false) {
948
+ } else if (precomputedSuperAdmin === false && isSuperAdmin2 !== false) {
931
949
  setIsSuperAdmin(false);
932
950
  }
933
- }, [precomputedSuperAdmin, isSuperAdmin]);
934
- useEffect5(() => {
951
+ }, [precomputedSuperAdmin, isSuperAdmin2]);
952
+ useEffect(() => {
935
953
  if (precomputedSuperAdmin === null) {
936
954
  if (!userId) {
937
955
  setIsSuperAdmin(false);
@@ -941,7 +959,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
941
959
  const checkSuperAdmin = async () => {
942
960
  const startTime = Date.now();
943
961
  try {
944
- const { isSuperAdmin: checkSuperAdmin2 } = await import("./api-O6HTBX5Y.js");
962
+ const { isSuperAdmin: checkSuperAdmin2 } = await import('./api-Y4MQWOFW.js');
945
963
  const timeoutWarning = setTimeout(() => {
946
964
  if (!cancelled) {
947
965
  console.warn("[useCan] Super admin check taking longer than 5 seconds", {
@@ -985,10 +1003,10 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
985
1003
  };
986
1004
  }
987
1005
  }, [userId, precomputedSuperAdmin]);
988
- useEffect5(() => {
1006
+ useEffect(() => {
989
1007
  const isPagePermission = permission.includes(":page.") || !!pageId;
990
1008
  const requiresOrgId = !isPagePermission;
991
- if (isSuperAdmin === true) {
1009
+ if (isSuperAdmin2 === true) {
992
1010
  return;
993
1011
  }
994
1012
  if (requiresOrgId && (!isValidScope || !organisationId || organisationId === null || typeof organisationId === "string" && organisationId.trim() === "")) {
@@ -1002,14 +1020,14 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1002
1020
  if (error?.message === "Organisation context is required for permission checks") {
1003
1021
  setError(null);
1004
1022
  }
1005
- }, [isValidScope, organisationId, error, permission, pageId, isSuperAdmin]);
1006
- const lastUserIdRef = useRef2(null);
1007
- const lastScopeRef = useRef2(null);
1008
- const lastPermissionRef = useRef2(null);
1009
- const lastPageIdRef = useRef2(null);
1010
- const lastUseCacheRef = useRef2(null);
1011
- const lastIsSuperAdminRef = useRef2(null);
1012
- const stableScope = useMemo5(() => {
1023
+ }, [isValidScope, organisationId, error, permission, pageId, isSuperAdmin2]);
1024
+ const lastUserIdRef = useRef(null);
1025
+ useRef(null);
1026
+ const lastPermissionRef = useRef(null);
1027
+ const lastPageIdRef = useRef(null);
1028
+ const lastUseCacheRef = useRef(null);
1029
+ const lastIsSuperAdminRef = useRef(null);
1030
+ const stableScope = useMemo(() => {
1013
1031
  if (!isValidScope) {
1014
1032
  return null;
1015
1033
  }
@@ -1019,12 +1037,12 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1019
1037
  appId
1020
1038
  };
1021
1039
  }, [isValidScope, organisationId, eventId, appId]);
1022
- const prevScopeRef = useRef2(null);
1023
- useEffect5(() => {
1040
+ const prevScopeRef = useRef(null);
1041
+ useEffect(() => {
1024
1042
  const scopeChanged = !scopeEqual(prevScopeRef.current, stableScope);
1025
- const isSuperAdminChanged = lastIsSuperAdminRef.current !== isSuperAdmin;
1043
+ const isSuperAdminChanged = lastIsSuperAdminRef.current !== isSuperAdmin2;
1026
1044
  if (lastUserIdRef.current !== userId || scopeChanged || lastPermissionRef.current !== permission || lastPageIdRef.current !== pageId || lastUseCacheRef.current !== useCache || isSuperAdminChanged) {
1027
- lastIsSuperAdminRef.current = isSuperAdmin;
1045
+ lastIsSuperAdminRef.current = isSuperAdmin2;
1028
1046
  lastUserIdRef.current = userId;
1029
1047
  prevScopeRef.current = stableScope;
1030
1048
  lastPermissionRef.current = permission;
@@ -1036,13 +1054,13 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1036
1054
  setIsLoading(false);
1037
1055
  return;
1038
1056
  }
1039
- if (isSuperAdmin === true) {
1057
+ if (isSuperAdmin2 === true) {
1040
1058
  setCan(true);
1041
1059
  setIsLoading(false);
1042
1060
  setError(null);
1043
1061
  return;
1044
1062
  }
1045
- if (isSuperAdmin === null) {
1063
+ if (isSuperAdmin2 === null) {
1046
1064
  setIsLoading(true);
1047
1065
  setCan(false);
1048
1066
  setError(null);
@@ -1078,7 +1096,7 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1078
1096
  ...eventId ? { eventId } : {},
1079
1097
  ...appId ? { appId } : {}
1080
1098
  };
1081
- const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, appName, isSuperAdmin === false ? false : null);
1099
+ const result = useCache ? await isPermittedCached({ userId, scope: validScope, permission, pageId }, appName) : await isPermitted({ userId, scope: validScope, permission, pageId }, appName, isSuperAdmin2 === false ? false : null);
1082
1100
  setCan(result);
1083
1101
  } catch (err) {
1084
1102
  const logger2 = getRBACLogger();
@@ -1092,8 +1110,8 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1092
1110
  };
1093
1111
  checkPermission();
1094
1112
  }
1095
- }, [userId, stableScope, permission, pageId, useCache, appName, isSuperAdmin]);
1096
- const refetch = useCallback4(async () => {
1113
+ }, [userId, stableScope, permission, pageId, useCache, appName, isSuperAdmin2]);
1114
+ const refetch = useCallback(async () => {
1097
1115
  if (!userId) {
1098
1116
  setCan(false);
1099
1117
  setIsLoading(false);
@@ -1130,105 +1148,18 @@ function useCan(userId, scope, permission, pageId, useCache = true, precomputedS
1130
1148
  setIsLoading(false);
1131
1149
  }
1132
1150
  }, [userId, isValidScope, organisationId, eventId, appId, permission, pageId, useCache, appName]);
1133
- return useMemo5(() => ({
1151
+ return useMemo(() => ({
1134
1152
  can,
1135
1153
  isLoading,
1136
1154
  error,
1137
1155
  refetch
1138
1156
  }), [can, isLoading, error, refetch]);
1139
1157
  }
1140
-
1141
- // src/rbac/hooks/permissions/useHasAllPermissions.ts
1142
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo6, useState as useState6 } from "react";
1143
- function useHasAllPermissions(userId, scope, permissions, useCache = true) {
1144
- const [hasAll, setHasAll] = useState6(false);
1145
- const [isLoading, setIsLoading] = useState6(true);
1146
- const [error, setError] = useState6(null);
1147
- const checkAllPermissions = useCallback5(async () => {
1148
- if (!userId || permissions.length === 0) {
1149
- setHasAll(false);
1150
- setIsLoading(false);
1151
- return;
1152
- }
1153
- try {
1154
- setIsLoading(true);
1155
- setError(null);
1156
- let hasAllPermissions = true;
1157
- for (const permission of permissions) {
1158
- const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission });
1159
- if (!result) {
1160
- hasAllPermissions = false;
1161
- break;
1162
- }
1163
- }
1164
- setHasAll(hasAllPermissions);
1165
- } catch (err) {
1166
- setError(err instanceof Error ? err : new Error("Failed to check permissions"));
1167
- setHasAll(false);
1168
- } finally {
1169
- setIsLoading(false);
1170
- }
1171
- }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
1172
- useEffect6(() => {
1173
- checkAllPermissions();
1174
- }, [checkAllPermissions]);
1175
- return useMemo6(() => ({
1176
- hasAll,
1177
- isLoading,
1178
- error,
1179
- refetch: checkAllPermissions
1180
- }), [hasAll, isLoading, error, checkAllPermissions]);
1181
- }
1182
-
1183
- // src/rbac/hooks/permissions/useHasAnyPermission.ts
1184
- import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo7, useState as useState7 } from "react";
1185
- function useHasAnyPermission(userId, scope, permissions, useCache = true) {
1186
- const [hasAny, setHasAny] = useState7(false);
1187
- const [isLoading, setIsLoading] = useState7(true);
1188
- const [error, setError] = useState7(null);
1189
- const checkAnyPermission = useCallback6(async () => {
1190
- if (!userId || permissions.length === 0) {
1191
- setHasAny(false);
1192
- setIsLoading(false);
1193
- return;
1194
- }
1195
- try {
1196
- setIsLoading(true);
1197
- setError(null);
1198
- let hasAnyPermission = false;
1199
- for (const permission of permissions) {
1200
- const result = useCache ? await isPermittedCached({ userId, scope, permission }) : await isPermitted({ userId, scope, permission });
1201
- if (result) {
1202
- hasAnyPermission = true;
1203
- break;
1204
- }
1205
- }
1206
- setHasAny(hasAnyPermission);
1207
- } catch (err) {
1208
- setError(err instanceof Error ? err : new Error("Failed to check permissions"));
1209
- setHasAny(false);
1210
- } finally {
1211
- setIsLoading(false);
1212
- }
1213
- }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
1214
- useEffect7(() => {
1215
- checkAnyPermission();
1216
- }, [checkAnyPermission]);
1217
- return useMemo7(() => ({
1218
- hasAny,
1219
- isLoading,
1220
- error,
1221
- refetch: checkAnyPermission
1222
- }), [hasAny, isLoading, error, checkAnyPermission]);
1223
- }
1224
-
1225
- // src/rbac/hooks/permissions/useMultiplePermissions.ts
1226
- import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo8, useState as useState8 } from "react";
1227
1158
  function useMultiplePermissions(userId, scope, permissions, useCache = true) {
1228
- const [results, setResults] = useState8({});
1229
- const [isLoading, setIsLoading] = useState8(true);
1230
- const [error, setError] = useState8(null);
1231
- const checkPermissions = useCallback7(async () => {
1159
+ const [results, setResults] = useState({});
1160
+ const [isLoading, setIsLoading] = useState(true);
1161
+ const [error, setError] = useState(null);
1162
+ const checkPermissions = useCallback(async () => {
1232
1163
  if (!userId || permissions.length === 0) {
1233
1164
  setResults({});
1234
1165
  setIsLoading(false);
@@ -1250,29 +1181,26 @@ function useMultiplePermissions(userId, scope, permissions, useCache = true) {
1250
1181
  setIsLoading(false);
1251
1182
  }
1252
1183
  }, [userId, scope.organisationId, scope.eventId, scope.appId, permissions, useCache]);
1253
- useEffect8(() => {
1184
+ useEffect(() => {
1254
1185
  checkPermissions();
1255
1186
  }, [checkPermissions]);
1256
- return useMemo8(() => ({
1187
+ return useMemo(() => ({
1257
1188
  results,
1258
1189
  isLoading,
1259
1190
  error,
1260
1191
  refetch: checkPermissions
1261
1192
  }), [results, isLoading, error, checkPermissions]);
1262
1193
  }
1263
-
1264
- // src/rbac/hooks/permissions/usePermissions.ts
1265
- import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo9, useRef as useRef3, useState as useState9 } from "react";
1266
1194
  function usePermissions(userId, organisationId, eventId, appId) {
1267
- const [permissions, setPermissions] = useState9({});
1268
- const [isLoading, setIsLoading] = useState9(true);
1269
- const [error, setError] = useState9(null);
1270
- const [fetchTrigger, setFetchTrigger] = useState9(0);
1271
- const isFetchingRef = useRef3(false);
1195
+ const [permissions, setPermissions] = useState({});
1196
+ const [isLoading, setIsLoading] = useState(true);
1197
+ const [error, setError] = useState(null);
1198
+ const [fetchTrigger, setFetchTrigger] = useState(0);
1199
+ const isFetchingRef = useRef(false);
1272
1200
  const logger2 = getRBACLogger();
1273
- const prevValuesRef = useRef3({ userId, organisationId, eventId, appId });
1201
+ const prevValuesRef = useRef({ userId, organisationId, eventId, appId });
1274
1202
  const orgId = organisationId || "";
1275
- useEffect9(() => {
1203
+ useEffect(() => {
1276
1204
  if (!userId) {
1277
1205
  return;
1278
1206
  }
@@ -1287,16 +1215,15 @@ function usePermissions(userId, organisationId, eventId, appId) {
1287
1215
  setError(null);
1288
1216
  }
1289
1217
  }, [userId, organisationId, error, orgId]);
1290
- useEffect9(() => {
1218
+ useEffect(() => {
1291
1219
  const paramsChanged = prevValuesRef.current.userId !== userId || prevValuesRef.current.organisationId !== organisationId || prevValuesRef.current.eventId !== eventId || prevValuesRef.current.appId !== appId;
1292
1220
  if (paramsChanged) {
1293
- if (prevValuesRef.current.appId !== appId) {
1294
- }
1221
+ if (prevValuesRef.current.appId !== appId) ;
1295
1222
  prevValuesRef.current = { userId, organisationId, eventId, appId };
1296
1223
  setFetchTrigger((prev) => prev + 1);
1297
1224
  }
1298
1225
  }, [userId, organisationId, eventId, appId, logger2]);
1299
- useEffect9(() => {
1226
+ useEffect(() => {
1300
1227
  const fetchPermissions = async () => {
1301
1228
  if (isFetchingRef.current) {
1302
1229
  return;
@@ -1343,25 +1270,25 @@ function usePermissions(userId, organisationId, eventId, appId) {
1343
1270
  };
1344
1271
  fetchPermissions();
1345
1272
  }, [fetchTrigger, userId, organisationId, eventId, appId]);
1346
- const hasPermission = useCallback8((permission) => {
1273
+ const hasPermission = useCallback((permission) => {
1347
1274
  if (permissions["*"]) {
1348
1275
  return true;
1349
1276
  }
1350
1277
  return permissions[permission] === true;
1351
1278
  }, [permissions]);
1352
- const hasAnyPermission = useCallback8((permissionList) => {
1279
+ const hasAnyPermission = useCallback((permissionList) => {
1353
1280
  if (permissions["*"]) {
1354
1281
  return true;
1355
1282
  }
1356
1283
  return permissionList.some((p) => permissions[p] === true);
1357
1284
  }, [permissions]);
1358
- const hasAllPermissions = useCallback8((permissionList) => {
1285
+ const hasAllPermissions = useCallback((permissionList) => {
1359
1286
  if (permissions["*"]) {
1360
1287
  return true;
1361
1288
  }
1362
1289
  return permissionList.every((p) => permissions[p] === true);
1363
1290
  }, [permissions]);
1364
- const refetch = useCallback8(async () => {
1291
+ const refetch = useCallback(async () => {
1365
1292
  if (isFetchingRef.current) {
1366
1293
  return;
1367
1294
  }
@@ -1395,7 +1322,7 @@ function usePermissions(userId, organisationId, eventId, appId) {
1395
1322
  isFetchingRef.current = false;
1396
1323
  }
1397
1324
  }, [userId, organisationId, eventId, appId]);
1398
- return useMemo9(() => ({
1325
+ return useMemo(() => ({
1399
1326
  permissions,
1400
1327
  isLoading,
1401
1328
  error,
@@ -1405,12 +1332,57 @@ function usePermissions(userId, organisationId, eventId, appId) {
1405
1332
  refetch
1406
1333
  }), [permissions, isLoading, error, hasPermission, hasAnyPermission, hasAllPermissions, refetch]);
1407
1334
  }
1408
-
1409
- // src/rbac/hooks/useResourcePermissions.ts
1410
- import { useMemo as useMemo10 } from "react";
1411
1335
  function useResourcePermissions(resource, options = {}) {
1412
1336
  const { enableRead = false, requireScope = true } = options;
1337
+ const logger2 = createLogger("ResourcePermissions");
1413
1338
  const { user, supabase } = useUnifiedAuth();
1339
+ const [isSuperAdminUser, setIsSuperAdminUser] = useState(null);
1340
+ const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState(() => !!user?.id);
1341
+ const lastCheckedUserIdRef = useRef(null);
1342
+ const isCheckingRef = useRef(false);
1343
+ useEffect(() => {
1344
+ if (lastCheckedUserIdRef.current === user?.id && isSuperAdminUser !== null) {
1345
+ return;
1346
+ }
1347
+ if (isCheckingRef.current) {
1348
+ return;
1349
+ }
1350
+ const checkSuperAdminStatus = async () => {
1351
+ if (!user?.id) {
1352
+ setIsSuperAdminUser(false);
1353
+ setIsCheckingSuperAdmin(false);
1354
+ lastCheckedUserIdRef.current = null;
1355
+ return;
1356
+ }
1357
+ isCheckingRef.current = true;
1358
+ lastCheckedUserIdRef.current = user.id;
1359
+ const startTime = Date.now();
1360
+ setIsCheckingSuperAdmin(true);
1361
+ const timeoutId = setTimeout(() => {
1362
+ logger2.warn("useResourcePermissions", "Super admin check taking longer than 5 seconds", {
1363
+ userId: user?.id,
1364
+ elapsedMs: Date.now() - startTime
1365
+ });
1366
+ }, 5e3);
1367
+ try {
1368
+ const superAdminStatus = await isSuperAdmin(user.id);
1369
+ setIsSuperAdminUser(superAdminStatus);
1370
+ } catch (error2) {
1371
+ const elapsed = Date.now() - startTime;
1372
+ logger2.error("useResourcePermissions", "Error checking super admin status", {
1373
+ userId: user?.id,
1374
+ error: error2,
1375
+ elapsedMs: elapsed
1376
+ });
1377
+ setIsSuperAdminUser(false);
1378
+ } finally {
1379
+ clearTimeout(timeoutId);
1380
+ setIsCheckingSuperAdmin(false);
1381
+ isCheckingRef.current = false;
1382
+ }
1383
+ };
1384
+ checkSuperAdminStatus();
1385
+ }, [user?.id, logger2]);
1414
1386
  const { selectedOrganisation } = useOrganisations();
1415
1387
  let selectedEvent = null;
1416
1388
  try {
@@ -1421,7 +1393,8 @@ function useResourcePermissions(resource, options = {}) {
1421
1393
  const { resolvedScope, isLoading: scopeLoading, error: scopeError } = useResolvedScope({
1422
1394
  supabase,
1423
1395
  selectedOrganisationId: selectedOrganisation?.id || null,
1424
- selectedEventId: selectedEvent?.event_id || null
1396
+ selectedEventId: selectedEvent?.event_id || null,
1397
+ selectedEventOrganisationId: selectedEvent?.organisation_id || null
1425
1398
  });
1426
1399
  const scope = resolvedScope || {
1427
1400
  organisationId: selectedOrganisation?.id || "",
@@ -1443,8 +1416,8 @@ function useResourcePermissions(resource, options = {}) {
1443
1416
  // Pass resource name as pageId when appId is available to enable page permission checks
1444
1417
  true,
1445
1418
  // useCache
1446
- null,
1447
- // precomputedSuperAdmin - not checked yet
1419
+ isSuperAdminUser,
1420
+ // precomputedSuperAdmin - null if checking, false/true if checked
1448
1421
  void 0
1449
1422
  // appName
1450
1423
  );
@@ -1456,8 +1429,8 @@ function useResourcePermissions(resource, options = {}) {
1456
1429
  // Pass resource name as pageId when appId is available to enable page permission checks
1457
1430
  true,
1458
1431
  // useCache
1459
- null,
1460
- // precomputedSuperAdmin - not checked yet
1432
+ isSuperAdminUser,
1433
+ // precomputedSuperAdmin - null if checking, false/true if checked
1461
1434
  void 0
1462
1435
  // appName
1463
1436
  );
@@ -1469,8 +1442,8 @@ function useResourcePermissions(resource, options = {}) {
1469
1442
  // Pass resource name as pageId when appId is available to enable page permission checks
1470
1443
  true,
1471
1444
  // useCache
1472
- null,
1473
- // precomputedSuperAdmin - not checked yet
1445
+ isSuperAdminUser,
1446
+ // precomputedSuperAdmin - null if checking, false/true if checked
1474
1447
  void 0
1475
1448
  // appName
1476
1449
  );
@@ -1482,16 +1455,17 @@ function useResourcePermissions(resource, options = {}) {
1482
1455
  // Pass resource name as pageId when appId is available to enable page permission checks
1483
1456
  true,
1484
1457
  // useCache
1485
- null,
1486
- // precomputedSuperAdmin - not checked yet
1458
+ isSuperAdminUser,
1459
+ // precomputedSuperAdmin - null if checking, false/true if checked
1487
1460
  void 0
1488
1461
  // appName
1489
1462
  );
1490
- const isLoading = useMemo10(() => {
1463
+ const isLoading = useMemo(() => {
1491
1464
  const waitingForScope = requireScope && scopeLoading;
1492
- return waitingForScope || createLoading || updateLoading || deleteLoading || enableRead && readLoading;
1493
- }, [scopeLoading, requireScope, createLoading, updateLoading, deleteLoading, readLoading, enableRead]);
1494
- const error = useMemo10(() => {
1465
+ const waitingForSuperAdmin = isSuperAdminUser === null && isCheckingSuperAdmin;
1466
+ return waitingForScope || waitingForSuperAdmin || createLoading || updateLoading || deleteLoading || enableRead && readLoading;
1467
+ }, [scopeLoading, requireScope, isSuperAdminUser, isCheckingSuperAdmin, createLoading, updateLoading, deleteLoading, readLoading, enableRead]);
1468
+ const error = useMemo(() => {
1495
1469
  if (scopeError) return scopeError;
1496
1470
  if (createError) return createError;
1497
1471
  if (updateError) return updateError;
@@ -1499,85 +1473,155 @@ function useResourcePermissions(resource, options = {}) {
1499
1473
  if (enableRead && readError) return readError;
1500
1474
  return null;
1501
1475
  }, [scopeError, createError, updateError, deleteError, readError, enableRead]);
1502
- return useMemo10(() => ({
1503
- canCreate: (res) => {
1504
- if (res !== resource) {
1505
- return false;
1506
- }
1507
- return canCreateResult;
1508
- },
1509
- canUpdate: (res) => {
1510
- if (res !== resource) {
1511
- return false;
1512
- }
1513
- return canUpdateResult;
1514
- },
1515
- canDelete: (res) => {
1516
- if (res !== resource) {
1517
- return false;
1518
- }
1519
- return canDeleteResult;
1520
- },
1521
- canRead: (res) => {
1522
- if (!enableRead) {
1476
+ return useMemo(() => {
1477
+ const createSuperAdminAwarePermission = (result) => {
1478
+ if (isSuperAdminUser === true) {
1523
1479
  return true;
1524
1480
  }
1525
- if (res !== resource) {
1526
- return false;
1527
- }
1528
- return canReadResult;
1529
- },
1530
- scope,
1531
- isLoading,
1532
- error
1533
- }), [
1481
+ return result;
1482
+ };
1483
+ return {
1484
+ canCreate: (res) => {
1485
+ if (res !== resource) {
1486
+ return false;
1487
+ }
1488
+ return createSuperAdminAwarePermission(canCreateResult);
1489
+ },
1490
+ canUpdate: (res) => {
1491
+ if (res !== resource) {
1492
+ return false;
1493
+ }
1494
+ return createSuperAdminAwarePermission(canUpdateResult);
1495
+ },
1496
+ canDelete: (res) => {
1497
+ if (res !== resource) {
1498
+ return false;
1499
+ }
1500
+ return createSuperAdminAwarePermission(canDeleteResult);
1501
+ },
1502
+ canRead: (res) => {
1503
+ if (!enableRead) {
1504
+ return true;
1505
+ }
1506
+ if (res !== resource) {
1507
+ return false;
1508
+ }
1509
+ return createSuperAdminAwarePermission(canReadResult);
1510
+ },
1511
+ scope,
1512
+ isLoading: isCheckingSuperAdmin || isLoading,
1513
+ error
1514
+ };
1515
+ }, [
1534
1516
  resource,
1517
+ isSuperAdminUser,
1518
+ isCheckingSuperAdmin,
1535
1519
  canCreateResult,
1536
- // This is already the boolean 'can' value
1537
1520
  canUpdateResult,
1538
- // This is already the boolean 'can' value
1539
1521
  canDeleteResult,
1540
- // This is already the boolean 'can' value
1541
1522
  canReadResult,
1542
- // This is already the boolean 'can' value
1543
1523
  enableRead,
1544
1524
  scope,
1545
1525
  isLoading,
1546
1526
  error
1547
1527
  ]);
1548
1528
  }
1549
-
1550
- // src/rbac/hooks/useRoleManagement.ts
1551
- import { useState as useState10, useCallback as useCallback9 } from "react";
1552
1529
  function useRoleManagement() {
1553
1530
  const { user, supabase } = useUnifiedAuth();
1554
- const [isLoading, setIsLoading] = useState10(false);
1555
- const [error, setError] = useState10(null);
1531
+ const [isLoading, setIsLoading] = useState(false);
1532
+ const [error, setError] = useState(null);
1556
1533
  if (!supabase) {
1557
1534
  throw new Error("useRoleManagement requires a Supabase client. Ensure UnifiedAuthProvider is configured.");
1558
1535
  }
1559
- const revokeEventAppRole = useCallback9(async (params) => {
1536
+ const revokeEventAppRole = useCallback(async (params) => {
1560
1537
  setIsLoading(true);
1561
1538
  setError(null);
1562
1539
  try {
1563
- const { data, error: rpcError } = await supabase.rpc("revoke_event_app_role", {
1540
+ const contextId = `${params.event_id}:${params.app_id}`;
1541
+ const rpcParams = {
1564
1542
  p_user_id: params.user_id,
1565
- p_organisation_id: params.organisation_id,
1566
- p_event_id: params.event_id,
1567
- p_app_id: params.app_id,
1568
- p_role: params.role,
1543
+ p_role_type: "event_app",
1544
+ p_role_name: params.role,
1545
+ p_context_id: contextId,
1569
1546
  p_revoked_by: params.revoked_by || user?.id || void 0
1570
- });
1547
+ };
1548
+ if (import.meta.env.MODE === "development") {
1549
+ console.log("[useRoleManagement] revokeEventAppRole called with:", rpcParams);
1550
+ }
1551
+ const { data, error: rpcError } = await supabase.rpc("rbac_role_revoke", rpcParams);
1571
1552
  if (rpcError) {
1572
- throw new Error(rpcError.message || "Failed to revoke role");
1553
+ if (import.meta.env.MODE === "development") {
1554
+ console.error("[useRoleManagement] RPC error:", {
1555
+ message: rpcError.message,
1556
+ details: rpcError.details,
1557
+ hint: rpcError.hint,
1558
+ code: rpcError.code,
1559
+ fullError: rpcError
1560
+ });
1561
+ }
1562
+ const errorMessage = rpcError.message || "Failed to revoke role - unknown RPC error";
1563
+ throw new Error(errorMessage);
1564
+ }
1565
+ if (import.meta.env.MODE === "development") {
1566
+ console.log("[useRoleManagement] RPC response:", {
1567
+ data,
1568
+ error: rpcError,
1569
+ dataType: Array.isArray(data) ? "array" : typeof data,
1570
+ dataLength: Array.isArray(data) ? data.length : "N/A"
1571
+ });
1572
+ }
1573
+ if (!data || !Array.isArray(data) || data.length === 0) {
1574
+ const errorMsg = "No response from database - role revocation may have failed";
1575
+ if (import.meta.env.MODE === "development") {
1576
+ console.error("[useRoleManagement] Empty or null data response:", {
1577
+ data,
1578
+ dataType: typeof data,
1579
+ isArray: Array.isArray(data),
1580
+ length: Array.isArray(data) ? data.length : "N/A"
1581
+ });
1582
+ }
1583
+ throw new Error(errorMsg);
1584
+ }
1585
+ const result = data[0];
1586
+ if (import.meta.env.MODE === "development") {
1587
+ console.log("[useRoleManagement] RPC result:", {
1588
+ success: result?.success,
1589
+ message: result?.message,
1590
+ error_code: result?.error_code,
1591
+ revoked_count: result?.revoked_count,
1592
+ fullResult: result
1593
+ });
1594
+ }
1595
+ if (!result || result.success !== true) {
1596
+ const errorMessage = result?.message || result?.error_code || "Role revocation failed";
1597
+ if (import.meta.env.MODE === "development") {
1598
+ console.error("[useRoleManagement] Role revocation failed:", {
1599
+ result,
1600
+ errorMessage,
1601
+ fullData: data,
1602
+ rpcParams
1603
+ });
1604
+ }
1605
+ return {
1606
+ success: false,
1607
+ message: result?.message || void 0,
1608
+ error: errorMessage
1609
+ };
1573
1610
  }
1574
1611
  return {
1575
- success: data === true,
1576
- message: data === true ? "Role revoked successfully" : "No role found to revoke",
1577
- error: data === false ? "No matching role found" : void 0
1612
+ success: true,
1613
+ message: result.message || "Role revoked successfully",
1614
+ error: void 0
1578
1615
  };
1579
1616
  } catch (err) {
1580
1617
  const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
1618
+ if (import.meta.env.MODE === "development") {
1619
+ console.error("[useRoleManagement] Exception in revokeEventAppRole:", {
1620
+ error: err,
1621
+ errorMessage,
1622
+ params
1623
+ });
1624
+ }
1581
1625
  setError(err instanceof Error ? err : new Error(errorMessage));
1582
1626
  return {
1583
1627
  success: false,
@@ -1586,8 +1630,8 @@ function useRoleManagement() {
1586
1630
  } finally {
1587
1631
  setIsLoading(false);
1588
1632
  }
1589
- }, [user?.id]);
1590
- const grantEventAppRole = useCallback9(async (params) => {
1633
+ }, [user?.id, supabase]);
1634
+ const grantEventAppRole = useCallback(async (params) => {
1591
1635
  setIsLoading(true);
1592
1636
  setError(null);
1593
1637
  try {
@@ -1626,7 +1670,7 @@ function useRoleManagement() {
1626
1670
  setIsLoading(false);
1627
1671
  }
1628
1672
  }, [user?.id]);
1629
- const revokeRoleById = useCallback9(async (roleId) => {
1673
+ const revokeRoleById = useCallback(async (roleId) => {
1630
1674
  setIsLoading(true);
1631
1675
  setError(null);
1632
1676
  try {
@@ -1643,13 +1687,28 @@ function useRoleManagement() {
1643
1687
  p_revoked_by: user?.id || void 0
1644
1688
  });
1645
1689
  if (rpcError) {
1646
- throw new Error(rpcError.message || "Failed to revoke role");
1690
+ const errorMessage = rpcError.message || "Failed to revoke role - unknown RPC error";
1691
+ throw new Error(errorMessage);
1647
1692
  }
1648
1693
  const result = Array.isArray(data) && data.length > 0 ? data[0] : null;
1694
+ if (!result) {
1695
+ return {
1696
+ success: false,
1697
+ error: void 0
1698
+ };
1699
+ }
1700
+ if (result.success === false) {
1701
+ const errorMessage = result.message || result.error_code || "Role revocation failed";
1702
+ return {
1703
+ success: false,
1704
+ message: result.message || void 0,
1705
+ error: errorMessage
1706
+ };
1707
+ }
1649
1708
  return {
1650
- success: result?.success === true,
1651
- message: result?.message || void 0,
1652
- error: result?.success === false ? result?.message || result?.error_code || "Unknown error" : void 0
1709
+ success: true,
1710
+ message: result.message || "Role revoked successfully",
1711
+ error: void 0
1653
1712
  };
1654
1713
  } catch (err) {
1655
1714
  const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
@@ -1662,7 +1721,7 @@ function useRoleManagement() {
1662
1721
  setIsLoading(false);
1663
1722
  }
1664
1723
  }, [user?.id, supabase]);
1665
- const grantGlobalRole = useCallback9(async (params) => {
1724
+ const grantGlobalRole = useCallback(async (params) => {
1666
1725
  setIsLoading(true);
1667
1726
  setError(null);
1668
1727
  try {
@@ -1701,7 +1760,7 @@ function useRoleManagement() {
1701
1760
  setIsLoading(false);
1702
1761
  }
1703
1762
  }, [user?.id, supabase]);
1704
- const revokeGlobalRole = useCallback9(async (params) => {
1763
+ const revokeGlobalRole = useCallback(async (params) => {
1705
1764
  setIsLoading(true);
1706
1765
  setError(null);
1707
1766
  try {
@@ -1714,7 +1773,14 @@ function useRoleManagement() {
1714
1773
  p_revoked_by: params.revoked_by || user?.id || void 0
1715
1774
  });
1716
1775
  if (rpcError) {
1717
- throw new Error(rpcError.message || "Failed to revoke role");
1776
+ const errorParts = [
1777
+ rpcError.message,
1778
+ rpcError.details,
1779
+ rpcError.hint,
1780
+ rpcError.code ? `Error code: ${rpcError.code}` : null
1781
+ ].filter(Boolean);
1782
+ const errorMessage = errorParts.length > 0 ? errorParts.join(" | ") : "Failed to revoke role - unknown RPC error";
1783
+ throw new Error(errorMessage);
1718
1784
  }
1719
1785
  const result = Array.isArray(data) && data.length > 0 ? data[0] : null;
1720
1786
  return {
@@ -1733,7 +1799,7 @@ function useRoleManagement() {
1733
1799
  setIsLoading(false);
1734
1800
  }
1735
1801
  }, [user?.id, supabase]);
1736
- const grantOrganisationRole = useCallback9(async (params) => {
1802
+ const grantOrganisationRole = useCallback(async (params) => {
1737
1803
  setIsLoading(true);
1738
1804
  setError(null);
1739
1805
  try {
@@ -1772,7 +1838,7 @@ function useRoleManagement() {
1772
1838
  setIsLoading(false);
1773
1839
  }
1774
1840
  }, [user?.id, supabase]);
1775
- const revokeOrganisationRole = useCallback9(async (params) => {
1841
+ const revokeOrganisationRole = useCallback(async (params) => {
1776
1842
  setIsLoading(true);
1777
1843
  setError(null);
1778
1844
  try {
@@ -1785,7 +1851,14 @@ function useRoleManagement() {
1785
1851
  p_revoked_by: params.revoked_by || user?.id || void 0
1786
1852
  });
1787
1853
  if (rpcError) {
1788
- throw new Error(rpcError.message || "Failed to revoke role");
1854
+ const errorParts = [
1855
+ rpcError.message,
1856
+ rpcError.details,
1857
+ rpcError.hint,
1858
+ rpcError.code ? `Error code: ${rpcError.code}` : null
1859
+ ].filter(Boolean);
1860
+ const errorMessage = errorParts.length > 0 ? errorParts.join(" | ") : "Failed to revoke role - unknown RPC error";
1861
+ throw new Error(errorMessage);
1789
1862
  }
1790
1863
  const result = Array.isArray(data) && data.length > 0 ? data[0] : null;
1791
1864
  return {
@@ -1820,13 +1893,10 @@ function useRoleManagement() {
1820
1893
  error
1821
1894
  };
1822
1895
  }
1823
-
1824
- // src/rbac/hooks/useSecureSupabase.ts
1825
- import { useMemo as useMemo11, useRef as useRef4 } from "react";
1826
1896
  var secureClientCache = /* @__PURE__ */ new Map();
1827
1897
  var MAX_CACHE_SIZE = 5;
1828
- function getCacheKey(organisationId, eventId, appId, isSuperAdmin) {
1829
- return `${organisationId || "no-org"}-${eventId || "no-event"}-${appId || "no-app"}-${isSuperAdmin ? "super" : "regular"}`;
1898
+ function getCacheKey(organisationId, eventId, appId, isSuperAdmin2) {
1899
+ return `${organisationId || "no-org"}-${eventId || "no-event"}-${appId || "no-app"}-${isSuperAdmin2 ? "super" : "regular"}`;
1830
1900
  }
1831
1901
  function getSupabaseConfig() {
1832
1902
  const getEnvVar = (key) => {
@@ -1852,28 +1922,26 @@ function useSecureSupabase(baseClient) {
1852
1922
  const { selectedEvent } = eventsContext;
1853
1923
  const eventLoading = "eventLoading" in eventsContext ? eventsContext.eventLoading : false;
1854
1924
  const { superAdminContext } = useOrganisationSecurity();
1855
- const isSuperAdmin = superAdminContext.isSuperAdmin;
1925
+ const isSuperAdmin2 = superAdminContext.isSuperAdmin;
1856
1926
  const { resolvedScope } = useResolvedScope({
1857
1927
  supabase: authSupabase || null,
1858
1928
  selectedOrganisationId: selectedOrganisation?.id || null,
1859
- selectedEventId: selectedEvent?.event_id || null
1929
+ selectedEventId: selectedEvent?.event_id || null,
1930
+ selectedEventOrganisationId: selectedEvent?.organisation_id || null
1860
1931
  });
1861
- const prevContextRef = useRef4({
1932
+ const prevContextRef = useRef({
1862
1933
  organisationId: void 0,
1863
1934
  eventId: void 0,
1864
1935
  appId: void 0
1865
1936
  });
1866
- return useMemo11(() => {
1867
- if (eventLoading) {
1868
- return baseClient || authSupabase || null;
1869
- }
1937
+ return useMemo(() => {
1870
1938
  const organisationId = resolvedScope?.organisationId;
1871
1939
  const eventId = resolvedScope?.eventId || selectedEvent?.event_id;
1872
1940
  const appId = resolvedScope?.appId;
1873
- const canCreateSecureClient = user?.id && (isSuperAdmin || organisationId);
1941
+ const canCreateSecureClient = user?.id && (isSuperAdmin2 || organisationId);
1874
1942
  if (canCreateSecureClient) {
1875
1943
  prevContextRef.current = { organisationId, eventId, appId };
1876
- const cacheKey = getCacheKey(organisationId, eventId, appId, isSuperAdmin);
1944
+ const cacheKey = getCacheKey(organisationId, eventId, appId, isSuperAdmin2);
1877
1945
  const cachedClient = secureClientCache.get(cacheKey);
1878
1946
  if (cachedClient) {
1879
1947
  return cachedClient.getClient();
@@ -1886,14 +1954,14 @@ function useSecureSupabase(baseClient) {
1886
1954
  return baseClient || authSupabase || null;
1887
1955
  }
1888
1956
  try {
1889
- const effectiveOrganisationId = isSuperAdmin ? organisationId || null : organisationId;
1957
+ const effectiveOrganisationId = isSuperAdmin2 ? organisationId || null : organisationId;
1890
1958
  const baseForSecureClient = baseClient || authSupabase || null;
1891
1959
  const secureClient = baseForSecureClient ? fromSupabaseClient(
1892
1960
  baseForSecureClient,
1893
1961
  effectiveOrganisationId ?? null,
1894
1962
  eventId,
1895
1963
  appId,
1896
- isSuperAdmin
1964
+ isSuperAdmin2
1897
1965
  ) : createSecureClient(
1898
1966
  config.url,
1899
1967
  config.key,
@@ -1902,7 +1970,7 @@ function useSecureSupabase(baseClient) {
1902
1970
  eventId,
1903
1971
  appId,
1904
1972
  // appId is string | undefined, UUID is string alias
1905
- isSuperAdmin
1973
+ isSuperAdmin2
1906
1974
  // Pass super admin status for conditional filtering
1907
1975
  );
1908
1976
  secureClientCache.set(cacheKey, secureClient);
@@ -1926,31 +1994,10 @@ function useSecureSupabase(baseClient) {
1926
1994
  selectedEvent?.event_id,
1927
1995
  user?.id,
1928
1996
  eventLoading,
1929
- isSuperAdmin,
1997
+ isSuperAdmin2,
1930
1998
  baseClient,
1931
1999
  authSupabase
1932
2000
  ]);
1933
2001
  }
1934
2002
 
1935
- export {
1936
- SECURE_CLIENT_SYMBOL,
1937
- isSecureClient,
1938
- warnIfInsecureClient,
1939
- SecureSupabaseClient,
1940
- createSecureClient,
1941
- fromSupabaseClient,
1942
- useResolvedScope,
1943
- useRBAC,
1944
- useAccessLevel,
1945
- useCachedPermissions,
1946
- scopeEqual,
1947
- useCan,
1948
- useHasAllPermissions,
1949
- useHasAnyPermission,
1950
- useMultiplePermissions,
1951
- usePermissions,
1952
- useResourcePermissions,
1953
- useRoleManagement,
1954
- useSecureSupabase
1955
- };
1956
- //# sourceMappingURL=chunk-HU2C6SSC.js.map
2003
+ export { Button, ButtonGroup, SECURE_CLIENT_SYMBOL, SecureSupabaseClient, Tooltip, TooltipContent, TooltipProvider, TooltipRoot, TooltipTrigger, createSecureClient, fromSupabaseClient, isSecureClient, scopeEqual, useAccessLevel, useCan, useEvents, useMultiplePermissions, usePermissions, useRBAC, useResolvedScope, useResourcePermissions, useRoleManagement, useSecureSupabase, warnIfInsecureClient };