@jmruthers/pace-core 0.6.1 → 0.6.3

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 (549) hide show
  1. package/CHANGELOG.md +88 -10
  2. package/cursor-rules/00-pace-core-compliance.mdc +46 -87
  3. package/cursor-rules/01-standards-compliance.mdc +16 -47
  4. package/cursor-rules/02-project-structure.mdc +4 -4
  5. package/cursor-rules/03-solid-principles.mdc +45 -164
  6. package/cursor-rules/04-testing-standards.mdc +22 -69
  7. package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
  8. package/cursor-rules/06-code-quality.mdc +42 -125
  9. package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
  10. package/cursor-rules/08-markup-quality.mdc +452 -0
  11. package/cursor-rules/CHANGELOG.md +18 -0
  12. package/cursor-rules/README.md +2 -1
  13. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-Cb34EQs3.d.ts} +63 -1
  14. package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
  15. package/dist/{DataTable-DQ7RSOHE.js → DataTable-THFPBKTP.js} +12 -10
  16. package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DEMpysFR.d.ts} +394 -171
  17. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CKvHP1MK.d.ts} +30 -8
  18. package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-KAGUYQ4J.js} +5 -4
  19. package/dist/{api-N774RPUA.js → api-IAGWF3ZG.js} +10 -10
  20. package/dist/{audit-B5P6FFIR.js → audit-V53FV5AG.js} +2 -2
  21. package/dist/{chunk-JBKQ3SAO.js → chunk-2T2IG7T7.js} +107 -57
  22. package/dist/chunk-2T2IG7T7.js.map +1 -0
  23. package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
  24. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  25. package/dist/{chunk-3XTALGJF.js → chunk-6Z7LTB3D.js} +69 -240
  26. package/dist/chunk-6Z7LTB3D.js.map +1 -0
  27. package/dist/{chunk-4ZC4GX36.js → chunk-CNCQDFLN.js} +199 -46
  28. package/dist/chunk-CNCQDFLN.js.map +1 -0
  29. package/dist/chunk-DGUM43GV.js +11 -0
  30. package/dist/{chunk-BYFSK72L.js → chunk-DWUBLJJM.js} +361 -187
  31. package/dist/chunk-DWUBLJJM.js.map +1 -0
  32. package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
  33. package/dist/chunk-FFQEQTNW.js.map +1 -0
  34. package/dist/chunk-FMUCXFII.js +76 -0
  35. package/dist/chunk-FMUCXFII.js.map +1 -0
  36. package/dist/{chunk-4N5C5XZU.js → chunk-HFZBI76P.js} +4 -4
  37. package/dist/chunk-HFZBI76P.js.map +1 -0
  38. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  39. package/dist/chunk-L4OXEN46.js.map +1 -0
  40. package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
  41. package/dist/chunk-M43Y4SSO.js.map +1 -0
  42. package/dist/{chunk-I7PSE6JW.js → chunk-M7MPQISP.js} +3 -76
  43. package/dist/chunk-M7MPQISP.js.map +1 -0
  44. package/dist/chunk-PQBSKX33.js +7793 -0
  45. package/dist/chunk-PQBSKX33.js.map +1 -0
  46. package/dist/chunk-QRPVRXYT.js +226 -0
  47. package/dist/chunk-QRPVRXYT.js.map +1 -0
  48. package/dist/{chunk-KNC55RTG.js → chunk-RWEBCB47.js} +194 -416
  49. package/dist/chunk-RWEBCB47.js.map +1 -0
  50. package/dist/{chunk-XM25TVIE.js → chunk-YDQHOZNA.js} +843 -388
  51. package/dist/chunk-YDQHOZNA.js.map +1 -0
  52. package/dist/{chunk-GLK6VM3F.js → chunk-ZNIWI3UC.js} +739 -737
  53. package/dist/chunk-ZNIWI3UC.js.map +1 -0
  54. package/dist/components.d.ts +5 -5
  55. package/dist/components.js +18 -16
  56. package/dist/components.js.map +1 -1
  57. package/dist/contextValidator-3JNZKUTX.js +9 -0
  58. package/dist/contextValidator-3JNZKUTX.js.map +1 -0
  59. package/dist/eslint-rules/pace-core-compliance.cjs +106 -0
  60. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  61. package/dist/hooks.d.ts +55 -122
  62. package/dist/hooks.js +10 -13
  63. package/dist/hooks.js.map +1 -1
  64. package/dist/index.d.ts +60 -13
  65. package/dist/index.js +30 -25
  66. package/dist/index.js.map +1 -1
  67. package/dist/providers.d.ts +21 -3
  68. package/dist/providers.js +4 -3
  69. package/dist/rbac/index.d.ts +210 -139
  70. package/dist/rbac/index.js +17 -13
  71. package/dist/styles/index.js +1 -1
  72. package/dist/theming/runtime.d.ts +1 -13
  73. package/dist/theming/runtime.js +2 -2
  74. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  75. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  76. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  77. package/dist/types.d.ts +2 -2
  78. package/dist/types.js +1 -1
  79. package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-i3qtoBgg.d.ts} +38 -17
  80. package/dist/utils.d.ts +4 -5
  81. package/dist/utils.js +17 -19
  82. package/dist/utils.js.map +1 -1
  83. package/docs/api/README.md +21 -17
  84. package/docs/api/modules.md +4191 -2967
  85. package/docs/architecture/database-schema-requirements.md +161 -0
  86. package/docs/components/context-selector.md +126 -0
  87. package/docs/core-concepts/rbac-system.md +3 -3
  88. package/docs/documentation-index.md +2 -4
  89. package/docs/getting-started/cursor-rules.md +2 -1
  90. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  91. package/docs/migration/MIGRATION_GUIDE.md +2 -24
  92. package/docs/migration/RBAC_SCOPE_MIGRATION.md +385 -0
  93. package/docs/migration/README.md +52 -6
  94. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  95. package/docs/migration/database-changes-december-2025.md +3 -3
  96. package/docs/pace-mint-fix-auto-selection.md +218 -0
  97. package/docs/pace-mint-rbac-setup.md +391 -0
  98. package/docs/rbac/event-based-apps.md +1 -1
  99. package/docs/rbac/getting-started.md +1 -1
  100. package/docs/rbac/quick-start.md +1 -1
  101. package/docs/rbac/secure-client-protection.md +330 -0
  102. package/docs/standards/README.md +1 -0
  103. package/package.json +4 -3
  104. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  105. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  106. package/scripts/audit/core/checks/bundle.cjs +142 -0
  107. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +784 -685
  108. package/scripts/audit/core/checks/config.cjs +54 -0
  109. package/scripts/audit/core/checks/coverage.cjs +84 -0
  110. package/scripts/audit/core/checks/dependencies.cjs +985 -0
  111. package/scripts/audit/core/checks/documentation.cjs +268 -0
  112. package/scripts/audit/core/checks/environment.cjs +116 -0
  113. package/scripts/audit/core/checks/error-handling.cjs +340 -0
  114. package/scripts/audit/core/checks/forms.cjs +172 -0
  115. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  116. package/scripts/audit/core/checks/hooks.cjs +334 -0
  117. package/scripts/audit/core/checks/imports.cjs +244 -0
  118. package/scripts/audit/core/checks/performance.cjs +325 -0
  119. package/scripts/audit/core/checks/routes.cjs +117 -0
  120. package/scripts/audit/core/checks/state.cjs +130 -0
  121. package/scripts/audit/core/checks/structure.cjs +65 -0
  122. package/scripts/audit/core/checks/style.cjs +584 -0
  123. package/scripts/audit/core/checks/testing.cjs +122 -0
  124. package/scripts/audit/core/checks/typescript.cjs +61 -0
  125. package/scripts/audit/core/scanner.cjs +199 -0
  126. package/scripts/audit/core/utils.cjs +137 -0
  127. package/scripts/audit/index.cjs +223 -0
  128. package/scripts/audit/reporters/console.cjs +151 -0
  129. package/scripts/audit/reporters/json.cjs +54 -0
  130. package/scripts/audit/reporters/markdown.cjs +124 -0
  131. package/scripts/audit-consuming-app.cjs +61 -936
  132. package/scripts/build-docs/build-decision.js +240 -0
  133. package/scripts/build-docs/cache-utils.js +105 -0
  134. package/scripts/build-docs/content-normalization.js +150 -0
  135. package/scripts/build-docs/file-utils.js +105 -0
  136. package/scripts/build-docs/git-utils.js +86 -0
  137. package/scripts/build-docs/hash-utils.js +116 -0
  138. package/scripts/build-docs/typedoc-runner.js +220 -0
  139. package/scripts/build-docs-incremental.js +77 -913
  140. package/scripts/utils/command-runner.js +16 -11
  141. package/scripts/validate-formats.js +61 -56
  142. package/scripts/validate-master.js +74 -69
  143. package/scripts/validate-pre-publish.js +70 -65
  144. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  145. package/src/components/Alert/Alert.test.tsx +12 -18
  146. package/src/components/Alert/Alert.tsx +5 -7
  147. package/src/components/Avatar/Avatar.test.tsx +4 -4
  148. package/src/components/Badge/Badge.tsx +14 -0
  149. package/src/components/Button/Button.tsx +22 -0
  150. package/src/components/Calendar/Calendar.tsx +8 -2
  151. package/src/components/Card/Card.tsx +4 -0
  152. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  153. package/src/components/Checkbox/Checkbox.tsx +2 -2
  154. package/src/components/ContextSelector/ContextSelector.tsx +384 -0
  155. package/src/components/ContextSelector/index.ts +3 -0
  156. package/src/components/DataTable/DataTable.tsx +38 -4
  157. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  158. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
  159. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  160. package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
  161. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  162. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
  163. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  164. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  165. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  166. package/src/components/DataTable/components/DataTableCore.tsx +196 -554
  167. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  168. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  169. package/src/components/DataTable/components/DataTableModals.tsx +8 -0
  170. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  171. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  172. package/src/components/DataTable/components/EditFields.tsx +307 -0
  173. package/src/components/DataTable/components/EditableRow.tsx +8 -0
  174. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  175. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  176. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  177. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  178. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  179. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  180. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  181. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  182. package/src/components/DataTable/components/UnifiedTableBody.tsx +63 -851
  183. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  184. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  185. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  186. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  187. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  188. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  189. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  190. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  191. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  192. package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
  193. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  194. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  195. package/src/components/DataTable/hooks/useDataTablePermissions.ts +127 -33
  196. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  197. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  198. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  199. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  200. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  201. package/src/components/DataTable/styles.ts +6 -6
  202. package/src/components/DataTable/types.ts +6 -10
  203. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  204. package/src/components/DataTable/utils/debugTools.ts +18 -113
  205. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  206. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  207. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  208. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  209. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  210. package/src/components/Dialog/Dialog.tsx +31 -3
  211. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  212. package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
  213. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  214. package/src/components/ErrorBoundary/index.ts +27 -2
  215. package/src/components/FileDisplay/FileDisplay.tsx +74 -28
  216. package/src/components/FileUpload/FileUpload.tsx +22 -2
  217. package/src/components/Footer/Footer.test.tsx +16 -16
  218. package/src/components/Footer/Footer.tsx +14 -11
  219. package/src/components/Form/Form.tsx +1 -0
  220. package/src/components/Header/Header.test.tsx +43 -73
  221. package/src/components/Header/Header.tsx +59 -49
  222. package/src/components/Input/Input.test.tsx +2 -2
  223. package/src/components/Input/Input.tsx +8 -4
  224. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  225. package/src/components/LoginForm/LoginForm.tsx +4 -0
  226. package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
  227. package/src/components/NavigationMenu/types.ts +56 -0
  228. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  229. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +10 -19
  230. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +2 -2
  231. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +5 -5
  232. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +13 -11
  233. package/src/components/PaceAppLayout/PaceAppLayout.tsx +167 -44
  234. package/src/components/PaceAppLayout/README.md +14 -17
  235. package/src/components/PaceAppLayout/test-setup.tsx +3 -4
  236. package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
  237. package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
  238. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  239. package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
  240. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  241. package/src/components/Select/Select.tsx +80 -434
  242. package/src/components/Select/context.ts +23 -0
  243. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  244. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  245. package/src/components/Select/hooks/useSelectState.ts +104 -0
  246. package/src/components/Select/index.ts +9 -1
  247. package/src/components/Select/types.ts +123 -0
  248. package/src/components/Select/utils/text.ts +26 -0
  249. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
  250. package/src/components/Switch/Switch.tsx +4 -4
  251. package/src/components/Tabs/Tabs.tsx +1 -1
  252. package/src/components/Toast/Toast.tsx +4 -0
  253. package/src/components/Tooltip/Tooltip.tsx +2 -2
  254. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  255. package/src/components/UserMenu/UserMenu.tsx +21 -18
  256. package/src/components/index.ts +7 -7
  257. package/src/eslint-rules/pace-core-compliance.cjs +106 -0
  258. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  259. package/src/hooks/__tests__/useAppConfig.unit.test.ts +4 -98
  260. package/src/hooks/index.ts +1 -2
  261. package/src/hooks/public/usePublicEvent.ts +4 -0
  262. package/src/hooks/public/usePublicEventLogo.ts +4 -0
  263. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  264. package/src/hooks/public/usePublicRouteParams.ts +4 -0
  265. package/src/hooks/services/useAuth.ts +32 -0
  266. package/src/hooks/services/useCurrentEvent.ts +6 -0
  267. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  268. package/src/hooks/useAppConfig.ts +15 -30
  269. package/src/hooks/useDebounce.ts +9 -0
  270. package/src/hooks/useEventTheme.ts +6 -0
  271. package/src/hooks/useFileDisplay.ts +81 -50
  272. package/src/hooks/useFileReference.ts +25 -7
  273. package/src/hooks/useFileUrl.ts +11 -1
  274. package/src/hooks/useFocusManagement.ts +14 -0
  275. package/src/hooks/useFocusTrap.ts +3 -0
  276. package/src/hooks/useInactivityTracker.ts +3 -0
  277. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  278. package/src/hooks/useOrganisationPermissions.ts +4 -0
  279. package/src/hooks/useOrganisationSecurity.ts +4 -0
  280. package/src/hooks/usePerformanceMonitor.ts +4 -0
  281. package/src/hooks/usePermissionCache.ts +7 -0
  282. package/src/hooks/useQueryCache.ts +12 -1
  283. package/src/hooks/useSessionRestoration.ts +4 -0
  284. package/src/hooks/useStorage.ts +4 -0
  285. package/src/hooks/useToast.ts +1 -1
  286. package/src/index.ts +6 -6
  287. package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
  288. package/src/providers/services/AuthServiceProvider.tsx +35 -7
  289. package/src/providers/services/EventServiceProvider.tsx +51 -5
  290. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  291. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +126 -134
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
  294. package/src/rbac/README.md +1 -1
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +1 -1
  296. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  297. package/src/rbac/adapters.tsx +12 -3
  298. package/src/rbac/api.test.ts +59 -51
  299. package/src/rbac/api.ts +246 -167
  300. package/src/rbac/components/NavigationProvider.tsx +4 -1
  301. package/src/rbac/components/PagePermissionGuard.tsx +185 -17
  302. package/src/rbac/components/RoleBasedRouter.tsx +5 -1
  303. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  304. package/src/rbac/components/SecureDataProvider.tsx +20 -5
  305. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  306. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  307. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  308. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  309. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  310. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  311. package/src/rbac/engine.ts +38 -14
  312. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +32 -21
  313. package/src/rbac/hooks/permissions/index.ts +7 -0
  314. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  315. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  316. package/src/rbac/hooks/permissions/useCan.ts +377 -0
  317. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  318. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  319. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  320. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  321. package/src/rbac/hooks/useCan.test.ts +64 -66
  322. package/src/rbac/hooks/usePermissions.ts +14 -995
  323. package/src/rbac/hooks/useRBAC.test.ts +1 -5
  324. package/src/rbac/hooks/useRBAC.ts +36 -37
  325. package/src/rbac/hooks/useResolvedScope.test.ts +120 -35
  326. package/src/rbac/hooks/useResolvedScope.ts +35 -40
  327. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  328. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  329. package/src/rbac/hooks/useSecureSupabase.ts +27 -7
  330. package/src/rbac/index.ts +7 -0
  331. package/src/rbac/permissions.ts +0 -30
  332. package/src/rbac/secureClient.test.ts +22 -18
  333. package/src/rbac/secureClient.ts +294 -68
  334. package/src/rbac/security.ts +0 -17
  335. package/src/rbac/types.ts +9 -0
  336. package/src/rbac/utils/__tests__/contextValidator.test.ts +64 -86
  337. package/src/rbac/utils/clientSecurity.ts +93 -0
  338. package/src/rbac/utils/contextValidator.ts +77 -168
  339. package/src/services/AuthService.ts +39 -7
  340. package/src/services/EventService.ts +186 -54
  341. package/src/services/OrganisationService.ts +81 -14
  342. package/src/services/__tests__/EventService.test.ts +1 -2
  343. package/src/services/base/BaseService.ts +3 -0
  344. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  345. package/src/theming/parseEventColours.ts +5 -19
  346. package/src/types/vitest-globals.d.ts +51 -26
  347. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  348. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  349. package/src/utils/__tests__/index.unit.test.ts +2 -2
  350. package/src/utils/audit/audit.ts +0 -3
  351. package/src/utils/core/cn.ts +1 -1
  352. package/src/utils/dynamic/dynamicUtils.ts +7 -4
  353. package/src/utils/file-reference/index.ts +53 -1
  354. package/src/utils/formatting/formatting.ts +8 -18
  355. package/src/utils/index.ts +0 -1
  356. package/dist/chunk-3QRJFVBR.js.map +0 -1
  357. package/dist/chunk-3XTALGJF.js.map +0 -1
  358. package/dist/chunk-4N5C5XZU.js.map +0 -1
  359. package/dist/chunk-4ZC4GX36.js.map +0 -1
  360. package/dist/chunk-7D4SUZUM.js +0 -38
  361. package/dist/chunk-BYFSK72L.js.map +0 -1
  362. package/dist/chunk-EXUD6RNJ.js +0 -451
  363. package/dist/chunk-EXUD6RNJ.js.map +0 -1
  364. package/dist/chunk-GLK6VM3F.js.map +0 -1
  365. package/dist/chunk-I7PSE6JW.js.map +0 -1
  366. package/dist/chunk-JBKQ3SAO.js.map +0 -1
  367. package/dist/chunk-KNC55RTG.js.map +0 -1
  368. package/dist/chunk-LXQLPRQ2.js.map +0 -1
  369. package/dist/chunk-R77UEZ4E.js.map +0 -1
  370. package/dist/chunk-SQGMNID3.js.map +0 -1
  371. package/dist/chunk-T33XF5ZC.js +0 -12922
  372. package/dist/chunk-T33XF5ZC.js.map +0 -1
  373. package/dist/chunk-XM25TVIE.js.map +0 -1
  374. package/docs/api/classes/ColumnFactory.md +0 -243
  375. package/docs/api/classes/ErrorBoundary.md +0 -144
  376. package/docs/api/classes/InvalidScopeError.md +0 -73
  377. package/docs/api/classes/Logger.md +0 -178
  378. package/docs/api/classes/MissingUserContextError.md +0 -66
  379. package/docs/api/classes/OrganisationContextRequiredError.md +0 -66
  380. package/docs/api/classes/PermissionDeniedError.md +0 -73
  381. package/docs/api/classes/RBACAuditManager.md +0 -297
  382. package/docs/api/classes/RBACCache.md +0 -322
  383. package/docs/api/classes/RBACEngine.md +0 -171
  384. package/docs/api/classes/RBACError.md +0 -76
  385. package/docs/api/classes/RBACNotInitializedError.md +0 -66
  386. package/docs/api/classes/SecureSupabaseClient.md +0 -160
  387. package/docs/api/classes/StorageUtils.md +0 -328
  388. package/docs/api/enums/FileCategory.md +0 -184
  389. package/docs/api/enums/LogLevel.md +0 -54
  390. package/docs/api/enums/RBACErrorCode.md +0 -228
  391. package/docs/api/enums/RPCFunction.md +0 -118
  392. package/docs/api/interfaces/AddressFieldProps.md +0 -241
  393. package/docs/api/interfaces/AddressFieldRef.md +0 -94
  394. package/docs/api/interfaces/AggregateConfig.md +0 -43
  395. package/docs/api/interfaces/AutocompleteOptions.md +0 -75
  396. package/docs/api/interfaces/AvatarProps.md +0 -128
  397. package/docs/api/interfaces/BadgeProps.md +0 -27
  398. package/docs/api/interfaces/ButtonProps.md +0 -53
  399. package/docs/api/interfaces/CalendarProps.md +0 -70
  400. package/docs/api/interfaces/CardProps.md +0 -66
  401. package/docs/api/interfaces/ColorPalette.md +0 -7
  402. package/docs/api/interfaces/ColorShade.md +0 -66
  403. package/docs/api/interfaces/ComplianceResult.md +0 -30
  404. package/docs/api/interfaces/DataAccessRecord.md +0 -96
  405. package/docs/api/interfaces/DataRecord.md +0 -11
  406. package/docs/api/interfaces/DataTableAction.md +0 -249
  407. package/docs/api/interfaces/DataTableColumn.md +0 -504
  408. package/docs/api/interfaces/DataTableProps.md +0 -625
  409. package/docs/api/interfaces/DataTableToolbarButton.md +0 -96
  410. package/docs/api/interfaces/DatabaseComplianceResult.md +0 -85
  411. package/docs/api/interfaces/DatabaseIssue.md +0 -41
  412. package/docs/api/interfaces/EmptyStateConfig.md +0 -61
  413. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +0 -235
  414. package/docs/api/interfaces/EventAppRoleData.md +0 -71
  415. package/docs/api/interfaces/ExportColumn.md +0 -90
  416. package/docs/api/interfaces/ExportOptions.md +0 -126
  417. package/docs/api/interfaces/FileDisplayProps.md +0 -249
  418. package/docs/api/interfaces/FileMetadata.md +0 -129
  419. package/docs/api/interfaces/FileReference.md +0 -118
  420. package/docs/api/interfaces/FileSizeLimits.md +0 -7
  421. package/docs/api/interfaces/FileUploadOptions.md +0 -139
  422. package/docs/api/interfaces/FileUploadProps.md +0 -293
  423. package/docs/api/interfaces/FooterProps.md +0 -105
  424. package/docs/api/interfaces/FormFieldProps.md +0 -166
  425. package/docs/api/interfaces/FormProps.md +0 -113
  426. package/docs/api/interfaces/GrantEventAppRoleParams.md +0 -122
  427. package/docs/api/interfaces/InactivityWarningModalProps.md +0 -115
  428. package/docs/api/interfaces/InputProps.md +0 -53
  429. package/docs/api/interfaces/LabelProps.md +0 -107
  430. package/docs/api/interfaces/LoggerConfig.md +0 -62
  431. package/docs/api/interfaces/LoginFormProps.md +0 -184
  432. package/docs/api/interfaces/NavigationAccessRecord.md +0 -107
  433. package/docs/api/interfaces/NavigationContextType.md +0 -164
  434. package/docs/api/interfaces/NavigationGuardProps.md +0 -139
  435. package/docs/api/interfaces/NavigationItem.md +0 -120
  436. package/docs/api/interfaces/NavigationMenuProps.md +0 -221
  437. package/docs/api/interfaces/NavigationProviderProps.md +0 -117
  438. package/docs/api/interfaces/Organisation.md +0 -140
  439. package/docs/api/interfaces/OrganisationContextType.md +0 -388
  440. package/docs/api/interfaces/OrganisationMembership.md +0 -140
  441. package/docs/api/interfaces/OrganisationProviderProps.md +0 -76
  442. package/docs/api/interfaces/OrganisationSecurityError.md +0 -62
  443. package/docs/api/interfaces/PaceAppLayoutProps.md +0 -406
  444. package/docs/api/interfaces/PaceLoginPageProps.md +0 -47
  445. package/docs/api/interfaces/PageAccessRecord.md +0 -85
  446. package/docs/api/interfaces/PagePermissionContextType.md +0 -140
  447. package/docs/api/interfaces/PagePermissionGuardProps.md +0 -153
  448. package/docs/api/interfaces/PagePermissionProviderProps.md +0 -119
  449. package/docs/api/interfaces/PaletteData.md +0 -41
  450. package/docs/api/interfaces/ParsedAddress.md +0 -120
  451. package/docs/api/interfaces/PermissionEnforcerProps.md +0 -153
  452. package/docs/api/interfaces/ProgressProps.md +0 -42
  453. package/docs/api/interfaces/ProtectedRouteProps.md +0 -97
  454. package/docs/api/interfaces/PublicPageFooterProps.md +0 -112
  455. package/docs/api/interfaces/PublicPageHeaderProps.md +0 -125
  456. package/docs/api/interfaces/PublicPageLayoutProps.md +0 -198
  457. package/docs/api/interfaces/QuickFix.md +0 -52
  458. package/docs/api/interfaces/RBACAccessValidateParams.md +0 -52
  459. package/docs/api/interfaces/RBACAccessValidateResult.md +0 -41
  460. package/docs/api/interfaces/RBACAuditLogParams.md +0 -85
  461. package/docs/api/interfaces/RBACAuditLogResult.md +0 -52
  462. package/docs/api/interfaces/RBACConfig.md +0 -133
  463. package/docs/api/interfaces/RBACContext.md +0 -52
  464. package/docs/api/interfaces/RBACLogger.md +0 -112
  465. package/docs/api/interfaces/RBACPageAccessCheckParams.md +0 -74
  466. package/docs/api/interfaces/RBACPerformanceMetrics.md +0 -138
  467. package/docs/api/interfaces/RBACPermissionCheckParams.md +0 -74
  468. package/docs/api/interfaces/RBACPermissionCheckResult.md +0 -52
  469. package/docs/api/interfaces/RBACPermissionsGetParams.md +0 -63
  470. package/docs/api/interfaces/RBACPermissionsGetResult.md +0 -63
  471. package/docs/api/interfaces/RBACResult.md +0 -58
  472. package/docs/api/interfaces/RBACRoleGrantParams.md +0 -63
  473. package/docs/api/interfaces/RBACRoleGrantResult.md +0 -52
  474. package/docs/api/interfaces/RBACRoleRevokeParams.md +0 -63
  475. package/docs/api/interfaces/RBACRoleRevokeResult.md +0 -52
  476. package/docs/api/interfaces/RBACRoleValidateParams.md +0 -52
  477. package/docs/api/interfaces/RBACRoleValidateResult.md +0 -63
  478. package/docs/api/interfaces/RBACRolesListParams.md +0 -52
  479. package/docs/api/interfaces/RBACRolesListResult.md +0 -74
  480. package/docs/api/interfaces/RBACSessionTrackParams.md +0 -74
  481. package/docs/api/interfaces/RBACSessionTrackResult.md +0 -52
  482. package/docs/api/interfaces/ResourcePermissions.md +0 -155
  483. package/docs/api/interfaces/RevokeEventAppRoleParams.md +0 -100
  484. package/docs/api/interfaces/RoleBasedRouterContextType.md +0 -151
  485. package/docs/api/interfaces/RoleBasedRouterProps.md +0 -156
  486. package/docs/api/interfaces/RoleManagementResult.md +0 -52
  487. package/docs/api/interfaces/RouteAccessRecord.md +0 -107
  488. package/docs/api/interfaces/RouteConfig.md +0 -134
  489. package/docs/api/interfaces/RuntimeComplianceResult.md +0 -55
  490. package/docs/api/interfaces/SecureDataContextType.md +0 -168
  491. package/docs/api/interfaces/SecureDataProviderProps.md +0 -132
  492. package/docs/api/interfaces/SessionRestorationLoaderProps.md +0 -34
  493. package/docs/api/interfaces/SetupIssue.md +0 -41
  494. package/docs/api/interfaces/StorageConfig.md +0 -41
  495. package/docs/api/interfaces/StorageFileInfo.md +0 -74
  496. package/docs/api/interfaces/StorageFileMetadata.md +0 -151
  497. package/docs/api/interfaces/StorageListOptions.md +0 -99
  498. package/docs/api/interfaces/StorageListResult.md +0 -41
  499. package/docs/api/interfaces/StorageUploadOptions.md +0 -101
  500. package/docs/api/interfaces/StorageUploadResult.md +0 -63
  501. package/docs/api/interfaces/StorageUrlOptions.md +0 -60
  502. package/docs/api/interfaces/StyleImport.md +0 -19
  503. package/docs/api/interfaces/SwitchProps.md +0 -34
  504. package/docs/api/interfaces/TabsContentProps.md +0 -9
  505. package/docs/api/interfaces/TabsListProps.md +0 -9
  506. package/docs/api/interfaces/TabsProps.md +0 -9
  507. package/docs/api/interfaces/TabsTriggerProps.md +0 -50
  508. package/docs/api/interfaces/TextareaProps.md +0 -53
  509. package/docs/api/interfaces/ToastActionElement.md +0 -9
  510. package/docs/api/interfaces/ToastProps.md +0 -9
  511. package/docs/api/interfaces/UnifiedAuthContextType.md +0 -820
  512. package/docs/api/interfaces/UnifiedAuthProviderProps.md +0 -171
  513. package/docs/api/interfaces/UseFormDialogOptions.md +0 -62
  514. package/docs/api/interfaces/UseFormDialogReturn.md +0 -117
  515. package/docs/api/interfaces/UseInactivityTrackerOptions.md +0 -136
  516. package/docs/api/interfaces/UseInactivityTrackerReturn.md +0 -123
  517. package/docs/api/interfaces/UsePublicEventLogoOptions.md +0 -87
  518. package/docs/api/interfaces/UsePublicEventLogoReturn.md +0 -81
  519. package/docs/api/interfaces/UsePublicEventOptions.md +0 -34
  520. package/docs/api/interfaces/UsePublicEventReturn.md +0 -68
  521. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +0 -47
  522. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +0 -120
  523. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +0 -94
  524. package/docs/api/interfaces/UseResolvedScopeOptions.md +0 -47
  525. package/docs/api/interfaces/UseResolvedScopeReturn.md +0 -47
  526. package/docs/api/interfaces/UseResourcePermissionsOptions.md +0 -34
  527. package/docs/api/interfaces/UserEventAccess.md +0 -118
  528. package/docs/api/interfaces/UserMenuProps.md +0 -86
  529. package/docs/api/interfaces/UserProfile.md +0 -63
  530. package/docs/migration/quick-migration-guide.md +0 -356
  531. package/docs/migration/service-architecture.md +0 -281
  532. package/src/components/EventSelector/EventSelector.test.tsx +0 -720
  533. package/src/components/EventSelector/EventSelector.tsx +0 -420
  534. package/src/components/EventSelector/index.ts +0 -3
  535. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +0 -784
  536. package/src/components/OrganisationSelector/OrganisationSelector.tsx +0 -324
  537. package/src/components/OrganisationSelector/index.ts +0 -9
  538. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  539. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  540. package/src/hooks/useSecureDataAccess.ts +0 -681
  541. /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-THFPBKTP.js.map} +0 -0
  542. /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-KAGUYQ4J.js.map} +0 -0
  543. /package/dist/{api-N774RPUA.js.map → api-IAGWF3ZG.js.map} +0 -0
  544. /package/dist/{audit-B5P6FFIR.js.map → audit-V53FV5AG.js.map} +0 -0
  545. /package/dist/{chunk-7D4SUZUM.js.map → chunk-DGUM43GV.js.map} +0 -0
  546. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  547. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  548. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  549. /package/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
