@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,263 +0,0 @@
1
- import {
2
- createLogger
3
- } from "./chunk-PWLANIRT.js";
4
-
5
- // src/rbac/types.ts
6
- var RBACError = class extends Error {
7
- constructor(message, code, context) {
8
- super(message);
9
- this.code = code;
10
- this.context = context;
11
- this.name = "RBACError";
12
- }
13
- };
14
- var PermissionDeniedError = class extends RBACError {
15
- constructor(permission, context) {
16
- super(
17
- `Permission denied: ${permission}`,
18
- "PERMISSION_DENIED",
19
- { permission, ...context }
20
- );
21
- this.name = "PermissionDeniedError";
22
- }
23
- };
24
- var OrganisationContextRequiredError = class extends RBACError {
25
- constructor() {
26
- super(
27
- "Organisation context is required for this operation",
28
- "ORGANISATION_CONTEXT_REQUIRED"
29
- );
30
- this.name = "OrganisationContextRequiredError";
31
- }
32
- };
33
- var EventContextRequiredError = class extends RBACError {
34
- constructor() {
35
- super(
36
- "Event context is required for this operation",
37
- "EVENT_CONTEXT_REQUIRED"
38
- );
39
- this.name = "EventContextRequiredError";
40
- }
41
- };
42
- var RBACNotInitializedError = class extends RBACError {
43
- constructor() {
44
- super(
45
- "RBAC system not initialized. Please call setupRBAC(supabase) before using any RBAC components or hooks. See: https://docs.pace-core.dev/rbac/setup",
46
- "RBAC_NOT_INITIALIZED"
47
- );
48
- this.name = "RBACNotInitializedError";
49
- }
50
- };
51
- var InvalidScopeError = class extends RBACError {
52
- constructor(scope, reason) {
53
- super(
54
- `Invalid scope provided: ${JSON.stringify(scope)}. ${reason}`,
55
- "INVALID_SCOPE",
56
- { scope, reason }
57
- );
58
- this.name = "InvalidScopeError";
59
- }
60
- };
61
- var MissingUserContextError = class extends RBACError {
62
- constructor() {
63
- super(
64
- "User context is required but not available. Make sure to wrap your app with an auth provider.",
65
- "MISSING_USER_CONTEXT"
66
- );
67
- this.name = "MissingUserContextError";
68
- }
69
- };
70
-
71
- // src/rbac/utils/eventContext.ts
72
- var orgDerivationCache = /* @__PURE__ */ new Map();
73
- var MAX_CACHE_SIZE = 100;
74
- async function getOrganisationFromEvent(supabase, eventId) {
75
- if (orgDerivationCache.has(eventId)) {
76
- return orgDerivationCache.get(eventId) ?? null;
77
- }
78
- const { data, error } = await supabase.from("core_events").select("organisation_id").eq("event_id", eventId).single();
79
- let organisationId = null;
80
- if (error || !data) {
81
- organisationId = null;
82
- } else if (data.organisation_id) {
83
- organisationId = data.organisation_id;
84
- } else {
85
- organisationId = null;
86
- }
87
- if (orgDerivationCache.size >= MAX_CACHE_SIZE) {
88
- const firstKey = orgDerivationCache.keys().next().value;
89
- if (firstKey) {
90
- orgDerivationCache.delete(firstKey);
91
- }
92
- }
93
- orgDerivationCache.set(eventId, organisationId);
94
- return organisationId;
95
- }
96
-
97
- // src/rbac/utils/contextValidator.ts
98
- var log = createLogger("ContextValidator");
99
- function allowsOptionalContexts(appName) {
100
- return appName === "PORTAL" || appName === "ADMIN";
101
- }
102
- var ContextValidator = class {
103
- /**
104
- * Derive organisation ID from event ID
105
- *
106
- * @param supabase - Supabase client
107
- * @param eventId - Event ID
108
- * @returns Organisation ID or null
109
- */
110
- static async deriveOrgFromEvent(supabase, eventId) {
111
- return getOrganisationFromEvent(supabase, eventId);
112
- }
113
- /**
114
- * Resolve scope based on page-level scope_type
115
- *
116
- * This method handles page-level scoping. All pages have explicit scope_type set.
117
- * Used for hybrid apps like pace-mint that have both event and organisation pages.
118
- *
119
- * @param scope - Current scope
120
- * @param pageScopeType - Page scope type ('event', 'organisation', or 'both')
121
- * @param appName - App name (for PORTAL/ADMIN special case)
122
- * @param supabase - Supabase client (for deriving org from event)
123
- * @returns Resolved scope with all required context
124
- */
125
- static async resolveScopeForPage(scope, pageScopeType, appName, supabase) {
126
- const effectiveScopeType = pageScopeType;
127
- if (effectiveScopeType === "both") {
128
- if (!scope.organisationId && !scope.eventId) {
129
- if (allowsOptionalContexts(appName)) {
130
- return {
131
- isValid: true,
132
- resolvedScope: {
133
- organisationId: void 0,
134
- eventId: void 0,
135
- appId: scope.appId
136
- },
137
- error: null
138
- };
139
- }
140
- return {
141
- isValid: false,
142
- resolvedScope: null,
143
- error: new Error("Page requires either organisation or event context")
144
- };
145
- }
146
- let organisationId = scope.organisationId;
147
- if (!organisationId && scope.eventId && supabase) {
148
- try {
149
- const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
150
- organisationId = derivedOrgId || void 0;
151
- } catch (error) {
152
- log.warn("Failed to derive org from event for both-scope page:", error);
153
- }
154
- }
155
- return {
156
- isValid: true,
157
- resolvedScope: {
158
- organisationId,
159
- eventId: scope.eventId,
160
- appId: scope.appId
161
- },
162
- error: null
163
- };
164
- }
165
- if (effectiveScopeType === "event") {
166
- if (!scope.eventId) {
167
- if (allowsOptionalContexts(appName)) {
168
- return {
169
- isValid: true,
170
- resolvedScope: {
171
- organisationId: scope.organisationId,
172
- eventId: void 0,
173
- appId: scope.appId
174
- },
175
- error: null
176
- };
177
- }
178
- return {
179
- isValid: false,
180
- resolvedScope: null,
181
- error: new EventContextRequiredError()
182
- };
183
- }
184
- let organisationId = scope.organisationId;
185
- if (!organisationId && supabase && scope.eventId) {
186
- try {
187
- const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
188
- organisationId = derivedOrgId || void 0;
189
- if (!organisationId) {
190
- return {
191
- isValid: false,
192
- resolvedScope: null,
193
- error: new Error("Could not resolve organisation from event context")
194
- };
195
- }
196
- } catch (error) {
197
- log.error("Failed to derive org from event:", error);
198
- return {
199
- isValid: false,
200
- resolvedScope: null,
201
- error: error instanceof Error ? error : new Error("Failed to derive organisation from event")
202
- };
203
- }
204
- }
205
- return {
206
- isValid: true,
207
- resolvedScope: {
208
- organisationId,
209
- eventId: scope.eventId,
210
- appId: scope.appId
211
- },
212
- error: null
213
- };
214
- }
215
- if (effectiveScopeType === "organisation") {
216
- if (!scope.organisationId) {
217
- if (allowsOptionalContexts(appName)) {
218
- return {
219
- isValid: true,
220
- resolvedScope: {
221
- organisationId: void 0,
222
- eventId: scope.eventId,
223
- appId: scope.appId
224
- },
225
- error: null
226
- };
227
- }
228
- return {
229
- isValid: false,
230
- resolvedScope: null,
231
- error: new OrganisationContextRequiredError()
232
- };
233
- }
234
- return {
235
- isValid: true,
236
- resolvedScope: {
237
- organisationId: scope.organisationId,
238
- eventId: scope.eventId,
239
- // Event is optional for org-scoped pages
240
- appId: scope.appId
241
- },
242
- error: null
243
- };
244
- }
245
- return {
246
- isValid: false,
247
- resolvedScope: null,
248
- error: new Error("Invalid scope type")
249
- };
250
- }
251
- };
252
-
253
- export {
254
- RBACError,
255
- PermissionDeniedError,
256
- OrganisationContextRequiredError,
257
- EventContextRequiredError,
258
- RBACNotInitializedError,
259
- InvalidScopeError,
260
- MissingUserContextError,
261
- ContextValidator
262
- };
263
- //# sourceMappingURL=chunk-AFVQODI2.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/rbac/types.ts","../src/rbac/utils/eventContext.ts","../src/rbac/utils/contextValidator.ts"],"sourcesContent":["/**\n * RBAC (Role-Based Access Control) Types - Build Contract Compliant\n * @package @jmruthers/pace-core\n * @module RBAC/Types\n * @since 1.0.0\n * \n * This module defines the core types for the RBAC system that match the build contract exactly.\n * All types are designed to be framework-agnostic and provide strong typing for permission operations.\n */\n\nimport type React from 'react';\nimport type { AppId, PageId } from '../types/core';\n\n// ============================================================================\n// CORE TYPES\n// ============================================================================\n\nexport type UUID = string;\n\nexport type Operation = 'read' | 'create' | 'update' | 'delete';\n\nexport type Permission = `${Operation}:${string}`; // e.g. \"read:base.events\" or \"create:team.members\"\n\nexport type AccessLevel =\n | 'viewer'\n | 'participant'\n | 'planner'\n | 'admin'\n | 'super';\n\n/**\n * Scope defines the context for permission checks.\n * Can include organisation, event, and/or app identifiers.\n */\nexport type Scope = {\n organisationId?: UUID;\n eventId?: string; // event_id is text/varchar\n appId?: AppId | UUID;\n};\n\n/**\n * Permission check request parameters.\n * Defines who (userId) is checking what permission in what context (scope).\n */\nexport type PermissionCheck = {\n userId: UUID;\n scope: Scope;\n permission: Permission;\n pageId?: PageId | UUID;\n};\n\nexport type PermissionMap = Record<Permission, boolean> & Partial<Record<'*', boolean>>;\n\n// ============================================================================\n// ROLE TYPES\n// ============================================================================\n\nexport type GlobalRole = 'super_admin';\n\nexport type OrganisationRole = 'supporter' | 'member' | 'leader' | 'org_admin';\n\nexport type EventAppRole = 'viewer' | 'participant' | 'planner' | 'event_admin';\n\n// ============================================================================\n// DATABASE TYPES\n// ============================================================================\n\nexport interface RBACGlobalRole {\n id: UUID;\n user_id: UUID;\n role: GlobalRole;\n granted_at: string;\n granted_by: UUID | null;\n valid_from: string;\n valid_to: string | null;\n}\n\nexport interface RBACOrganisationRole {\n id: UUID;\n user_id: UUID;\n organisation_id: UUID;\n role: OrganisationRole;\n status: 'active' | 'inactive' | 'suspended';\n granted_at: string;\n granted_by: UUID | null;\n revoked_at: string | null;\n revoked_by: UUID | null;\n notes: string | null;\n created_at: string;\n updated_at: string;\n valid_from: string;\n valid_to: string | null;\n}\n\nexport interface RBACEventAppRole {\n id: UUID;\n user_id: UUID;\n event_id: string;\n role: EventAppRole;\n status: 'active' | 'inactive' | 'suspended';\n granted_at: string;\n granted_by: UUID | null;\n organisation_id: UUID;\n app_id: UUID;\n valid_from: string;\n valid_to: string | null;\n}\n\nexport interface RBACPagePermission {\n id: UUID;\n app_page_id: UUID;\n operation: Operation;\n role_name: string;\n allowed: boolean;\n created_at: string;\n updated_at: string;\n organisation_id: UUID;\n}\n\nexport interface RBACAppPage {\n id: UUID;\n page_name: string;\n page_description: string | null;\n created_at: string;\n updated_at: string;\n created_by: UUID | null;\n updated_by: UUID | null;\n app_id: UUID;\n scope_type: 'event' | 'organisation' | 'both'; // Required - single source of truth for page scoping\n}\n\nexport interface RBACApp {\n id: UUID;\n name: string;\n display_name: string;\n description: string | null;\n requires_event: boolean;\n is_active: boolean;\n created_at: string;\n updated_at: string;\n created_by: UUID | null;\n updated_by: UUID | null;\n}\n\n// ============================================================================\n// AUDIT EVENT TYPES\n// ============================================================================\n\nexport type AuditEventType = \n | 'permission_check'\n | 'permission_denied'\n | 'role_granted'\n | 'role_denied'\n | 'rls_denied';\n\nexport type AuditEventSource = 'api' | 'ui' | 'middleware' | 'rls';\n\nexport interface RBACAuditEvent {\n id: UUID;\n event_type: AuditEventType;\n user_id: UUID;\n organisation_id: UUID | null; // Nullable to properly track missing context cases (should be rare since organisationId is required)\n event_id?: string;\n app_id?: UUID;\n page_id?: UUID;\n permission?: string;\n decision?: boolean;\n source?: AuditEventSource;\n bypass?: boolean;\n duration_ms?: number;\n metadata: Record<string, any>;\n created_at: string;\n}\n\nexport interface RBACAppContext {\n appId: UUID;\n hasAccess: boolean;\n}\n\nexport interface RBACRoleContext {\n globalRole: GlobalRole | null;\n organisationRole: OrganisationRole | null;\n eventAppRole: EventAppRole | null;\n}\n\n// ============================================================================\n// CACHE TYPES\n// ============================================================================\n\nexport interface CacheEntry<T> {\n data: T;\n expires: number;\n}\n\nexport interface PermissionCacheKey {\n userId: UUID;\n organisationId?: UUID;\n eventId?: string;\n appId?: UUID;\n permission?: Permission;\n pageId?: UUID | string;\n}\n\n// ============================================================================\n// API TYPES\n// ============================================================================\n\nexport interface GetAccessLevelInput {\n userId: UUID;\n scope: Scope;\n}\n\nexport interface GetPermissionMapInput {\n userId: UUID;\n scope: Scope;\n}\n\nexport interface IsPermittedInput extends PermissionCheck {}\n\n// ============================================================================\n// HOOK TYPES\n// ============================================================================\n\nexport interface UsePermissionsReturn {\n permissions: PermissionMap;\n isLoading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n}\n\nexport interface UseCanReturn {\n can: boolean;\n isLoading: boolean;\n error: Error | null;\n check: () => Promise<void>;\n}\n\n// ============================================================================\n// ADAPTER TYPES\n// ============================================================================\n\nexport interface PermissionGuardConfig {\n permission: Permission;\n pageId?: UUID;\n}\n\nexport interface WithPermissionGuardOptions {\n permission: Permission;\n pageId?: UUID;\n fallback?: React.ReactNode;\n onDenied?: () => void;\n}\n\n// ============================================================================\n// HOOK RETURN TYPES\n// ============================================================================\n\nexport interface UserRBACContext {\n user: any; // User from auth context\n globalRole: GlobalRole | null;\n organisationRole: OrganisationRole | null;\n eventAppRole: EventAppRole | null;\n hasGlobalPermission: (permission: Permission) => boolean;\n isSuperAdmin: boolean;\n isOrgAdmin: boolean;\n isEventAdmin: boolean;\n canManageOrganisation: boolean;\n canManageEvent: boolean;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport interface RBACPermission {\n permission_type: string;\n role_name: string;\n [key: string]: any;\n}\n\n// ============================================================================\n// COMPONENT TYPES\n// ============================================================================\n\nexport interface RBACGuardProps {\n children: React.ReactNode;\n operation: Operation;\n pageId?: UUID;\n fallback?: React.ReactNode;\n}\n\nexport interface RoleBasedContentProps {\n children: React.ReactNode;\n globalRoles?: GlobalRole[];\n organisationRoles?: OrganisationRole[];\n eventAppRoles?: EventAppRole[];\n fallback?: React.ReactNode;\n}\n\n// ============================================================================\n// ERROR TYPES\n// ============================================================================\n\nexport class RBACError extends Error {\n constructor(\n message: string,\n public code: string,\n public context?: Record<string, any>\n ) {\n super(message);\n this.name = 'RBACError';\n }\n}\n\nexport class PermissionDeniedError extends RBACError {\n constructor(permission: Permission, context?: Record<string, any>) {\n super(\n `Permission denied: ${permission}`,\n 'PERMISSION_DENIED',\n { permission, ...context }\n );\n this.name = 'PermissionDeniedError';\n }\n}\n\nexport class OrganisationContextRequiredError extends RBACError {\n constructor() {\n super(\n 'Organisation context is required for this operation',\n 'ORGANISATION_CONTEXT_REQUIRED'\n );\n this.name = 'OrganisationContextRequiredError';\n }\n}\n\nexport class EventContextRequiredError extends RBACError {\n constructor() {\n super(\n 'Event context is required for this operation',\n 'EVENT_CONTEXT_REQUIRED'\n );\n this.name = 'EventContextRequiredError';\n }\n}\n\nexport class RBACNotInitializedError extends RBACError {\n constructor() {\n super(\n 'RBAC system not initialized. Please call setupRBAC(supabase) before using any RBAC components or hooks. See: https://docs.pace-core.dev/rbac/setup',\n 'RBAC_NOT_INITIALIZED'\n );\n this.name = 'RBACNotInitializedError';\n }\n}\n\nexport class InvalidScopeError extends RBACError {\n constructor(scope: Scope, reason: string) {\n super(\n `Invalid scope provided: ${JSON.stringify(scope)}. ${reason}`,\n 'INVALID_SCOPE',\n { scope, reason }\n );\n this.name = 'InvalidScopeError';\n }\n}\n\nexport class MissingUserContextError extends RBACError {\n constructor() {\n super(\n 'User context is required but not available. Make sure to wrap your app with an auth provider.',\n 'MISSING_USER_CONTEXT'\n );\n this.name = 'MissingUserContextError';\n }\n}\n","/**\n * Event Context Utilities for RBAC\n * @package @jmruthers/pace-core\n * @module RBAC/EventContext\n * @since 1.0.0\n * \n * This module provides utilities for event-based RBAC operations where\n * the organization context is derived from the event context.\n */\n\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { Database } from '../../types/database';\nimport { UUID, Scope } from '../types';\n\n/**\n * Cache for organisation derivation from event\n * Key: eventId, Value: organisationId | null\n * Maximum cache size to prevent memory leaks\n */\nconst orgDerivationCache = new Map<string, UUID | null>();\nconst MAX_CACHE_SIZE = 100; // Limit cache to 100 entries\n\n/**\n * Clear cache entry for a specific event (useful if event's org changes)\n * @param eventId - Event ID to clear from cache\n */\nexport function clearOrgDerivationCache(eventId: string): void {\n orgDerivationCache.delete(eventId);\n}\n\n/**\n * Clear all cached organisation derivations\n */\nexport function clearAllOrgDerivationCache(): void {\n orgDerivationCache.clear();\n}\n\n/**\n * Get organization ID from event ID\n * \n * Uses caching to avoid repeated database queries for the same event.\n * Cache is limited to prevent memory leaks.\n * \n * @param supabase - Supabase client\n * @param eventId - Event ID\n * @returns Promise resolving to organization ID or null\n */\nexport async function getOrganisationFromEvent(\n supabase: SupabaseClient<Database>,\n eventId: string\n): Promise<UUID | null> {\n // Check cache first\n if (orgDerivationCache.has(eventId)) {\n return orgDerivationCache.get(eventId) ?? null;\n }\n\n // Query database\n const { data, error } = await supabase\n .from('core_events')\n .select('organisation_id')\n .eq('event_id', eventId)\n .single() as { data: { organisation_id: string } | null; error: any };\n\n let organisationId: UUID | null = null;\n\n if (error || !data) {\n organisationId = null;\n } else if (data.organisation_id) {\n organisationId = data.organisation_id;\n } else {\n // organisation_id is null or undefined\n organisationId = null;\n }\n\n // Cache the result (with size limit to prevent memory leaks)\n if (orgDerivationCache.size >= MAX_CACHE_SIZE) {\n // Remove oldest entry (first key in Map)\n const firstKey = orgDerivationCache.keys().next().value;\n if (firstKey) {\n orgDerivationCache.delete(firstKey);\n }\n }\n orgDerivationCache.set(eventId, organisationId);\n\n return organisationId;\n}\n\n/**\n * Create a complete scope from event context\n * \n * @param supabase - Supabase client\n * @param eventId - Event ID\n * @param appId - Optional app ID\n * @returns Promise resolving to complete scope\n */\nexport async function createScopeFromEvent(\n supabase: SupabaseClient<Database>,\n eventId: string,\n appId?: UUID\n): Promise<Scope | null> {\n const organisationId = await getOrganisationFromEvent(supabase, eventId);\n \n if (!organisationId) {\n return null;\n }\n\n return {\n organisationId,\n eventId,\n appId\n };\n}\n\n/**\n * Check if a scope is event-based (has eventId but no explicit organisationId)\n * \n * @param scope - Permission scope\n * @returns True if scope is event-based\n */\nexport function isEventBasedScope(scope: Scope): boolean {\n return !scope.organisationId && !!scope.eventId;\n}\n\n/**\n * Validate that an event-based scope has the required context\n * \n * @param scope - Permission scope\n * @returns True if scope is valid for event-based operations\n */\nexport function isValidEventBasedScope(scope: Scope): boolean {\n return isEventBasedScope(scope) && !!scope.eventId;\n}\n","/**\n * Context Validator for RBAC\n * @package @jmruthers/pace-core\n * @module RBAC/ContextValidator\n * @since 1.0.0\n * \n * Centralized validation for RBAC context requirements based on app configuration.\n * Enforces app-specific context rules with single primary context:\n * - requires_event = TRUE: Event is PRIMARY context, org derived from event (org not required in input)\n * - requires_event = FALSE: Organisation is PRIMARY context, event optional\n * - PORTAL/ADMIN apps: Both contexts optional (allows users to view/edit own profiles, super admin access)\n * \n * Key principle: Only one primary context is required based on app config. The other is derived or optional.\n */\n\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { Database } from '../../types/database';\nimport { UUID, Scope } from '../types';\nimport { EventContextRequiredError, OrganisationContextRequiredError } from '../types';\nimport { getOrganisationFromEvent } from './eventContext';\nimport { createLogger } from '../../utils/core/logger';\n\nconst log = createLogger('ContextValidator');\n\n/**\n * Page scope type - determines what context is required for a page\n * This is the single source of truth for page scoping.\n */\nexport type PageScopeType = 'event' | 'organisation' | 'both';\n\n/**\n * Check if an app allows optional contexts (both organisation and event optional)\n * @param appName - App name to check\n * @returns True if app allows optional contexts\n */\nfunction allowsOptionalContexts(appName?: string): boolean {\n return appName === 'PORTAL' || appName === 'ADMIN';\n}\n\nexport interface ContextValidationResult {\n isValid: boolean;\n resolvedScope: Scope | null;\n error: Error | null;\n}\n\n/**\n * Context Validator class\n * \n * Validates and resolves RBAC scope based on app configuration requirements.\n */\nexport class ContextValidator {\n\n /**\n * Derive organisation ID from event ID\n * \n * @param supabase - Supabase client\n * @param eventId - Event ID\n * @returns Organisation ID or null\n */\n static async deriveOrgFromEvent(\n supabase: SupabaseClient<Database>,\n eventId: string\n ): Promise<UUID | null> {\n return getOrganisationFromEvent(supabase, eventId);\n }\n\n /**\n * Resolve scope based on page-level scope_type\n * \n * This method handles page-level scoping. All pages have explicit scope_type set.\n * Used for hybrid apps like pace-mint that have both event and organisation pages.\n * \n * @param scope - Current scope\n * @param pageScopeType - Page scope type ('event', 'organisation', or 'both')\n * @param appName - App name (for PORTAL/ADMIN special case)\n * @param supabase - Supabase client (for deriving org from event)\n * @returns Resolved scope with all required context\n */\n static async resolveScopeForPage(\n scope: Scope,\n pageScopeType: PageScopeType,\n appName?: string,\n supabase?: SupabaseClient<Database> | null\n ): Promise<ContextValidationResult> {\n // Use page-level scope (single source of truth)\n const effectiveScopeType = pageScopeType;\n \n // Handle 'both' scope - requires both contexts available, but can use either\n if (effectiveScopeType === 'both') {\n // For 'both' pages, we need at least one context (org or event)\n // Both will be checked during permission evaluation\n // For PORTAL/ADMIN apps, both contexts are optional\n if (!scope.organisationId && !scope.eventId) {\n if (allowsOptionalContexts(appName)) {\n return {\n isValid: true,\n resolvedScope: {\n organisationId: undefined,\n eventId: undefined,\n appId: scope.appId\n },\n error: null\n };\n }\n return {\n isValid: false,\n resolvedScope: null,\n error: new Error('Page requires either organisation or event context')\n };\n }\n \n // Derive org from event if event is provided but org is not\n let organisationId = scope.organisationId;\n if (!organisationId && scope.eventId && supabase) {\n try {\n const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);\n organisationId = derivedOrgId || undefined;\n } catch (error) {\n log.warn('Failed to derive org from event for both-scope page:', error);\n // Continue without org - permission check will handle it\n }\n }\n \n return {\n isValid: true,\n resolvedScope: {\n organisationId,\n eventId: scope.eventId,\n appId: scope.appId\n },\n error: null\n };\n }\n \n // Handle 'event' scope - requires event context\n if (effectiveScopeType === 'event') {\n if (!scope.eventId) {\n // For PORTAL/ADMIN apps, event context is optional\n if (allowsOptionalContexts(appName)) {\n return {\n isValid: true,\n resolvedScope: {\n organisationId: scope.organisationId,\n eventId: undefined,\n appId: scope.appId\n },\n error: null\n };\n }\n return {\n isValid: false,\n resolvedScope: null,\n error: new EventContextRequiredError()\n };\n }\n \n // Derive organisationId from event if not provided\n let organisationId: UUID | undefined = scope.organisationId;\n if (!organisationId && supabase && scope.eventId) {\n try {\n const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);\n organisationId = derivedOrgId || undefined;\n if (!organisationId) {\n return {\n isValid: false,\n resolvedScope: null,\n error: new Error('Could not resolve organisation from event context')\n };\n }\n } catch (error) {\n log.error('Failed to derive org from event:', error);\n return {\n isValid: false,\n resolvedScope: null,\n error: error instanceof Error ? error : new Error('Failed to derive organisation from event')\n };\n }\n }\n \n return {\n isValid: true,\n resolvedScope: {\n organisationId,\n eventId: scope.eventId,\n appId: scope.appId\n },\n error: null\n };\n }\n \n // Handle 'organisation' scope - requires organisation context\n if (effectiveScopeType === 'organisation') {\n if (!scope.organisationId) {\n // For PORTAL/ADMIN apps, organisation context is optional\n if (allowsOptionalContexts(appName)) {\n return {\n isValid: true,\n resolvedScope: {\n organisationId: undefined,\n eventId: scope.eventId,\n appId: scope.appId\n },\n error: null\n };\n }\n return {\n isValid: false,\n resolvedScope: null,\n error: new OrganisationContextRequiredError()\n };\n }\n \n return {\n isValid: true,\n resolvedScope: {\n organisationId: scope.organisationId,\n eventId: scope.eventId, // Event is optional for org-scoped pages\n appId: scope.appId\n },\n error: null\n };\n }\n \n // Fallback (should not happen)\n return {\n isValid: false,\n resolvedScope: null,\n error: new Error('Invalid scope type')\n };\n }\n\n}\n\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/useComponentPerformance.ts"],"sourcesContent":["\nimport { useEffect, useRef } from 'react';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('useComponentPerformance');\n\ninterface PerformanceConfig {\n componentName: string;\n enableLogging?: boolean;\n threshold?: number;\n}\n\nexport function useComponentPerformance({ \n componentName, \n enableLogging = import.meta.env.MODE === 'development',\n threshold = 16 // 60fps = 16ms per frame\n}: PerformanceConfig) {\n const renderCount = useRef(0);\n const lastRenderTime = useRef<number>(0);\n\n useEffect(() => {\n if (!enableLogging) return;\n\n const now = performance.now();\n const renderTime = now - lastRenderTime.current;\n renderCount.current += 1;\n\n if (renderCount.current > 1 && renderTime > threshold) {\n log.warn(\n `Performance warning: ${componentName} rendered in ${renderTime.toFixed(2)}ms ` +\n `(render #${renderCount.current}). Consider optimizing.`\n );\n }\n\n lastRenderTime.current = now;\n });\n\n return {\n renderCount: renderCount.current,\n componentName\n };\n}\n"],"mappings":";;;;;AACA,SAAS,WAAW,cAAc;AAGlC,IAAM,MAAM,aAAa,yBAAyB;AAQ3C,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA,gBAAgB,YAAY,IAAI,SAAS;AAAA,EACzC,YAAY;AAAA;AACd,GAAsB;AACpB,QAAM,cAAc,OAAO,CAAC;AAC5B,QAAM,iBAAiB,OAAe,CAAC;AAEvC,YAAU,MAAM;AACd,QAAI,CAAC,cAAe;AAEpB,UAAM,MAAM,YAAY,IAAI;AAC5B,UAAM,aAAa,MAAM,eAAe;AACxC,gBAAY,WAAW;AAEvB,QAAI,YAAY,UAAU,KAAK,aAAa,WAAW;AACrD,UAAI;AAAA,QACF,wBAAwB,aAAa,gBAAgB,WAAW,QAAQ,CAAC,CAAC,eAC9D,YAAY,OAAO;AAAA,MACjC;AAAA,IACF;AAEA,mBAAe,UAAU;AAAA,EAC3B,CAAC;AAED,SAAO;AAAA,IACL,aAAa,YAAY;AAAA,IACzB;AAAA,EACF;AACF;","names":[]}