@jmruthers/pace-core 0.5.190 → 0.5.193

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 (334) hide show
  1. package/dist/{AuthService-CbP_utw2.d.ts → AuthService-DjnJHDtC.d.ts} +1 -0
  2. package/dist/{DataTable-ON3IXISJ.js → DataTable-5FU7IESH.js} +7 -6
  3. package/dist/{DataTable-IVYljGJ6.d.ts → DataTable-Be6dH_dR.d.ts} +1 -1
  4. package/dist/{PublicPageProvider-C4uxosp6.d.ts → PublicPageProvider-C0Sm_e5k.d.ts} +4 -2
  5. package/dist/{UnifiedAuthProvider-BYA9qB-o.d.ts → UnifiedAuthProvider-185Ih4dj.d.ts} +2 -0
  6. package/dist/{UnifiedAuthProvider-X5NXANVI.js → UnifiedAuthProvider-RGJTDE2C.js} +3 -3
  7. package/dist/{api-I6UCQ5S6.js → api-N774RPUA.js} +2 -2
  8. package/dist/chunk-6C4YBBJM 5.js +628 -0
  9. package/dist/chunk-7D4SUZUM.js 2.map +1 -0
  10. package/dist/{chunk-73HSNNOQ.js → chunk-7EQTDTTJ.js} +47 -74
  11. package/dist/chunk-7EQTDTTJ.js 2.map +1 -0
  12. package/dist/chunk-7EQTDTTJ.js.map +1 -0
  13. package/dist/{chunk-J2XXC7R5.js → chunk-7FLMSG37.js} +409 -244
  14. package/dist/chunk-7FLMSG37.js 2.map +1 -0
  15. package/dist/chunk-7FLMSG37.js.map +1 -0
  16. package/dist/{chunk-NIU6J6OX.js → chunk-BC4IJKSL.js} +23 -32
  17. package/dist/chunk-BC4IJKSL.js.map +1 -0
  18. package/dist/{chunk-SDMHPX3X.js → chunk-E3SPN4VZ 5.js } +198 -53
  19. package/dist/chunk-E3SPN4VZ.js +12917 -0
  20. package/dist/{chunk-SDMHPX3X.js.map → chunk-E3SPN4VZ.js.map} +1 -1
  21. package/dist/chunk-E66EQZE6 5.js +37 -0
  22. package/dist/chunk-E66EQZE6.js 2.map +1 -0
  23. package/dist/{chunk-DZWK57KZ.js → chunk-G37KK66H.js} +1 -1
  24. package/dist/{chunk-DZWK57KZ.js.map → chunk-G37KK66H.js.map} +1 -1
  25. package/dist/{chunk-STYK4OH2.js → chunk-HWIIPPNI.js} +44 -225
  26. package/dist/chunk-HWIIPPNI.js.map +1 -0
  27. package/dist/chunk-I7PSE6JW 5.js +191 -0
  28. package/dist/chunk-I7PSE6JW.js 2.map +1 -0
  29. package/dist/{chunk-Y4BUBBHD.js → chunk-IIELH4DL.js} +211 -136
  30. package/dist/chunk-IIELH4DL.js.map +1 -0
  31. package/dist/{chunk-RUYZKXOD.js → chunk-KNC55RTG.js} +17 -5
  32. package/dist/chunk-KNC55RTG.js 5.map +1 -0
  33. package/dist/chunk-KNC55RTG.js.map +1 -0
  34. package/dist/chunk-KQCRWDSA.js 5.map +1 -0
  35. package/dist/{chunk-4QYC5L4K.js → chunk-LFNCN2SP.js} +26 -30
  36. package/dist/chunk-LFNCN2SP.js 2.map +1 -0
  37. package/dist/chunk-LFNCN2SP.js.map +1 -0
  38. package/dist/chunk-LMC26NLJ 2.js +84 -0
  39. package/dist/{chunk-VVBAW5A5.js → chunk-NOAYCWCX 5.js } +118 -110
  40. package/dist/chunk-NOAYCWCX.js +4993 -0
  41. package/dist/chunk-NOAYCWCX.js.map +1 -0
  42. package/dist/chunk-QWWZ5CAQ.js 3.map +1 -0
  43. package/dist/chunk-QXHPKYJV 3.js +113 -0
  44. package/dist/chunk-R77UEZ4E 3.js +68 -0
  45. package/dist/chunk-VBXEHIUJ.js 6.map +1 -0
  46. package/dist/{chunk-HQVPB5MZ.js → chunk-XNXXZ43G.js} +77 -33
  47. package/dist/chunk-XNXXZ43G.js.map +1 -0
  48. package/dist/chunk-ZSAAAMVR 6.js +25 -0
  49. package/dist/components.d.ts +4 -4
  50. package/dist/components.js +8 -8
  51. package/dist/components.js 5.map +1 -0
  52. package/dist/{database.generated-DI89OQeI.d.ts → database.generated-CzIvgcPu.d.ts} +165 -201
  53. package/dist/hooks.d.ts +12 -12
  54. package/dist/hooks.js +9 -9
  55. package/dist/index.d.ts +11 -11
  56. package/dist/index.js +20 -27
  57. package/dist/index.js.map +1 -1
  58. package/dist/providers.d.ts +3 -3
  59. package/dist/providers.js +2 -2
  60. package/dist/rbac/index.d.ts +2 -20
  61. package/dist/rbac/index.js +7 -9
  62. package/dist/styles/index 2.js +12 -0
  63. package/dist/styles/index.js 5.map +1 -0
  64. package/dist/theming/runtime 5.js +19 -0
  65. package/dist/theming/runtime.js 5.map +1 -0
  66. package/dist/{types-Bwgl--Xo.d.ts → types-CEpcvwwF.d.ts} +1 -1
  67. package/dist/types.d.ts +2 -2
  68. package/dist/{usePublicRouteParams-DxIDS4bC.d.ts → usePublicRouteParams-TZe0gy-4.d.ts} +1 -1
  69. package/dist/utils.d.ts +8 -8
  70. package/dist/utils.js +2 -2
  71. package/docs/api/classes/ColumnFactory.md +1 -1
  72. package/docs/api/classes/ErrorBoundary.md +1 -1
  73. package/docs/api/classes/InvalidScopeError.md +1 -1
  74. package/docs/api/classes/Logger.md +1 -1
  75. package/docs/api/classes/MissingUserContextError.md +1 -1
  76. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  77. package/docs/api/classes/PermissionDeniedError.md +2 -2
  78. package/docs/api/classes/RBACAuditManager.md +2 -2
  79. package/docs/api/classes/RBACCache.md +1 -1
  80. package/docs/api/classes/RBACEngine.md +2 -2
  81. package/docs/api/classes/RBACError.md +1 -1
  82. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  83. package/docs/api/classes/SecureSupabaseClient.md +10 -10
  84. package/docs/api/classes/StorageUtils.md +1 -1
  85. package/docs/api/enums/FileCategory.md +1 -1
  86. package/docs/api/enums/LogLevel.md +1 -1
  87. package/docs/api/enums/RBACErrorCode.md +1 -1
  88. package/docs/api/enums/RPCFunction.md +1 -1
  89. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  90. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  91. package/docs/api/interfaces/AggregateConfig.md +1 -1
  92. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  93. package/docs/api/interfaces/AvatarProps.md +1 -1
  94. package/docs/api/interfaces/BadgeProps.md +1 -1
  95. package/docs/api/interfaces/ButtonProps.md +1 -1
  96. package/docs/api/interfaces/CalendarProps.md +1 -1
  97. package/docs/api/interfaces/CardProps.md +1 -1
  98. package/docs/api/interfaces/ColorPalette.md +1 -1
  99. package/docs/api/interfaces/ColorShade.md +1 -1
  100. package/docs/api/interfaces/ComplianceResult.md +1 -1
  101. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  102. package/docs/api/interfaces/DataRecord.md +1 -1
  103. package/docs/api/interfaces/DataTableAction.md +1 -1
  104. package/docs/api/interfaces/DataTableColumn.md +1 -1
  105. package/docs/api/interfaces/DataTableProps.md +1 -1
  106. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  107. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  108. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  109. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  110. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  111. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  112. package/docs/api/interfaces/ExportColumn.md +1 -1
  113. package/docs/api/interfaces/ExportOptions.md +1 -1
  114. package/docs/api/interfaces/FileDisplayProps.md +24 -11
  115. package/docs/api/interfaces/FileMetadata.md +1 -1
  116. package/docs/api/interfaces/FileReference.md +1 -1
  117. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  118. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  119. package/docs/api/interfaces/FileUploadProps.md +1 -1
  120. package/docs/api/interfaces/FooterProps.md +1 -1
  121. package/docs/api/interfaces/FormFieldProps.md +1 -1
  122. package/docs/api/interfaces/FormProps.md +1 -1
  123. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  124. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  125. package/docs/api/interfaces/InputProps.md +1 -1
  126. package/docs/api/interfaces/LabelProps.md +1 -1
  127. package/docs/api/interfaces/LoggerConfig.md +1 -1
  128. package/docs/api/interfaces/LoginFormProps.md +1 -1
  129. package/docs/api/interfaces/NavigationAccessRecord.md +2 -2
  130. package/docs/api/interfaces/NavigationContextType.md +1 -1
  131. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  132. package/docs/api/interfaces/NavigationItem.md +1 -1
  133. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  134. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  135. package/docs/api/interfaces/Organisation.md +1 -1
  136. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  137. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  138. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  139. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  140. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  141. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  142. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  143. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  144. package/docs/api/interfaces/PagePermissionGuardProps.md +2 -2
  145. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  146. package/docs/api/interfaces/PaletteData.md +1 -1
  147. package/docs/api/interfaces/ParsedAddress.md +2 -2
  148. package/docs/api/interfaces/PermissionEnforcerProps.md +4 -4
  149. package/docs/api/interfaces/ProgressProps.md +1 -1
  150. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  151. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  152. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  153. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  154. package/docs/api/interfaces/QuickFix.md +1 -1
  155. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  156. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  157. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  158. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  159. package/docs/api/interfaces/RBACConfig.md +2 -2
  160. package/docs/api/interfaces/RBACContext.md +1 -1
  161. package/docs/api/interfaces/RBACLogger.md +1 -1
  162. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  163. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  164. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  165. package/docs/api/interfaces/RBACPermissionCheckResult.md +2 -2
  166. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  167. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  168. package/docs/api/interfaces/RBACResult.md +1 -1
  169. package/docs/api/interfaces/RBACRoleGrantParams.md +2 -2
  170. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  171. package/docs/api/interfaces/RBACRoleRevokeParams.md +2 -2
  172. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  173. package/docs/api/interfaces/RBACRoleValidateParams.md +2 -2
  174. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  175. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  176. package/docs/api/interfaces/RBACRolesListResult.md +2 -2
  177. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  178. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  179. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  180. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  181. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  182. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  183. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  184. package/docs/api/interfaces/RouteAccessRecord.md +2 -2
  185. package/docs/api/interfaces/RouteConfig.md +2 -2
  186. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  187. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  188. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  189. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  190. package/docs/api/interfaces/SetupIssue.md +1 -1
  191. package/docs/api/interfaces/StorageConfig.md +1 -1
  192. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  193. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  194. package/docs/api/interfaces/StorageListOptions.md +1 -1
  195. package/docs/api/interfaces/StorageListResult.md +1 -1
  196. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  197. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  198. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  199. package/docs/api/interfaces/StyleImport.md +1 -1
  200. package/docs/api/interfaces/SwitchProps.md +1 -1
  201. package/docs/api/interfaces/TabsContentProps.md +1 -1
  202. package/docs/api/interfaces/TabsListProps.md +1 -1
  203. package/docs/api/interfaces/TabsProps.md +1 -1
  204. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  205. package/docs/api/interfaces/TextareaProps.md +1 -1
  206. package/docs/api/interfaces/ToastActionElement.md +1 -1
  207. package/docs/api/interfaces/ToastProps.md +1 -1
  208. package/docs/api/interfaces/UnifiedAuthContextType.md +60 -38
  209. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  210. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  211. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  212. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  213. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  214. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  215. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  216. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  217. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  218. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  219. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  220. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  221. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  222. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  223. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  224. package/docs/api/interfaces/UserEventAccess.md +1 -1
  225. package/docs/api/interfaces/UserMenuProps.md +1 -1
  226. package/docs/api/interfaces/UserProfile.md +1 -1
  227. package/docs/api/modules.md +202 -217
  228. package/docs/migration/README.md +18 -0
  229. package/docs/migration/database-changes-december-2025.md +768 -0
  230. package/docs/migration/person-scoped-profiles-migration-guide.md +472 -0
  231. package/docs/rbac/event-based-apps.md +124 -6
  232. package/package.json +1 -1
  233. package/scripts/check-pace-core-compliance.cjs +292 -57
  234. package/src/__tests__/public-recipe-view.test.ts +10 -10
  235. package/src/__tests__/rls-policies.test.ts +16 -14
  236. package/src/components/AddressField/README.md +6 -6
  237. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +172 -45
  238. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +121 -28
  239. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +9 -8
  240. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +20 -52
  241. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +170 -34
  242. package/src/components/DataTable/__tests__/keyboard.test.tsx +75 -12
  243. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +75 -11
  244. package/src/components/DataTable/components/UnifiedTableBody.tsx +85 -14
  245. package/src/components/DataTable/hooks/useDataTablePermissions.ts +75 -10
  246. package/src/components/FileDisplay/FileDisplay.test.tsx +2 -1
  247. package/src/components/FileDisplay/FileDisplay.tsx +16 -4
  248. package/src/components/NavigationMenu/NavigationMenu.test.tsx +6 -4
  249. package/src/components/NavigationMenu/NavigationMenu.tsx +1 -10
  250. package/src/components/OrganisationSelector/OrganisationSelector.tsx +35 -16
  251. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +25 -2
  252. package/src/components/PaceAppLayout/PaceAppLayout.tsx +97 -68
  253. package/src/components/PaceLoginPage/PaceLoginPage.tsx +0 -7
  254. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +5 -9
  255. package/src/components/ProtectedRoute/ProtectedRoute.tsx +0 -1
  256. package/src/components/PublicLayout/PublicPageProvider.tsx +0 -1
  257. package/src/components/Select/Select.test.tsx +4 -1
  258. package/src/components/Select/Select.tsx +60 -15
  259. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +192 -0
  260. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +741 -0
  261. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +703 -0
  262. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +581 -0
  263. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +23 -15
  264. package/src/hooks/public/usePublicEvent.ts +8 -8
  265. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  266. package/src/hooks/services/useAuthService.ts +21 -3
  267. package/src/hooks/services/useEventService.ts +21 -3
  268. package/src/hooks/services/useInactivityService.ts +21 -3
  269. package/src/hooks/services/useOrganisationService.ts +21 -3
  270. package/src/hooks/useFileDisplay.ts +18 -26
  271. package/src/hooks/useQueryCache.ts +6 -6
  272. package/src/hooks/useSecureDataAccess.test.ts +24 -17
  273. package/src/hooks/useSecureDataAccess.ts +18 -13
  274. package/src/providers/__tests__/OrganisationProvider.test.tsx +27 -21
  275. package/src/providers/services/EventServiceProvider.tsx +0 -8
  276. package/src/providers/services/UnifiedAuthProvider.tsx +174 -24
  277. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +10 -16
  278. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +82 -0
  279. package/src/rbac/adapters.tsx +3 -22
  280. package/src/rbac/api.test.ts +2 -2
  281. package/src/rbac/api.ts +7 -1
  282. package/src/rbac/components/EnhancedNavigationMenu.tsx +2 -15
  283. package/src/rbac/components/NavigationGuard.tsx +1 -10
  284. package/src/rbac/components/NavigationProvider.tsx +0 -1
  285. package/src/rbac/components/PermissionEnforcer.tsx +45 -12
  286. package/src/rbac/components/SecureDataProvider.tsx +0 -1
  287. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +7 -43
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +4 -11
  289. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +3 -3
  290. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +1 -1
  291. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +1 -1
  292. package/src/rbac/engine.ts +14 -2
  293. package/src/rbac/hooks/index.ts +0 -3
  294. package/src/rbac/hooks/usePermissions.ts +51 -11
  295. package/src/rbac/hooks/useRBAC.simple.test.ts +95 -0
  296. package/src/rbac/hooks/useRBAC.ts +3 -13
  297. package/src/rbac/hooks/useResolvedScope.test.ts +75 -54
  298. package/src/rbac/hooks/useResolvedScope.ts +58 -33
  299. package/src/rbac/hooks/useSecureSupabase.ts +4 -9
  300. package/src/rbac/secureClient.ts +31 -0
  301. package/src/rbac/utils/__tests__/eventContext.test.ts +2 -2
  302. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +490 -0
  303. package/src/rbac/utils/eventContext.ts +5 -2
  304. package/src/services/AuthService.ts +37 -8
  305. package/src/services/EventService.ts +4 -57
  306. package/src/services/InactivityService.ts +127 -34
  307. package/src/services/OrganisationService.ts +160 -149
  308. package/src/services/__tests__/OrganisationService.pagination.test.ts +34 -8
  309. package/src/services/__tests__/OrganisationService.test.ts +218 -86
  310. package/src/types/database.generated.ts +166 -201
  311. package/src/types/supabase.ts +2 -2
  312. package/src/utils/__tests__/secureDataAccess.unit.test.ts +3 -2
  313. package/src/utils/file-reference/index.ts +4 -4
  314. package/src/utils/google-places/googlePlacesUtils.ts +1 -1
  315. package/src/utils/google-places/types.ts +1 -1
  316. package/src/utils/request-deduplication.ts +4 -4
  317. package/src/utils/security/secureDataAccess.test.ts +1 -1
  318. package/src/utils/security/secureDataAccess.ts +7 -4
  319. package/src/utils/storage/README.md +1 -1
  320. package/dist/chunk-4QYC5L4K.js.map +0 -1
  321. package/dist/chunk-73HSNNOQ.js.map +0 -1
  322. package/dist/chunk-HQVPB5MZ.js.map +0 -1
  323. package/dist/chunk-J2XXC7R5.js.map +0 -1
  324. package/dist/chunk-NIU6J6OX.js.map +0 -1
  325. package/dist/chunk-RUYZKXOD.js.map +0 -1
  326. package/dist/chunk-STYK4OH2.js.map +0 -1
  327. package/dist/chunk-VVBAW5A5.js.map +0 -1
  328. package/dist/chunk-Y4BUBBHD.js.map +0 -1
  329. package/scripts/check-pace-core-compliance.js +0 -512
  330. package/src/rbac/hooks/useSuperAdminBypass.ts +0 -126
  331. package/src/utils/context/superAdminOverride.ts +0 -58
  332. /package/dist/{DataTable-ON3IXISJ.js.map → DataTable-5FU7IESH.js.map} +0 -0
  333. /package/dist/{UnifiedAuthProvider-X5NXANVI.js.map → UnifiedAuthProvider-RGJTDE2C.js.map} +0 -0
  334. /package/dist/{api-I6UCQ5S6.js.map → api-N774RPUA.js.map} +0 -0