@@ -3,76 +3,19 @@ import {
3
3
  emitAuditEvent,
4
4
  setGlobalAuditManager
5
5
  } from "./chunk-63FOKYGO.js";
6
+ import {
7
+ ContextValidator,
8
+ InvalidScopeError,
9
+ MissingUserContextError,
10
+ OrganisationContextRequiredError,
11
+ PermissionDeniedError,
12
+ RBACError,
13
+ RBACNotInitializedError
14
+ } from "./chunk-QRPVRXYT.js";
6
15
  import {
7
16
  createLogger
8
17
  } from "./chunk-PWLANIRT.js";
9
18
 
10
- // src/rbac/types.ts
11
- var RBACError = class extends Error {
12
- constructor(message, code, context) {
13
- super(message);
14
- this.code = code;
15
- this.context = context;
16
- this.name = "RBACError";
17
- }
18
- };
19
- var PermissionDeniedError = class extends RBACError {
20
- constructor(permission, context) {
21
- super(
22
- `Permission denied: ${permission}`,
23
- "PERMISSION_DENIED",
24
- { permission, ...context }
25
- );
26
- this.name = "PermissionDeniedError";
27
- }
28
- };
29
- var OrganisationContextRequiredError = class extends RBACError {
30
- constructor() {
31
- super(
32
- "Organisation context is required for this operation",
33
- "ORGANISATION_CONTEXT_REQUIRED"
34
- );
35
- this.name = "OrganisationContextRequiredError";
36
- }
37
- };
38
- var EventContextRequiredError = class extends RBACError {
39
- constructor() {
40
- super(
41
- "Event context is required for this operation",
42
- "EVENT_CONTEXT_REQUIRED"
43
- );
44
- this.name = "EventContextRequiredError";
45
- }
46
- };
47
- var RBACNotInitializedError = class extends RBACError {
48
- constructor() {
49
- super(
50
- "RBAC system not initialized. Please call setupRBAC(supabase) before using any RBAC components or hooks. See: https://docs.pace-core.dev/rbac/setup",
51
- "RBAC_NOT_INITIALIZED"
52
- );
53
- this.name = "RBACNotInitializedError";
54
- }
55
- };
56
- var InvalidScopeError = class extends RBACError {
57
- constructor(scope, reason) {
58
- super(
59
- `Invalid scope provided: ${JSON.stringify(scope)}. ${reason}`,
60
- "INVALID_SCOPE",
61
- { scope, reason }
62
- );
63
- this.name = "InvalidScopeError";
64
- }
65
- };
66
- var MissingUserContextError = class extends RBACError {
67
- constructor() {
68
- super(
69
- "User context is required but not available. Make sure to wrap your app with an auth provider.",
70
- "MISSING_USER_CONTEXT"
71
- );
72
- this.name = "MissingUserContextError";
73
- }
74
- };
75
-
76
19
  // src/rbac/cache.ts
77
20
  var RBACCache = class {
78
21
  constructor() {
@@ -694,228 +637,8 @@ function mapErrorCategoryToSecurityEventType(category) {
694
637
  }
695
638
  }
696
639
 
697
- // src/rbac/utils/eventContext.ts
698
- var orgDerivationCache = /* @__PURE__ */ new Map();
699
- var MAX_CACHE_SIZE = 100;
700
- async function getOrganisationFromEvent(supabase, eventId) {
701
- if (orgDerivationCache.has(eventId)) {
702
- return orgDerivationCache.get(eventId) ?? null;
703
- }
704
- const { data, error } = await supabase.from("core_events").select("organisation_id").eq("event_id", eventId).single();
705
- let organisationId = null;
706
- if (error || !data) {
707
- organisationId = null;
708
- } else if (data.organisation_id) {
709
- organisationId = data.organisation_id;
710
- } else {
711
- organisationId = null;
712
- }
713
- if (orgDerivationCache.size >= MAX_CACHE_SIZE) {
714
- const firstKey = orgDerivationCache.keys().next().value;
715
- if (firstKey) {
716
- orgDerivationCache.delete(firstKey);
717
- }
718
- }
719
- orgDerivationCache.set(eventId, organisationId);
720
- return organisationId;
721
- }
722
-
723
- // src/rbac/utils/contextValidator.ts
724
- var log2 = createLogger("ContextValidator");
725
- function allowsOptionalContexts(appName) {
726
- return appName === "PORTAL" || appName === "ADMIN";
727
- }
728
- var ContextValidator = class {
729
- /**
730
- * Validate scope against app requirements
731
- *
732
- * @param scope - Current scope
733
- * @param appConfig - App configuration (requires_event flag)
734
- * @param appName - App name (for PORTAL/ADMIN special case)
735
- * @returns Validation result with resolved scope
736
- */
737
- static async validateScope(scope, appConfig, appName) {
738
- if (allowsOptionalContexts(appName)) {
739
- return {
740
- isValid: true,
741
- resolvedScope: {
742
- organisationId: scope.organisationId,
743
- eventId: scope.eventId,
744
- appId: scope.appId
745
- },
746
- error: null
747
- };
748
- }
749
- if (!appConfig) {
750
- if (!scope.organisationId) {
751
- return {
752
- isValid: false,
753
- resolvedScope: null,
754
- error: new OrganisationContextRequiredError()
755
- };
756
- }
757
- return {
758
- isValid: true,
759
- resolvedScope: scope,
760
- error: null
761
- };
762
- }
763
- if (appConfig.requires_event) {
764
- if (!scope.eventId) {
765
- return {
766
- isValid: false,
767
- resolvedScope: null,
768
- error: new EventContextRequiredError()
769
- };
770
- }
771
- return {
772
- isValid: true,
773
- resolvedScope: scope,
774
- error: null
775
- };
776
- }
777
- if (!scope.organisationId) {
778
- return {
779
- isValid: false,
780
- resolvedScope: null,
781
- error: new OrganisationContextRequiredError()
782
- };
783
- }
784
- return {
785
- isValid: true,
786
- resolvedScope: scope,
787
- error: null
788
- };
789
- }
790
- /**
791
- * Resolve required context and derive missing values
792
- *
793
- * @param scope - Current scope
794
- * @param appConfig - App configuration
795
- * @param appName - App name (for PORTAL/ADMIN special case)
796
- * @param supabase - Supabase client (for deriving org from event)
797
- * @returns Resolved scope with all required context
798
- */
799
- static async resolveRequiredContext(scope, appConfig, appName, supabase) {
800
- if (allowsOptionalContexts(appName)) {
801
- return {
802
- isValid: true,
803
- resolvedScope: {
804
- organisationId: scope.organisationId,
805
- eventId: scope.eventId,
806
- appId: scope.appId
807
- },
808
- error: null
809
- };
810
- }
811
- if (!appConfig) {
812
- if (!scope.organisationId) {
813
- return {
814
- isValid: false,
815
- resolvedScope: null,
816
- error: new OrganisationContextRequiredError()
817
- };
818
- }
819
- return {
820
- isValid: true,
821
- resolvedScope: scope,
822
- error: null
823
- };
824
- }
825
- if (appConfig.requires_event) {
826
- if (!scope.eventId) {
827
- return {
828
- isValid: false,
829
- resolvedScope: null,
830
- error: new EventContextRequiredError()
831
- };
832
- }
833
- let organisationId = scope.organisationId;
834
- if (!organisationId && supabase && scope.eventId) {
835
- try {
836
- const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
837
- organisationId = derivedOrgId || void 0;
838
- if (!organisationId) {
839
- return {
840
- isValid: false,
841
- resolvedScope: null,
842
- error: new Error("Could not resolve organisation from event context")
843
- };
844
- }
845
- } catch (error) {
846
- log2.error("Failed to derive org from event:", error);
847
- return {
848
- isValid: false,
849
- resolvedScope: null,
850
- error: error instanceof Error ? error : new Error("Failed to derive organisation from event")
851
- };
852
- }
853
- } else if (!organisationId) {
854
- return {
855
- isValid: false,
856
- resolvedScope: null,
857
- error: new Error("Event context requires organisationId but it could not be derived (supabase client not available)")
858
- };
859
- }
860
- return {
861
- isValid: true,
862
- resolvedScope: {
863
- organisationId,
864
- eventId: scope.eventId,
865
- appId: scope.appId
866
- },
867
- error: null
868
- };
869
- }
870
- if (!scope.organisationId) {
871
- return {
872
- isValid: false,
873
- resolvedScope: null,
874
- error: new OrganisationContextRequiredError()
875
- };
876
- }
877
- return {
878
- isValid: true,
879
- resolvedScope: scope,
880
- error: null
881
- };
882
- }
883
- /**
884
- * Derive organisation ID from event ID
885
- *
886
- * @param supabase - Supabase client
887
- * @param eventId - Event ID
888
- * @returns Organisation ID or null
889
- */
890
- static async deriveOrgFromEvent(supabase, eventId) {
891
- return getOrganisationFromEvent(supabase, eventId);
892
- }
893
- /**
894
- * Check if context is ready for permission checks
895
- *
896
- * @param scope - Current scope
897
- * @param appConfig - App configuration
898
- * @param appName - App name
899
- * @param hasSelectedEvent - Whether event is selected
900
- * @param hasSelectedOrganisation - Whether organisation is selected
901
- * @returns True if context is ready
902
- */
903
- static isContextReady(scope, appConfig, appName, hasSelectedEvent, hasSelectedOrganisation) {
904
- if (allowsOptionalContexts(appName)) {
905
- return true;
906
- }
907
- if (!appConfig) {
908
- return !!hasSelectedOrganisation || !!scope.organisationId;
909
- }
910
- if (appConfig.requires_event) {
911
- return !!hasSelectedEvent || !!scope.eventId;
912
- }
913
- return !!hasSelectedOrganisation || !!scope.organisationId;
914
- }
915
- };
916
-
917
640
  // src/rbac/security.ts
918
- var log3 = createLogger("RBACSecurity");
641
+ var log2 = createLogger("RBACSecurity");
919
642
  var RBACSecurityValidator = class {
920
643
  /**
921
644
  * Validate permission string format
@@ -1021,17 +744,6 @@ var RBACSecurityValidator = class {
1021
744
  static async checkRateLimit(userId, operation) {
1022
745
  return true;
1023
746
  }
1024
- /**
1025
- * Validate context requirements for security
1026
- * @param scope - Scope object
1027
- * @param appConfig - App configuration
1028
- * @param appName - App name (for PORTAL special case)
1029
- * @returns True if context is valid, false otherwise
1030
- */
1031
- static async validateContextRequirements(scope, appConfig, appName) {
1032
- const validation = await ContextValidator.validateScope(scope, appConfig || null, appName);
1033
- return validation.isValid;
1034
- }
1035
747
  // Only warn once per 5 seconds per user
1036
748
  static logSecurityEvent(event) {
1037
749
  const securityEvent = {
@@ -1049,7 +761,7 @@ var RBACSecurityValidator = class {
1049
761
  this.rateLimitWarningCount.set(event.userId, userWarning);
1050
762
  return;
1051
763
  } else {
1052
- log3.warn("Security event (throttled):", {
764
+ log2.warn("Security event (throttled):", {
1053
765
  ...securityEvent,
1054
766
  details: {
1055
767
  ...securityEvent.details,
@@ -1062,11 +774,11 @@ var RBACSecurityValidator = class {
1062
774
  }
1063
775
  } else {
1064
776
  this.rateLimitWarningCount.set(event.userId, { count: 0, lastWarning: now });
1065
- log3.warn("Security event:", securityEvent);
777
+ log2.warn("Security event:", securityEvent);
1066
778
  return;
1067
779
  }
1068
780
  }
1069
- log3.warn("Security event:", securityEvent);
781
+ log2.warn("Security event:", securityEvent);
1070
782
  }
1071
783
  /**
1072
784
  * Get severity level for security event
@@ -1669,11 +1381,30 @@ var RBACEngine = class {
1669
1381
  if (cached !== null) {
1670
1382
  return cached;
1671
1383
  }
1384
+ const startTime = Date.now();
1672
1385
  const now = (/* @__PURE__ */ new Date()).toISOString();
1673
- const { data, error } = await this.supabase.from("rbac_global_roles").select("role").eq("user_id", userId).eq("role", "super_admin").lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).limit(1);
1674
- const isSuperAdmin2 = !error && data && data.length > 0;
1675
- rbacCache.set(cacheKey, isSuperAdmin2, 6e4);
1676
- return Boolean(isSuperAdmin2);
1386
+ try {
1387
+ const { data, error } = await this.supabase.from("rbac_global_roles").select("role").eq("user_id", userId).eq("role", "super_admin").lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).limit(1);
1388
+ const elapsed = Date.now() - startTime;
1389
+ if (elapsed > 2e3) {
1390
+ console.warn("[RBACEngine] Super admin check took longer than expected", {
1391
+ userId,
1392
+ elapsedMs: elapsed,
1393
+ error: error?.message
1394
+ });
1395
+ }
1396
+ const isSuperAdmin2 = !error && data && data.length > 0;
1397
+ rbacCache.set(cacheKey, isSuperAdmin2, 6e4);
1398
+ return Boolean(isSuperAdmin2);
1399
+ } catch (err) {
1400
+ const elapsed = Date.now() - startTime;
1401
+ console.error("[RBACEngine] Error checking super admin", {
1402
+ userId,
1403
+ error: err,
1404
+ elapsedMs: elapsed
1405
+ });
1406
+ return false;
1407
+ }
1677
1408
  }
1678
1409
  /**
1679
1410
  * Resolve a page ID to UUID if it's a page name
@@ -1877,7 +1608,7 @@ function getInFlightRequestCount() {
1877
1608
  }
1878
1609
 
1879
1610
  // src/rbac/api.ts
1880
- var log4 = createLogger("RBACAPI");
1611
+ var log3 = createLogger("RBACAPI");
1881
1612
  var globalEngine = null;
1882
1613
  function setupRBAC(supabase, config) {
1883
1614
  const logger = getRBACLogger();
@@ -1908,73 +1639,76 @@ function setupRBAC(supabase, config) {
1908
1639
  enablePerformanceMonitoring();
1909
1640
  }
1910
1641
  }
1642
+ function isRBACInitialized() {
1643
+ return globalEngine !== null;
1644
+ }
1911
1645
  function getEngine() {
1912
1646
  if (!globalEngine) {
1913
1647
  throw new RBACNotInitializedError();
1914
1648
  }
1915
1649
  return globalEngine;
1916
1650
  }
1917
- async function getAccessLevel(input, appConfig, appName) {
1918
- const engine = getEngine();
1919
- const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
1920
- if (isSuperAdminUser) {
1921
- return "super";
1922
- }
1923
- let resolvedAppConfig = appConfig ?? null;
1924
- let resolvedAppName = appName;
1925
- if (!resolvedAppConfig && input.scope.appId) {
1926
- resolvedAppConfig = await getAppConfig(input.scope.appId);
1927
- }
1928
- const validation = await ContextValidator.resolveRequiredContext(
1929
- input.scope,
1930
- resolvedAppConfig,
1931
- resolvedAppName,
1932
- engine["supabase"]
1933
- );
1934
- if (!validation.isValid || !validation.resolvedScope) {
1935
- throw validation.error || new OrganisationContextRequiredError();
1651
+ async function getAccessLevel(input, appName) {
1652
+ try {
1653
+ const engine = getEngine();
1654
+ const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
1655
+ if (isSuperAdminUser) {
1656
+ return "super";
1657
+ }
1658
+ const validation = await ContextValidator.resolveScopeForPage(
1659
+ input.scope,
1660
+ "organisation",
1661
+ // Default to organisation scope when no page context
1662
+ appName,
1663
+ engine["supabase"]
1664
+ );
1665
+ if (!validation.isValid || !validation.resolvedScope) {
1666
+ throw validation.error || new OrganisationContextRequiredError();
1667
+ }
1668
+ return engine.getAccessLevel({
1669
+ ...input,
1670
+ scope: validation.resolvedScope
1671
+ });
1672
+ } catch (error) {
1673
+ throw error;
1936
1674
  }
1937
- return engine.getAccessLevel({
1938
- ...input,
1939
- scope: validation.resolvedScope
1940
- });
1941
1675
  }
1942
- async function getPermissionMap(input, appConfig, appName) {
1943
- const engine = getEngine();
1944
- let resolvedAppConfig = appConfig ?? null;
1945
- let resolvedAppName = appName;
1946
- if (!resolvedAppConfig && input.scope.appId) {
1947
- resolvedAppConfig = await getAppConfig(input.scope.appId);
1948
- }
1949
- const validation = await ContextValidator.resolveRequiredContext(
1950
- input.scope,
1951
- resolvedAppConfig,
1952
- resolvedAppName,
1953
- engine["supabase"]
1954
- );
1955
- if (!validation.isValid || !validation.resolvedScope) {
1956
- throw validation.error || new OrganisationContextRequiredError();
1676
+ async function getPermissionMap(input, appName) {
1677
+ try {
1678
+ const engine = getEngine();
1679
+ const validation = await ContextValidator.resolveScopeForPage(
1680
+ input.scope,
1681
+ "organisation",
1682
+ // Default to organisation scope when no page context
1683
+ appName,
1684
+ engine["supabase"]
1685
+ );
1686
+ if (!validation.isValid || !validation.resolvedScope) {
1687
+ throw validation.error || new OrganisationContextRequiredError();
1688
+ }
1689
+ return engine.getPermissionMap({
1690
+ ...input,
1691
+ scope: validation.resolvedScope
1692
+ });
1693
+ } catch (error) {
1694
+ throw error;
1957
1695
  }
1958
- return engine.getPermissionMap({
1959
- ...input,
1960
- scope: validation.resolvedScope
1961
- });
1962
1696
  }
1963
1697
  async function resolveAppContext(input) {
1964
- const engine = getEngine();
1965
- return engine.resolveAppContext(input);
1698
+ try {
1699
+ const engine = getEngine();
1700
+ return await engine.resolveAppContext(input);
1701
+ } catch (error) {
1702
+ throw error;
1703
+ }
1966
1704
  }
1967
- async function getRoleContext(input, appConfig, appName) {
1705
+ async function getRoleContext(input, appName) {
1968
1706
  const engine = getEngine();
1969
- let resolvedAppConfig = appConfig ?? null;
1970
- let resolvedAppName = appName;
1971
- if (!resolvedAppConfig && input.scope.appId) {
1972
- resolvedAppConfig = await getAppConfig(input.scope.appId);
1973
- }
1974
- const validation = await ContextValidator.resolveRequiredContext(
1707
+ const validation = await ContextValidator.resolveScopeForPage(
1975
1708
  input.scope,
1976
- resolvedAppConfig,
1977
- resolvedAppName,
1709
+ "organisation",
1710
+ // Default to organisation scope when no page context
1711
+ appName,
1978
1712
  engine["supabase"]
1979
1713
  );
1980
1714
  if (!validation.isValid || !validation.resolvedScope) {
@@ -1985,17 +1719,18 @@ async function getRoleContext(input, appConfig, appName) {
1985
1719
  scope: validation.resolvedScope
1986
1720
  });
1987
1721
  }
1988
- async function isPermitted(input, appConfig, appName) {
1722
+ async function isPermitted(input, appName, precomputedSuperAdmin = null) {
1989
1723
  const engine = getEngine();
1990
- const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
1991
- if (isSuperAdminUser) {
1724
+ if (precomputedSuperAdmin === true) {
1992
1725
  return true;
1993
1726
  }
1994
- let resolvedAppConfig = appConfig ?? null;
1995
- let resolvedAppName = appName;
1996
- if (!resolvedAppConfig && input.scope.appId) {
1997
- resolvedAppConfig = await getAppConfig(input.scope.appId);
1727
+ if (precomputedSuperAdmin === null) {
1728
+ const isSuperAdminUser = await engine["checkSuperAdmin"](input.userId);
1729
+ if (isSuperAdminUser) {
1730
+ return true;
1731
+ }
1998
1732
  }
1733
+ let resolvedAppName = appName;
1999
1734
  if (!resolvedAppName && input.scope.appId) {
2000
1735
  try {
2001
1736
  const { data } = await engine["supabase"].from("rbac_apps").select("name").eq("id", input.scope.appId).eq("is_active", true).single();
@@ -2005,9 +1740,28 @@ async function isPermitted(input, appConfig, appName) {
2005
1740
  } catch (err) {
2006
1741
  }
2007
1742
  }
2008
- const validation = await ContextValidator.resolveRequiredContext(
1743
+ let pageScopeType;
1744
+ if (input.pageId) {
1745
+ try {
1746
+ const scopeType = await getPageScopeType(
1747
+ input.pageId,
1748
+ input.scope.appId,
1749
+ resolvedAppName
1750
+ );
1751
+ if (!scopeType) {
1752
+ throw new Error(`Page ${input.pageId} does not have scope_type set`);
1753
+ }
1754
+ pageScopeType = scopeType;
1755
+ } catch (err) {
1756
+ log3.error("Failed to get page scope type:", err);
1757
+ throw new Error(`Failed to determine page scope type: ${err instanceof Error ? err.message : String(err)}`);
1758
+ }
1759
+ } else {
1760
+ pageScopeType = "organisation";
1761
+ }
1762
+ const validation = await ContextValidator.resolveScopeForPage(
2009
1763
  input.scope,
2010
- resolvedAppConfig,
1764
+ pageScopeType,
2011
1765
  resolvedAppName,
2012
1766
  engine["supabase"]
2013
1767
  );
@@ -2015,6 +1769,44 @@ async function isPermitted(input, appConfig, appName) {
2015
1769
  throw validation.error || new OrganisationContextRequiredError();
2016
1770
  }
2017
1771
  const validatedScope = validation.resolvedScope;
1772
+ if (pageScopeType === "both" && input.pageId) {
1773
+ const eventScope = {
1774
+ organisationId: validatedScope.organisationId,
1775
+ // Org derived from event
1776
+ eventId: validatedScope.eventId,
1777
+ appId: validatedScope.appId
1778
+ };
1779
+ const eventSecurityContext = {
1780
+ userId: input.userId,
1781
+ organisationId: eventScope.organisationId || null,
1782
+ timestamp: /* @__PURE__ */ new Date()
1783
+ };
1784
+ const eventInput = {
1785
+ ...input,
1786
+ scope: eventScope
1787
+ };
1788
+ const hasEventPermission = await engine.isPermitted(eventInput, eventSecurityContext);
1789
+ if (validatedScope.organisationId && validatedScope.eventId) {
1790
+ const orgScope = {
1791
+ organisationId: validatedScope.organisationId,
1792
+ eventId: void 0,
1793
+ // Clear event for org-only check
1794
+ appId: validatedScope.appId
1795
+ };
1796
+ const orgSecurityContext = {
1797
+ userId: input.userId,
1798
+ organisationId: orgScope.organisationId || null,
1799
+ timestamp: /* @__PURE__ */ new Date()
1800
+ };
1801
+ const orgInput = {
1802
+ ...input,
1803
+ scope: orgScope
1804
+ };
1805
+ const hasOrgPermission = await engine.isPermitted(orgInput, orgSecurityContext);
1806
+ return hasEventPermission || hasOrgPermission;
1807
+ }
1808
+ return hasEventPermission;
1809
+ }
2018
1810
  const securityContext = {
2019
1811
  userId: input.userId,
2020
1812
  organisationId: validatedScope.organisationId || null,
@@ -2027,7 +1819,7 @@ async function isPermitted(input, appConfig, appName) {
2027
1819
  };
2028
1820
  return engine.isPermitted(validatedInput, securityContext);
2029
1821
  }
2030
- async function isPermittedCached(input, appConfig, appName) {
1822
+ async function isPermittedCached(input, appName) {
2031
1823
  const { userId, scope, permission, pageId } = input;
2032
1824
  const cacheKey = RBACCache.generatePermissionKey({
2033
1825
  userId,
@@ -2042,7 +1834,7 @@ async function isPermittedCached(input, appConfig, appName) {
2042
1834
  return cached;
2043
1835
  }
2044
1836
  return getOrCreateRequest(input, async (checkInput) => {
2045
- const result = await isPermitted(checkInput, appConfig, appName);
1837
+ const result = await isPermitted(checkInput, appName, null);
2046
1838
  const isPageLevelCheck = !!pageId || permission.includes("page.");
2047
1839
  rbacCache.set(cacheKey, result, void 0, isPageLevelCheck);
2048
1840
  return result;
@@ -2081,50 +1873,40 @@ async function isSuperAdmin(userId) {
2081
1873
  const engine = getEngine();
2082
1874
  return engine["checkSuperAdmin"](userId);
2083
1875
  }
2084
- async function getAppConfig(appId) {
1876
+ async function getPageScopeType(pageId, appId, appName) {
1877
+ const engine = getEngine();
2085
1878
  try {
2086
- const engine = getEngine();
2087
- return getAppConfigWithClient(engine["supabase"], appId);
2088
- } catch (err) {
2089
- if (err instanceof RBACNotInitializedError) {
2090
- return null;
1879
+ let resolvedAppId = appId;
1880
+ if (!resolvedAppId && appName) {
1881
+ const { data: app } = await engine["supabase"].from("rbac_apps").select("id").eq("name", appName).eq("is_active", true).single();
1882
+ resolvedAppId = app?.id;
2091
1883
  }
2092
- throw err;
2093
- }
2094
- }
2095
- async function getAppConfigWithClient(client, appId) {
2096
- if (!client) {
2097
- return null;
2098
- }
2099
- const cacheKey = `app_config:${appId}`;
2100
- const cached = rbacCache.get(cacheKey, true);
2101
- if (cached !== null) {
2102
- return cached;
2103
- }
2104
- try {
2105
- const { data, error } = await client.from("rbac_apps").select("requires_event, name").eq("id", appId).eq("is_active", true).single();
2106
- if (error || !data) {
2107
- return null;
1884
+ if (!resolvedAppId) {
1885
+ throw new Error(`Could not resolve appId for page ${pageId}`);
2108
1886
  }
2109
- const appConfig = { requires_event: data.requires_event ?? false };
2110
- rbacCache.set(cacheKey, appConfig, 5 * 60 * 1e3, true);
2111
- return appConfig;
2112
- } catch (err) {
2113
- log4.error("Error fetching app config:", err);
2114
- return null;
2115
- }
2116
- }
2117
- async function getAppConfigByName(appName) {
2118
- const engine = getEngine();
2119
- try {
2120
- const { data, error } = await engine["supabase"].from("rbac_apps").select("requires_event, name").eq("name", appName).eq("is_active", true).single();
2121
- if (error || !data) {
2122
- return null;
1887
+ let resolvedPageId = pageId;
1888
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1889
+ if (!uuidRegex.test(pageId)) {
1890
+ const { data: page } = await engine["supabase"].from("rbac_app_pages").select("id").eq("app_id", resolvedAppId).eq("page_name", pageId).maybeSingle();
1891
+ resolvedPageId = page?.id || pageId;
1892
+ }
1893
+ if (!uuidRegex.test(resolvedPageId)) {
1894
+ throw new Error(`Could not resolve pageId ${pageId} to a valid UUID`);
2123
1895
  }
2124
- return { requires_event: data.requires_event ?? false };
1896
+ const { data, error } = await engine["supabase"].rpc("get_page_scope_type", {
1897
+ p_page_id: resolvedPageId
1898
+ });
1899
+ if (error) {
1900
+ log3.error("Error fetching page scope type:", { pageId, appId, error });
1901
+ throw new Error(`Failed to get page scope type: ${error.message}`);
1902
+ }
1903
+ if (!data) {
1904
+ throw new Error(`Page ${resolvedPageId} does not have scope_type set`);
1905
+ }
1906
+ return data;
2125
1907
  } catch (err) {
2126
- log4.error("Error fetching app config by name:", err);
2127
- return null;
1908
+ log3.error("Error fetching page scope type:", err);
1909
+ throw err instanceof Error ? err : new Error(`Failed to get page scope type: ${String(err)}`);
2128
1910
  }
2129
1911
  }
2130
1912
  async function isOrganisationAdmin(userId, organisationId) {
@@ -2167,12 +1949,9 @@ function clearCache() {
2167
1949
  }
2168
1950
 
2169
1951
  export {
2170
- OrganisationContextRequiredError,
2171
- RBACNotInitializedError,
2172
1952
  RBACCache,
2173
1953
  rbacCache,
2174
1954
  CACHE_PATTERNS,
2175
- ContextValidator,
2176
1955
  createRBACConfig,
2177
1956
  getRBACConfig,
2178
1957
  getRBACLogger,
@@ -2191,6 +1970,7 @@ export {
2191
1970
  clearInFlightRequests,
2192
1971
  getInFlightRequestCount,
2193
1972
  setupRBAC,
1973
+ isRBACInitialized,
2194
1974
  getAccessLevel,
2195
1975
  getPermissionMap,
2196
1976
  resolveAppContext,
@@ -2201,9 +1981,7 @@ export {
2201
1981
  hasAnyPermission,
2202
1982
  hasAllPermissions,
2203
1983
  isSuperAdmin,
2204
- getAppConfig,
2205
- getAppConfigWithClient,
2206
- getAppConfigByName,
1984
+ getPageScopeType,
2207
1985
  isOrganisationAdmin,
2208
1986
  isEventAdmin,
2209
1987
  invalidateUserCache,
@@ -2212,4 +1990,4 @@ export {
2212
1990
  invalidateAppCache,
2213
1991
  clearCache
2214
1992
  };
2215
- //# sourceMappingURL=chunk-KNC55RTG.js.map
1993
+ //# sourceMappingURL=chunk-RWEBCB47.js.map