@@ -210,7 +210,7 @@ export function usePublicEvent(
210
210
 
211
211
  // Fallback: Direct table access with public RLS policy
212
212
  const tableResponse2 = await (supabase as any)
213
- .from('event')
213
+ .from('core_events')
214
214
  .select(`
215
215
  event_id,
216
216
  event_name,
@@ -247,11 +247,11 @@ export function usePublicEvent(
247
247
  return;
248
248
  }
249
249
 
250
- // Get event logo from file_references
250
+ // Get event logo from core_file_references
251
251
  const logoResponse = await (supabase as any)
252
- .from('file_references')
252
+ .from('core_file_references')
253
253
  .select('file_path')
254
- .eq('table_name', 'event')
254
+ .eq('table_name', 'core_events')
255
255
  .eq('record_id', tableData.event_id)
256
256
  .eq('is_public', true)
257
257
  .eq('file_metadata->>category', 'event_logos')
@@ -286,7 +286,7 @@ export function usePublicEvent(
286
286
  logger.warn('usePublicEvent', 'RPC call failed, falling back to direct table access:', rpcError);
287
287
 
288
288
  const tableResponse = await (supabase as any)
289
- .from('event')
289
+ .from('core_events')
290
290
  .select(`
291
291
  event_id,
292
292
  event_name,
@@ -323,11 +323,11 @@ export function usePublicEvent(
323
323
  return;
324
324
  }
325
325
 
326
- // Get event logo from file_references
326
+ // Get event logo from core_file_references
327
327
  const logoResponse = await (supabase as any)
328
- .from('file_references')
328
+ .from('core_file_references')
329
329
  .select('file_path')
330
- .eq('table_name', 'event')
330
+ .eq('table_name', 'core_events')
331
331
  .eq('record_id', tableData.event_id)
332
332
  .eq('is_public', true)
333
333
  .eq('file_metadata->>category', 'event_logos')
@@ -202,7 +202,7 @@ export function usePublicFileDisplay(
202
202
  const ids = userData.map((item: any) => item.id);
203
203
  if (ids.length > 0) {
204
204
  const { data: fullData } = await supabase
205
- .from('file_references')
205
+ .from('core_file_references')
206
206
  .select('id, table_name, record_id, file_path, file_metadata, organisation_id, app_id, is_public, created_at, updated_at')
207
207
  .in('id', ids)
208
208
  .eq('is_public', true);
@@ -320,7 +320,7 @@ export function usePublicFileDisplay(
320
320
  // Fetch full file reference data for each ID, but only public files
321
321
  const ids = fileIds.map((item: any) => item.id);
322
322
  const { data: fullData, error: fetchError } = await supabase
323
- .from('file_references')
323
+ .from('core_file_references')
324
324
  .select('id, table_name, record_id, file_path, file_metadata, organisation_id, app_id, is_public, created_at, updated_at')
325
325
  .in('id', ids)
326
326
  .eq('is_public', true); // Only public files in public context
@@ -8,7 +8,7 @@
8
8
  * Provides authentication service with reactive state updates.
9
9
  */
10
10
 
11
- import { useContext, useReducer, useEffect } from 'react';
11
+ import { useContext, useReducer, useEffect, useRef } from 'react';
12
12
  import { AuthServiceContext } from '../../providers/services/AuthServiceProvider';
13
13
  import { AuthService } from '../../services/AuthService';
14
14
 
@@ -19,11 +19,29 @@ export function useAuthService(): AuthService {
19
19
  throw new Error('useAuthService must be used within AuthServiceProvider');
20
20
  }
21
21
 
22
- // Subscribe to service state changes
22
+ // Subscribe to service state changes with debouncing to prevent excessive re-renders
23
23
  const [, forceUpdate] = useReducer(x => x + 1, 0);
24
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
24
25
 
25
26
  useEffect(() => {
26
- return context.authService.subscribe(() => forceUpdate());
27
+ const debouncedUpdate = () => {
28
+ if (timeoutRef.current) {
29
+ clearTimeout(timeoutRef.current);
30
+ }
31
+ timeoutRef.current = setTimeout(() => {
32
+ forceUpdate();
33
+ timeoutRef.current = null;
34
+ }, 50); // 50ms debounce to batch rapid updates
35
+ };
36
+
37
+ const unsubscribe = context.authService.subscribe(debouncedUpdate);
38
+
39
+ return () => {
40
+ unsubscribe();
41
+ if (timeoutRef.current) {
42
+ clearTimeout(timeoutRef.current);
43
+ }
44
+ };
27
45
  }, [context.authService]);
28
46
 
29
47
  return context.authService;
@@ -8,7 +8,7 @@
8
8
  * Provides event service with reactive state updates.
9
9
  */
10
10
 
11
- import { useContext, useReducer, useEffect } from 'react';
11
+ import { useContext, useReducer, useEffect, useRef } from 'react';
12
12
  import { EventServiceContext } from '../../providers/services/EventServiceProvider';
13
13
  import { EventService } from '../../services/EventService';
14
14
 
@@ -19,11 +19,29 @@ export function useEventService(): EventService {
19
19
  throw new Error('useEventService must be used within EventServiceProvider');
20
20
  }
21
21
 
22
- // Subscribe to service state changes
22
+ // Subscribe to service state changes with debouncing to prevent excessive re-renders
23
23
  const [, forceUpdate] = useReducer(x => x + 1, 0);
24
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
24
25
 
25
26
  useEffect(() => {
26
- return context.eventService.subscribe(() => forceUpdate());
27
+ const debouncedUpdate = () => {
28
+ if (timeoutRef.current) {
29
+ clearTimeout(timeoutRef.current);
30
+ }
31
+ timeoutRef.current = setTimeout(() => {
32
+ forceUpdate();
33
+ timeoutRef.current = null;
34
+ }, 50); // 50ms debounce to batch rapid updates
35
+ };
36
+
37
+ const unsubscribe = context.eventService.subscribe(debouncedUpdate);
38
+
39
+ return () => {
40
+ unsubscribe();
41
+ if (timeoutRef.current) {
42
+ clearTimeout(timeoutRef.current);
43
+ }
44
+ };
27
45
  }, [context.eventService]);
28
46
 
29
47
  return context.eventService;
@@ -8,7 +8,7 @@
8
8
  * Provides inactivity service with reactive state updates.
9
9
  */
10
10
 
11
- import { useContext, useReducer, useEffect } from 'react';
11
+ import { useContext, useReducer, useEffect, useRef } from 'react';
12
12
  import { InactivityServiceContext } from '../../providers/services/InactivityServiceProvider';
13
13
  import { InactivityService } from '../../services/InactivityService';
14
14
 
@@ -19,11 +19,29 @@ export function useInactivityService(): InactivityService {
19
19
  throw new Error('useInactivityService must be used within InactivityServiceProvider');
20
20
  }
21
21
 
22
- // Subscribe to service state changes
22
+ // Subscribe to service state changes with debouncing to prevent excessive re-renders
23
23
  const [, forceUpdate] = useReducer(x => x + 1, 0);
24
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
24
25
 
25
26
  useEffect(() => {
26
- return context.inactivityService.subscribe(() => forceUpdate());
27
+ const debouncedUpdate = () => {
28
+ if (timeoutRef.current) {
29
+ clearTimeout(timeoutRef.current);
30
+ }
31
+ timeoutRef.current = setTimeout(() => {
32
+ forceUpdate();
33
+ timeoutRef.current = null;
34
+ }, 50); // 50ms debounce to batch rapid updates
35
+ };
36
+
37
+ const unsubscribe = context.inactivityService.subscribe(debouncedUpdate);
38
+
39
+ return () => {
40
+ unsubscribe();
41
+ if (timeoutRef.current) {
42
+ clearTimeout(timeoutRef.current);
43
+ }
44
+ };
27
45
  }, [context.inactivityService]);
28
46
 
29
47
  return context.inactivityService;
@@ -8,7 +8,7 @@
8
8
  * Provides organisation service with reactive state updates.
9
9
  */
10
10
 
11
- import { useContext, useReducer, useEffect } from 'react';
11
+ import { useContext, useReducer, useEffect, useRef } from 'react';
12
12
  import { OrganisationServiceContext } from '../../providers/services/OrganisationServiceProvider';
13
13
  import { OrganisationService } from '../../services/OrganisationService';
14
14
 
@@ -19,11 +19,29 @@ export function useOrganisationService(): OrganisationService {
19
19
  throw new Error('useOrganisationService must be used within OrganisationServiceProvider');
20
20
  }
21
21
 
22
- // Subscribe to service state changes
22
+ // Subscribe to service state changes with debouncing to prevent excessive re-renders
23
23
  const [, forceUpdate] = useReducer(x => x + 1, 0);
24
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
24
25
 
25
26
  useEffect(() => {
26
- return context.organisationService.subscribe(() => forceUpdate());
27
+ const debouncedUpdate = () => {
28
+ if (timeoutRef.current) {
29
+ clearTimeout(timeoutRef.current);
30
+ }
31
+ timeoutRef.current = setTimeout(() => {
32
+ forceUpdate();
33
+ timeoutRef.current = null;
34
+ }, 50); // 50ms debounce to batch rapid updates
35
+ };
36
+
37
+ const unsubscribe = context.organisationService.subscribe(debouncedUpdate);
38
+
39
+ return () => {
40
+ unsubscribe();
41
+ if (timeoutRef.current) {
42
+ clearTimeout(timeoutRef.current);
43
+ }
44
+ };
27
45
  }, [context.organisationService]);
28
46
 
29
47
  return context.organisationService;
@@ -4,7 +4,7 @@
4
4
  * @module Hooks
5
5
  *
6
6
  * A React hook for accessing file references in authenticated contexts.
7
- * Can handle both public and private files using the file_references system.
7
+ * Can handle both public and private files using the core_file_references system.
8
8
  *
9
9
  * Features:
10
10
  * - Works in authenticated contexts
@@ -20,7 +20,7 @@
20
20
  *
21
21
  * function FileView() {
22
22
  * const { fileUrl, fileReference, isLoading, error } = useFileDisplay(
23
- * 'event',
23
+ * 'core_events',
24
24
  * eventId,
25
25
  * organisationId,
26
26
  * FileCategory.EVENT_LOGOS
@@ -247,10 +247,9 @@ export function useFileDisplay(
247
247
  if (user) {
248
248
  // Query user's active organisation memberships
249
249
  const { data: memberships, error: membershipError } = await supabase
250
- .from('organisation_memberships')
250
+ .from('core_organisation_memberships')
251
251
  .select('organisation_id')
252
- .eq('user_id', user.id)
253
- .or('status.is.null,status.eq.active');
252
+ .eq('user_id', user.id);
254
253
 
255
254
  if (membershipError) {
256
255
  logger.warn('useFileDisplay', 'Error querying organisation memberships:', membershipError);
@@ -292,7 +291,7 @@ export function useFileDisplay(
292
291
  try {
293
292
  // Try querying without organisation_id filter - let RLS handle security
294
293
  let fallbackQuery = supabase
295
- .from('file_references')
294
+ .from('core_file_references')
296
295
  .select('id, table_name, record_id, file_path, file_metadata, organisation_id, app_id, is_public, created_at, updated_at')
297
296
  .eq('table_name', table_name)
298
297
  .eq('record_id', record_id)
@@ -350,11 +349,11 @@ export function useFileDisplay(
350
349
 
351
350
  // If no files found through RPC, try a direct query as fallback
352
351
  // This handles cases where RLS policy allows access but RPC security check is too strict
353
- // (e.g., pace_person files where user owns the person record but record_id != user_id)
352
+ // (e.g., core_person files where user owns the person record but record_id != user_id)
354
353
  if (files.length === 0) {
355
354
  try {
356
355
  let directQuery = supabase
357
- .from('file_references')
356
+ .from('core_file_references')
358
357
  .select('id, table_name, record_id, file_path, file_metadata, organisation_id, app_id, is_public, created_at, updated_at')
359
358
  .eq('table_name', table_name)
360
359
  .eq('record_id', record_id)
@@ -392,12 +391,7 @@ export function useFileDisplay(
392
391
  // Category is stored in file_metadata JSONB field, not a direct column
393
392
  if (category) {
394
393
  // Single file mode - get files by category using RPC
395
- logger.debug('useFileDisplay', 'Using RPC function for category filtering:', {
396
- table_name,
397
- record_id,
398
- category,
399
- organisation_id
400
- });
394
+ // Removed verbose debug log - only log on errors
401
395
  files = await service.getFilesByCategory(
402
396
  table_name,
403
397
  record_id,
@@ -444,7 +438,7 @@ export function useFileDisplay(
444
438
  const { data: { user } } = await supabase.auth.getUser();
445
439
  if (user) {
446
440
  const { data: memberships } = await supabase
447
- .from('organisation_memberships')
441
+ .from('core_organisation_memberships')
448
442
  .select('organisation_id')
449
443
  .eq('user_id', user.id)
450
444
  .or('status.is.null,status.eq.active');
@@ -511,21 +505,13 @@ export function useFileDisplay(
511
505
  if (category && files.length > 0) {
512
506
  // Single file mode - get first file
513
507
  const firstFile = files[0];
514
- logger.debug('useFileDisplay', 'Processing category files, first file:', {
515
- id: firstFile.id,
516
- file_path: firstFile.file_path,
517
- is_public: firstFile.is_public,
518
- has_file_metadata: !!firstFile.file_metadata,
519
- category_in_metadata: firstFile.file_metadata?.category
520
- });
521
-
508
+ // Removed verbose debug logs - only log on errors
522
509
  setFileReference(firstFile);
523
510
 
524
511
  // Generate URL based on file visibility
525
512
  let url: string | null = null;
526
513
  if (firstFile.is_public) {
527
514
  url = getPublicUrl(supabase, firstFile.file_path, true);
528
- logger.debug('useFileDisplay', 'Generated public URL:', url);
529
515
  } else {
530
516
  const signedUrlResult = await getSignedUrl(supabase, firstFile.file_path, {
531
517
  appName: 'pace-core',
@@ -534,9 +520,15 @@ export function useFileDisplay(
534
520
  expiresIn: 3600
535
521
  });
536
522
  url = signedUrlResult?.url || null;
537
- logger.debug('useFileDisplay', 'Generated signed URL:', url ? 'URL generated' : 'URL generation failed');
523
+ // Only log if URL generation fails
524
+ if (!url) {
525
+ logger.warn('useFileDisplay', 'Failed to generate signed URL for file:', {
526
+ file_path: firstFile.file_path,
527
+ record_id,
528
+ table_name
529
+ });
530
+ }
538
531
  }
539
- logger.debug('useFileDisplay', 'Setting file URL:', url ? 'URL set' : 'URL is null');
540
532
  setFileUrl(url);
541
533
  } else {
542
534
  // Multiple files mode - generate URLs for all files in batch
@@ -112,12 +112,12 @@ export interface UseQueryCacheReturn {
112
112
  * const { getCachedQuery } = useQueryCache(supabase);
113
113
  *
114
114
  * const person = await getCachedQuery(
115
- * 'pace_person',
115
+ * 'core_person',
116
116
  * 'user_id',
117
117
  * userId,
118
118
  * async () => {
119
119
  * const { data } = await supabase
120
- * .from('pace_person')
120
+ * .from('core_person')
121
121
  * .select('id, first_name, last_name, email')
122
122
  * .eq('user_id', userId)
123
123
  * .single();
@@ -220,7 +220,7 @@ export function useQueryCache(supabase?: SupabaseClient<Database>): UseQueryCach
220
220
  */
221
221
  export const queryCacheHelpers = {
222
222
  /**
223
- * Cache pace_person queries by user_id
223
+ * Cache core_person queries by user_id
224
224
  * TTL: 5 minutes
225
225
  */
226
226
  pacePersonByUserId: <T>(
@@ -228,7 +228,7 @@ export const queryCacheHelpers = {
228
228
  userId: string,
229
229
  fetchFn: () => Promise<T>
230
230
  ): Promise<T> => {
231
- const cacheKey = `pace_person:user_id:${userId}`;
231
+ const cacheKey = `core_person:user_id:${userId}`;
232
232
  const now = Date.now();
233
233
  const ttl = 300 * 1000; // 5 minutes
234
234
 
@@ -258,7 +258,7 @@ export const queryCacheHelpers = {
258
258
  },
259
259
 
260
260
  /**
261
- * Cache pace_member queries by person_id
261
+ * Cache core_member queries by person_id
262
262
  * TTL: 5 minutes
263
263
  */
264
264
  paceMemberByPersonId: <T>(
@@ -266,7 +266,7 @@ export const queryCacheHelpers = {
266
266
  personId: string,
267
267
  fetchFn: () => Promise<T>
268
268
  ): Promise<T> => {
269
- const cacheKey = `pace_member:person_id:${personId}`;
269
+ const cacheKey = `core_member:person_id:${personId}`;
270
270
  const now = Date.now();
271
271
  const ttl = 300 * 1000; // 5 minutes
272
272
 
@@ -15,7 +15,7 @@ import { useOrganisations } from './useOrganisations';
15
15
  import { setOrganisationContext } from '../utils/context/organisationContext';
16
16
  import { createMockSupabaseClient, createMockQueryBuilderWithData } from '../__tests__/helpers/supabaseMock';
17
17
  import { useResolvedScope } from '../rbac/hooks/useResolvedScope';
18
- import { useSuperAdminBypass } from '../rbac/hooks/useSuperAdminBypass';
18
+ import { useOrganisationSecurity } from './useOrganisationSecurity';
19
19
 
20
20
  // Mock the providers
21
21
  vi.mock('../providers', () => ({
@@ -36,9 +36,9 @@ vi.mock('../rbac/hooks/useResolvedScope', () => ({
36
36
  useResolvedScope: vi.fn()
37
37
  }));
38
38
 
39
- // Mock useSuperAdminBypass
40
- vi.mock('../rbac/hooks/useSuperAdminBypass', () => ({
41
- useSuperAdminBypass: vi.fn()
39
+ // Mock useOrganisationSecurity
40
+ vi.mock('./useOrganisationSecurity', () => ({
41
+ useOrganisationSecurity: vi.fn()
42
42
  }));
43
43
 
44
44
 
@@ -47,7 +47,7 @@ describe('useSecureDataAccess', () => {
47
47
  const mockUseOrganisations = vi.mocked(useOrganisations);
48
48
  const mockSetOrganisationContext = vi.mocked(setOrganisationContext);
49
49
  const mockUseResolvedScope = vi.mocked(useResolvedScope);
50
- const mockUseSuperAdminBypass = vi.mocked(useSuperAdminBypass);
50
+ const mockUseOrganisationSecurity = vi.mocked(useOrganisationSecurity);
51
51
 
52
52
  const mockUser = {
53
53
  id: 'user-123',
@@ -119,10 +119,17 @@ describe('useSecureDataAccess', () => {
119
119
  error: null,
120
120
  });
121
121
 
122
- // Mock useSuperAdminBypass to return not super admin
123
- mockUseSuperAdminBypass.mockReturnValue({
124
- isSuperAdmin: false,
125
- });
122
+ // Mock useOrganisationSecurity to return not super admin
123
+ mockUseOrganisationSecurity.mockReturnValue({
124
+ superAdminContext: { isSuperAdmin: false, hasGlobalAccess: false, canManageAllOrganisations: false },
125
+ validateOrganisationAccess: vi.fn(),
126
+ hasMinimumRole: vi.fn(),
127
+ canAccessChildOrganisations: vi.fn(),
128
+ checkPermission: vi.fn(),
129
+ getPermissions: vi.fn(),
130
+ logOrganisationAccess: vi.fn(),
131
+ canManageOrganisation: vi.fn(),
132
+ } as any);
126
133
  });
127
134
 
128
135
  describe('Hook Initialization', () => {
@@ -154,9 +161,9 @@ describe('useSecureDataAccess', () => {
154
161
  it('executes secure query with organisation filtering', async () => {
155
162
  const { result } = renderHook(() => useSecureDataAccess());
156
163
 
157
- const data = await result.current.secureQuery('event', '*', { active: true });
164
+ const data = await result.current.secureQuery('core_events', '*', { active: true });
158
165
 
159
- expect(freshMockSupabase.from).toHaveBeenCalledWith('event');
166
+ expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
160
167
  expect(freshMockQueryBuilder.select).toHaveBeenCalledWith('*');
161
168
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
162
169
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('active', true);
@@ -270,9 +277,9 @@ describe('useSecureDataAccess', () => {
270
277
  it('executes secure update with organisation filtering', async () => {
271
278
  const { result } = renderHook(() => useSecureDataAccess());
272
279
 
273
- const data = await result.current.secureUpdate('event', { event_name: 'Updated Event' }, { id: 'event-123' });
280
+ const data = await result.current.secureUpdate('core_events', { event_name: 'Updated Event' }, { id: 'event-123' });
274
281
 
275
- expect(freshMockSupabase.from).toHaveBeenCalledWith('event');
282
+ expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
276
283
  expect(freshMockQueryBuilder.update).toHaveBeenCalledWith({ event_name: 'Updated Event' });
277
284
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('id', 'event-123');
278
285
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
@@ -307,9 +314,9 @@ describe('useSecureDataAccess', () => {
307
314
  it('executes secure delete with organisation filtering', async () => {
308
315
  const { result } = renderHook(() => useSecureDataAccess());
309
316
 
310
- await result.current.secureDelete('event', { id: 'event-123' });
317
+ await result.current.secureDelete('core_events', { id: 'event-123' });
311
318
 
312
- expect(freshMockSupabase.from).toHaveBeenCalledWith('event');
319
+ expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
313
320
  expect(freshMockQueryBuilder.delete).toHaveBeenCalled();
314
321
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('id', 'event-123');
315
322
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
@@ -387,7 +394,7 @@ describe('useSecureDataAccess', () => {
387
394
  const { result } = renderHook(() => useSecureDataAccess());
388
395
 
389
396
  // Use 'event' table which is in the tablesWithOrganisation list
390
- await result.current.secureQuery('event', '*');
397
+ await result.current.secureQuery('core_events', '*');
391
398
 
392
399
  // Verify that the query was executed with organisation filter
393
400
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
@@ -443,7 +450,7 @@ describe('useSecureDataAccess', () => {
443
450
  it('prevents data leaks between organisations', async () => {
444
451
  const { result } = renderHook(() => useSecureDataAccess());
445
452
 
446
- await result.current.secureQuery('event', '*');
453
+ await result.current.secureQuery('core_events', '*');
447
454
 
448
455
  // Verify organisation_id filter is always applied
449
456
  expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
@@ -15,7 +15,7 @@
15
15
  * const loadData = async () => {
16
16
  * try {
17
17
  * // Automatically includes organisation_id filter
18
- * const events = await secureQuery('event', '*', { is_visible: true });
18
+ * const events = await secureQuery('core_events', '*', { is_visible: true });
19
19
  * console.log('Organisation events:', events);
20
20
  * } catch (error) {
21
21
  * console.error('Failed to load data:', error);
@@ -25,7 +25,7 @@
25
25
  * const createEvent = async (eventData) => {
26
26
  * try {
27
27
  * // Automatically sets organisation_id
28
- * const newEvent = await secureInsert('event', eventData);
28
+ * const newEvent = await secureInsert('core_events', eventData);
29
29
  * console.log('Created event:', newEvent);
30
30
  * } catch (error) {
31
31
  * console.error('Failed to create event:', error);
@@ -59,7 +59,7 @@ import { setOrganisationContext } from '../utils/context/organisationContext';
59
59
  import { logger } from '../utils/core/logger';
60
60
  import type { Permission } from '../rbac/types';
61
61
  import type { OrganisationSecurityError } from '../types/organisation';
62
- import { useSuperAdminBypass } from '../rbac/hooks/useSuperAdminBypass';
62
+ import { useOrganisationSecurity } from './useOrganisationSecurity';
63
63
  import { useResolvedScope } from '../rbac/hooks/useResolvedScope';
64
64
 
65
65
  export interface SecureDataAccessReturn {
@@ -158,7 +158,8 @@ export function useSecureDataAccess(): SecureDataAccessReturn {
158
158
  const eventServiceContext = useContext(EventServiceContext);
159
159
  const eventFromContext = eventServiceContext?.eventService?.getSelectedEvent() || null;
160
160
  const effectiveSelectedEvent = selectedEvent || eventFromContext;
161
- const { isSuperAdmin } = useSuperAdminBypass();
161
+ const { superAdminContext } = useOrganisationSecurity();
162
+ const isSuperAdmin = superAdminContext.isSuperAdmin;
162
163
 
163
164
  // Use resolved scope to get organisationId (derived from event if needed)
164
165
  const { resolvedScope } = useResolvedScope({
@@ -231,15 +232,19 @@ export function useSecureDataAccess(): SecureDataAccessReturn {
231
232
  // - RLS policies are the primary security layer (cannot be bypassed)
232
233
  // - Application-level filtering adds an additional layer of protection
233
234
  const tablesWithOrganisation = [
234
- 'event', 'organisation_settings',
235
+ 'core_events', 'organisation_settings',
235
236
  'rbac_event_app_roles', 'rbac_organisation_roles',
236
237
  // SECURITY: Phase 2 additions - complete organisation table mapping
237
238
  'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',
238
239
  // SECURITY: Emergency additions for Phase 1 fixes
239
- 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',
240
+ 'cake_meal', 'cake_mealtype', 'core_person',
241
+ // NOTE: core_member, medi_profile, core_contact, core_consent, core_identification, core_qualification
242
+ // are now person-scoped (not organisation-scoped) - removed from this list
240
243
  // SECURITY: Phase 3A additions - medical and personal data
241
- 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',
242
- 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',
244
+ // NOTE: medi_condition, medi_diet, medi_action_plan, medi_profile_versions are now person-scoped
245
+ // (via medi_profile) - removed from this list
246
+ // core_identification_type remains organisation-scoped (lookup table)
247
+ 'core_identification_type',
243
248
  'form_responses', 'form_response_values', 'forms',
244
249
  // SECURITY: Phase 3B additions - remaining critical tables
245
250
  'invoice', 'line_item', 'credit_balance', 'payment_method',
@@ -360,12 +365,12 @@ export function useSecureDataAccess(): SecureDataAccessReturn {
360
365
 
361
366
  // Add organisation filter only if table has organisation_id column
362
367
  const tablesWithOrganisation = [
363
- 'event', 'organisation_settings',
368
+ 'core_events', 'organisation_settings',
364
369
  'rbac_event_app_roles', 'rbac_organisation_roles',
365
370
  // SECURITY: Phase 2 additions - complete organisation table mapping
366
371
  'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',
367
372
  // SECURITY: Emergency additions for Phase 1 fixes
368
- 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member'
373
+ 'cake_meal', 'cake_mealtype', 'core_person', 'core_member'
369
374
  ];
370
375
 
371
376
  if (!bypassOrganisationFilter && organisationId && tablesWithOrganisation.includes(table)) {
@@ -407,15 +412,15 @@ export function useSecureDataAccess(): SecureDataAccessReturn {
407
412
 
408
413
  // Add organisation filter only if table has organisation_id column
409
414
  const tablesWithOrganisation = [
410
- 'event', 'organisation_settings',
415
+ 'core_events', 'organisation_settings',
411
416
  'rbac_event_app_roles', 'rbac_organisation_roles',
412
417
  // SECURITY: Phase 2 additions - complete organisation table mapping
413
418
  'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',
414
419
  // SECURITY: Emergency additions for Phase 1 fixes
415
- 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',
420
+ 'cake_meal', 'cake_mealtype', 'core_person', 'core_member',
416
421
  // SECURITY: Phase 3A additions - medical and personal data
417
422
  'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',
418
- 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',
423
+ 'core_consent', 'core_contact', 'core_identification', 'core_identification_type', 'core_qualification',
419
424
  'form_responses', 'form_response_values', 'forms',
420
425
  // SECURITY: Phase 3B additions - remaining critical tables
421
426
  'invoice', 'line_item', 'credit_balance', 'payment_method',
@@ -40,24 +40,7 @@ const createMockSupabaseClient = () => {
40
40
  const orgId = '123e4567-e89b-12d3-a456-426614174000'; // Valid UUID format
41
41
  const userId = '123e4567-e89b-12d3-a456-426614174001'; // Valid UUID format
42
42
 
43
- return {
44
- rpc: vi.fn().mockResolvedValue({
45
- data: [
46
- {
47
- user_id: userId,
48
- organisation_id: orgId,
49
- role: 'org_admin',
50
- status: 'active',
51
- },
52
- ],
53
- error: null,
54
- }),
55
- from: vi.fn((table: string) => {
56
- if (table === 'organisations') {
57
- return {
58
- select: vi.fn().mockResolvedValue({
59
- data: [
60
- {
43
+ const mockOrganisation = {
61
44
  id: orgId,
62
45
  name: 'Test Organisation 1',
63
46
  display_name: 'Test Organisation 1',
@@ -67,11 +50,34 @@ const createMockSupabaseClient = () => {
67
50
  parent_id: null,
68
51
  created_at: '2023-01-01T00:00:00Z',
69
52
  updated_at: '2023-01-01T00:00:00Z',
70
- },
71
- ],
53
+ };
54
+
55
+ const mockQueryBuilder = {
56
+ select: vi.fn().mockReturnThis(),
57
+ eq: vi.fn().mockReturnThis(),
58
+ is: vi.fn().mockResolvedValue({
59
+ data: [{
60
+ id: 'membership-1',
61
+ user_id: userId,
62
+ organisation_id: orgId,
63
+ role: 'org_admin',
64
+ status: 'active',
65
+ granted_at: '2023-01-01T00:00:00Z',
66
+ revoked_at: null,
67
+ core_organisations: mockOrganisation
68
+ }],
69
+ error: null
70
+ })
71
+ };
72
+
73
+ return {
74
+ rpc: vi.fn().mockResolvedValue({
75
+ data: [],
72
76
  error: null,
73
77
  }),
74
- };
78
+ from: vi.fn((table: string) => {
79
+ if (table === 'rbac_organisation_roles') {
80
+ return mockQueryBuilder;
75
81
  }
76
82
  return {
77
83
  select: vi.fn().mockResolvedValue({ data: [], error: null }),