@jmruthers/pace-core 0.5.189 → 0.5.191

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/core-usage-manifest.json +0 -4
  2. package/dist/{AuthService-B-cd2MA4.d.ts → AuthService-CbP_utw2.d.ts} +7 -3
  3. package/dist/{DataTable-IVYljGJ6.d.ts → DataTable-Be6dH_dR.d.ts} +1 -1
  4. package/dist/{DataTable-GUFUNZ3N.js → DataTable-WKRZD47S.js} +8 -8
  5. package/dist/{PublicPageProvider-B8HaLe69.d.ts → PublicPageProvider-ULXC_u6U.d.ts} +84 -25
  6. package/dist/{UnifiedAuthProvider-BG0AL5eE.d.ts → UnifiedAuthProvider-BYA9qB-o.d.ts} +4 -3
  7. package/dist/{UnifiedAuthProvider-643PUAIM.js → UnifiedAuthProvider-FTSG5XH7.js} +4 -2
  8. package/dist/{api-YP7XD5L6.js → api-IHKALJZD.js} +4 -2
  9. package/dist/{chunk-VGZZXKBR.js → chunk-6LTQQAT6.js} +351 -157
  10. package/dist/chunk-6LTQQAT6.js.map +1 -0
  11. package/dist/{chunk-MX64ZF6I.js → chunk-6TQDD426.js} +15 -15
  12. package/dist/chunk-6TQDD426.js.map +1 -0
  13. package/dist/{chunk-YHCN776L.js → chunk-G37KK66H.js} +2 -75
  14. package/dist/chunk-G37KK66H.js.map +1 -0
  15. package/dist/{chunk-THRPYOFK.js → chunk-HW3OVDUF.js} +5 -5
  16. package/dist/chunk-HW3OVDUF.js.map +1 -0
  17. package/dist/{chunk-F2IMUDXZ.js → chunk-I7PSE6JW.js} +75 -2
  18. package/dist/chunk-I7PSE6JW.js.map +1 -0
  19. package/dist/{chunk-IM4QE42D.js → chunk-LOMZXPSN.js} +141 -326
  20. package/dist/chunk-LOMZXPSN.js.map +1 -0
  21. package/dist/chunk-OETXORNB.js +614 -0
  22. package/dist/chunk-OETXORNB.js.map +1 -0
  23. package/dist/{chunk-HESYZWZW.js → chunk-QWWZ5CAQ.js} +2 -2
  24. package/dist/{chunk-HEHYGYOX.js → chunk-ROXMHMY2.js} +403 -46
  25. package/dist/chunk-ROXMHMY2.js.map +1 -0
  26. package/dist/{chunk-2UUZZJFT.js → chunk-ULHIJK66.js} +228 -177
  27. package/dist/{chunk-2UUZZJFT.js.map → chunk-ULHIJK66.js.map} +1 -1
  28. package/dist/{chunk-YGPFYGA6.js → chunk-VKB2CO4Z.js} +838 -503
  29. package/dist/chunk-VKB2CO4Z.js.map +1 -0
  30. package/dist/{chunk-3GOZZZYH.js → chunk-VRGWKHDB.js} +238 -301
  31. package/dist/chunk-VRGWKHDB.js.map +1 -0
  32. package/dist/{chunk-UCQSRW7Z.js → chunk-XNYQOL3Z.js} +431 -384
  33. package/dist/chunk-XNYQOL3Z.js.map +1 -0
  34. package/dist/{chunk-DDM4CCYT.js → chunk-XYXSXPUK.js} +79 -59
  35. package/dist/chunk-XYXSXPUK.js.map +1 -0
  36. package/dist/{chunk-SAUPYVLF.js → chunk-ZSAAAMVR.js} +1 -1
  37. package/dist/chunk-ZSAAAMVR.js.map +1 -0
  38. package/dist/components.d.ts +5 -6
  39. package/dist/components.js +19 -19
  40. package/dist/components.js.map +1 -1
  41. package/dist/{database.generated-DI89OQeI.d.ts → database.generated-CzIvgcPu.d.ts} +165 -201
  42. package/dist/eslint-rules/pace-core-compliance.cjs +0 -2
  43. package/dist/{file-reference-D037xOFK.d.ts → file-reference-BavO2eQj.d.ts} +13 -10
  44. package/dist/hooks.d.ts +20 -15
  45. package/dist/hooks.js +14 -8
  46. package/dist/hooks.js.map +1 -1
  47. package/dist/index.d.ts +17 -15
  48. package/dist/index.js +86 -81
  49. package/dist/index.js.map +1 -1
  50. package/dist/providers.d.ts +3 -3
  51. package/dist/providers.js +3 -1
  52. package/dist/rbac/index.d.ts +77 -13
  53. package/dist/rbac/index.js +12 -9
  54. package/dist/{types-Bwgl--Xo.d.ts → types-CEpcvwwF.d.ts} +1 -1
  55. package/dist/types.d.ts +3 -3
  56. package/dist/types.js +1 -1
  57. package/dist/{usePublicRouteParams-CTDELQ7H.d.ts → usePublicRouteParams-TZe0gy-4.d.ts} +17 -10
  58. package/dist/utils.d.ts +8 -8
  59. package/dist/utils.js +16 -16
  60. package/docs/README.md +2 -2
  61. package/docs/api/classes/ColumnFactory.md +1 -1
  62. package/docs/api/classes/ErrorBoundary.md +1 -1
  63. package/docs/api/classes/InvalidScopeError.md +2 -2
  64. package/docs/api/classes/Logger.md +1 -1
  65. package/docs/api/classes/MissingUserContextError.md +2 -2
  66. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  67. package/docs/api/classes/PermissionDeniedError.md +1 -1
  68. package/docs/api/classes/RBACAuditManager.md +2 -2
  69. package/docs/api/classes/RBACCache.md +1 -1
  70. package/docs/api/classes/RBACEngine.md +5 -5
  71. package/docs/api/classes/RBACError.md +1 -1
  72. package/docs/api/classes/RBACNotInitializedError.md +2 -2
  73. package/docs/api/classes/SecureSupabaseClient.md +25 -20
  74. package/docs/api/classes/StorageUtils.md +7 -4
  75. package/docs/api/enums/FileCategory.md +1 -1
  76. package/docs/api/enums/LogLevel.md +1 -1
  77. package/docs/api/enums/RBACErrorCode.md +1 -1
  78. package/docs/api/enums/RPCFunction.md +1 -1
  79. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  80. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  81. package/docs/api/interfaces/AggregateConfig.md +1 -1
  82. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  83. package/docs/api/interfaces/AvatarProps.md +1 -1
  84. package/docs/api/interfaces/BadgeProps.md +1 -1
  85. package/docs/api/interfaces/ButtonProps.md +1 -1
  86. package/docs/api/interfaces/CalendarProps.md +20 -6
  87. package/docs/api/interfaces/CardProps.md +1 -1
  88. package/docs/api/interfaces/ColorPalette.md +1 -1
  89. package/docs/api/interfaces/ColorShade.md +1 -1
  90. package/docs/api/interfaces/ComplianceResult.md +1 -1
  91. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  92. package/docs/api/interfaces/DataRecord.md +1 -1
  93. package/docs/api/interfaces/DataTableAction.md +1 -1
  94. package/docs/api/interfaces/DataTableColumn.md +1 -1
  95. package/docs/api/interfaces/DataTableProps.md +1 -1
  96. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  97. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  98. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  99. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  100. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  101. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  102. package/docs/api/interfaces/ExportColumn.md +1 -1
  103. package/docs/api/interfaces/ExportOptions.md +1 -1
  104. package/docs/api/interfaces/FileDisplayProps.md +62 -16
  105. package/docs/api/interfaces/FileMetadata.md +1 -1
  106. package/docs/api/interfaces/FileReference.md +2 -2
  107. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  108. package/docs/api/interfaces/FileUploadOptions.md +26 -12
  109. package/docs/api/interfaces/FileUploadProps.md +30 -19
  110. package/docs/api/interfaces/FooterProps.md +1 -1
  111. package/docs/api/interfaces/FormFieldProps.md +1 -1
  112. package/docs/api/interfaces/FormProps.md +1 -1
  113. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  114. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  115. package/docs/api/interfaces/InputProps.md +1 -1
  116. package/docs/api/interfaces/LabelProps.md +1 -1
  117. package/docs/api/interfaces/LoggerConfig.md +1 -1
  118. package/docs/api/interfaces/LoginFormProps.md +1 -1
  119. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  120. package/docs/api/interfaces/NavigationContextType.md +9 -9
  121. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  122. package/docs/api/interfaces/NavigationItem.md +1 -1
  123. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  124. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  125. package/docs/api/interfaces/Organisation.md +1 -1
  126. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  127. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  128. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  129. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  130. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  131. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  132. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  133. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  134. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  135. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  136. package/docs/api/interfaces/PaletteData.md +1 -1
  137. package/docs/api/interfaces/ParsedAddress.md +2 -2
  138. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  139. package/docs/api/interfaces/ProgressProps.md +3 -11
  140. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  141. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  142. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  143. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  144. package/docs/api/interfaces/QuickFix.md +1 -1
  145. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  146. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  147. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  148. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  149. package/docs/api/interfaces/RBACConfig.md +2 -2
  150. package/docs/api/interfaces/RBACContext.md +1 -1
  151. package/docs/api/interfaces/RBACLogger.md +1 -1
  152. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  153. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  154. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  155. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  156. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  157. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  158. package/docs/api/interfaces/RBACResult.md +1 -1
  159. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  160. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  161. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  162. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  163. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  164. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  165. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  166. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  167. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  168. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  169. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  170. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  171. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  172. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  173. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  174. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  175. package/docs/api/interfaces/RouteConfig.md +10 -10
  176. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  177. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  178. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  179. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  180. package/docs/api/interfaces/SetupIssue.md +1 -1
  181. package/docs/api/interfaces/StorageConfig.md +4 -4
  182. package/docs/api/interfaces/StorageFileInfo.md +7 -7
  183. package/docs/api/interfaces/StorageFileMetadata.md +25 -14
  184. package/docs/api/interfaces/StorageListOptions.md +22 -9
  185. package/docs/api/interfaces/StorageListResult.md +4 -4
  186. package/docs/api/interfaces/StorageUploadOptions.md +21 -8
  187. package/docs/api/interfaces/StorageUploadResult.md +6 -6
  188. package/docs/api/interfaces/StorageUrlOptions.md +19 -6
  189. package/docs/api/interfaces/StyleImport.md +1 -1
  190. package/docs/api/interfaces/SwitchProps.md +1 -1
  191. package/docs/api/interfaces/TabsContentProps.md +1 -1
  192. package/docs/api/interfaces/TabsListProps.md +1 -1
  193. package/docs/api/interfaces/TabsProps.md +1 -1
  194. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  195. package/docs/api/interfaces/TextareaProps.md +1 -1
  196. package/docs/api/interfaces/ToastActionElement.md +1 -1
  197. package/docs/api/interfaces/ToastProps.md +1 -1
  198. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  199. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  200. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  201. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  202. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  203. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  204. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  205. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  206. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  207. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  208. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  209. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  210. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  211. package/docs/api/interfaces/UseResolvedScopeOptions.md +5 -5
  212. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  213. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  214. package/docs/api/interfaces/UserEventAccess.md +11 -11
  215. package/docs/api/interfaces/UserMenuProps.md +1 -1
  216. package/docs/api/interfaces/UserProfile.md +1 -1
  217. package/docs/api/modules.md +165 -106
  218. package/docs/api-reference/components.md +15 -7
  219. package/docs/api-reference/providers.md +2 -2
  220. package/docs/api-reference/rpc-functions.md +1 -0
  221. package/docs/best-practices/README.md +1 -1
  222. package/docs/best-practices/deployment.md +8 -8
  223. package/docs/getting-started/examples/README.md +2 -2
  224. package/docs/getting-started/installation-guide.md +4 -4
  225. package/docs/getting-started/quick-start.md +3 -3
  226. package/docs/migration/MIGRATION_GUIDE.md +3 -3
  227. package/docs/migration/README.md +18 -0
  228. package/docs/migration/database-changes-december-2025.md +767 -0
  229. package/docs/migration/person-scoped-profiles-migration-guide.md +472 -0
  230. package/docs/rbac/compliance/compliance-guide.md +2 -2
  231. package/docs/rbac/event-based-apps.md +2 -2
  232. package/docs/rbac/getting-started.md +2 -2
  233. package/docs/rbac/quick-start.md +2 -2
  234. package/docs/security/README.md +4 -4
  235. package/docs/standards/07-rbac-and-rls-standard.md +430 -7
  236. package/docs/troubleshooting/README.md +2 -2
  237. package/docs/troubleshooting/migration.md +3 -3
  238. package/package.json +1 -3
  239. package/scripts/check-pace-core-compliance.cjs +1 -1
  240. package/scripts/check-pace-core-compliance.js +1 -1
  241. package/src/__tests__/fixtures/supabase.ts +301 -0
  242. package/src/__tests__/public-recipe-view.test.ts +19 -19
  243. package/src/__tests__/rls-policies.test.ts +210 -74
  244. package/src/components/AddressField/AddressField.test.tsx +42 -0
  245. package/src/components/AddressField/AddressField.tsx +71 -60
  246. package/src/components/AddressField/README.md +7 -6
  247. package/src/components/Alert/Alert.test.tsx +50 -10
  248. package/src/components/Alert/Alert.tsx +5 -3
  249. package/src/components/Avatar/Avatar.test.tsx +95 -43
  250. package/src/components/Avatar/Avatar.tsx +16 -16
  251. package/src/components/Button/Button.test.tsx +2 -1
  252. package/src/components/Button/Button.tsx +3 -3
  253. package/src/components/Calendar/Calendar.test.tsx +53 -37
  254. package/src/components/Calendar/Calendar.tsx +409 -82
  255. package/src/components/Card/Card.test.tsx +7 -4
  256. package/src/components/Card/Card.tsx +3 -6
  257. package/src/components/Checkbox/Checkbox.tsx +2 -2
  258. package/src/components/DataTable/components/ActionButtons.tsx +5 -5
  259. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  260. package/src/components/DataTable/components/ColumnFilter.tsx +1 -1
  261. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +3 -3
  262. package/src/components/DataTable/components/DataTableBody.tsx +12 -12
  263. package/src/components/DataTable/components/DataTableCore.tsx +3 -3
  264. package/src/components/DataTable/components/DataTableToolbar.tsx +5 -5
  265. package/src/components/DataTable/components/DraggableColumnHeader.tsx +3 -3
  266. package/src/components/DataTable/components/EditableRow.tsx +2 -2
  267. package/src/components/DataTable/components/EmptyState.tsx +3 -3
  268. package/src/components/DataTable/components/GroupHeader.tsx +2 -2
  269. package/src/components/DataTable/components/GroupingDropdown.tsx +1 -1
  270. package/src/components/DataTable/components/ImportModal.tsx +4 -4
  271. package/src/components/DataTable/components/LoadingState.tsx +1 -1
  272. package/src/components/DataTable/components/PaginationControls.tsx +11 -11
  273. package/src/components/DataTable/components/UnifiedTableBody.tsx +9 -9
  274. package/src/components/DataTable/components/ViewRowModal.tsx +2 -2
  275. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +11 -37
  276. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +157 -0
  277. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +2 -1
  278. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +128 -0
  279. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +19 -0
  280. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +51 -0
  281. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +84 -0
  282. package/src/components/DataTable/core/__tests__/DataManager.test.ts +14 -0
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +136 -0
  284. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +16 -0
  285. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +18 -0
  286. package/src/components/DataTable/hooks/useDataTablePermissions.ts +28 -7
  287. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +30 -1
  288. package/src/components/DataTable/utils/hierarchicalUtils.ts +38 -10
  289. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -3
  290. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +4 -4
  291. package/src/components/Dialog/Dialog.tsx +2 -2
  292. package/src/components/EventSelector/EventSelector.tsx +7 -7
  293. package/src/components/FileDisplay/FileDisplay.tsx +291 -179
  294. package/src/components/FileUpload/FileUpload.tsx +7 -4
  295. package/src/components/Header/Header.test.tsx +28 -0
  296. package/src/components/Header/Header.tsx +22 -9
  297. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -2
  298. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +19 -14
  299. package/src/components/LoadingSpinner/LoadingSpinner.tsx +5 -5
  300. package/src/components/NavigationMenu/NavigationMenu.test.tsx +127 -1
  301. package/src/components/OrganisationSelector/OrganisationSelector.tsx +42 -22
  302. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +4 -0
  303. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +3 -0
  304. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +3 -0
  305. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +16 -6
  306. package/src/components/PaceAppLayout/PaceAppLayout.tsx +37 -3
  307. package/src/components/PaceAppLayout/test-setup.tsx +1 -0
  308. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +66 -45
  309. package/src/components/PaceLoginPage/PaceLoginPage.tsx +6 -4
  310. package/src/components/Progress/Progress.test.tsx +18 -19
  311. package/src/components/Progress/Progress.tsx +31 -32
  312. package/src/components/PublicLayout/PublicLayout.test.tsx +6 -6
  313. package/src/components/PublicLayout/PublicPageProvider.tsx +5 -3
  314. package/src/components/Select/Select.test.tsx +4 -1
  315. package/src/components/Select/Select.tsx +65 -20
  316. package/src/components/Switch/Switch.test.tsx +2 -1
  317. package/src/components/Switch/Switch.tsx +1 -1
  318. package/src/components/Toast/Toast.tsx +1 -1
  319. package/src/components/Tooltip/Tooltip.test.tsx +8 -2
  320. package/src/components/UserMenu/UserMenu.tsx +3 -3
  321. package/src/eslint-rules/pace-core-compliance.cjs +0 -2
  322. package/src/eslint-rules/pace-core-compliance.js +0 -2
  323. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -1
  324. package/src/hooks/__tests__/useAppConfig.unit.test.ts +76 -5
  325. package/src/hooks/__tests__/useDataTableState.test.ts +76 -0
  326. package/src/hooks/__tests__/useFileUrl.unit.test.ts +25 -69
  327. package/src/hooks/__tests__/useFileUrlCache.test.ts +129 -0
  328. package/src/hooks/__tests__/usePreventTabReload.test.ts +88 -0
  329. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -1
  330. package/src/hooks/__tests__/usePublicEvent.test.ts +608 -0
  331. package/src/hooks/__tests__/useQueryCache.test.ts +144 -0
  332. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +67 -24
  333. package/src/hooks/index.ts +1 -1
  334. package/src/hooks/public/usePublicEvent.ts +10 -10
  335. package/src/hooks/public/usePublicFileDisplay.ts +173 -87
  336. package/src/hooks/useAppConfig.ts +24 -5
  337. package/src/hooks/useFileDisplay.ts +298 -36
  338. package/src/hooks/useFileReference.ts +56 -11
  339. package/src/hooks/useFileUrl.ts +1 -1
  340. package/src/hooks/useInactivityTracker.ts +16 -7
  341. package/src/hooks/usePermissionCache.test.ts +85 -8
  342. package/src/hooks/useQueryCache.ts +27 -6
  343. package/src/hooks/useSecureDataAccess.test.ts +87 -42
  344. package/src/hooks/useSecureDataAccess.ts +95 -48
  345. package/src/providers/__tests__/OrganisationProvider.test.tsx +27 -21
  346. package/src/providers/services/EventServiceProvider.tsx +37 -17
  347. package/src/providers/services/InactivityServiceProvider.tsx +4 -4
  348. package/src/providers/services/OrganisationServiceProvider.tsx +8 -1
  349. package/src/providers/services/UnifiedAuthProvider.tsx +115 -29
  350. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +451 -0
  351. package/src/rbac/__tests__/engine.comprehensive.test.ts +12 -0
  352. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +8 -0
  353. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +4 -0
  354. package/src/rbac/api.ts +240 -36
  355. package/src/rbac/cache-invalidation.ts +21 -7
  356. package/src/rbac/compliance/quick-fix-suggestions.ts +1 -1
  357. package/src/rbac/components/NavigationGuard.tsx +23 -63
  358. package/src/rbac/components/NavigationProvider.test.tsx +52 -23
  359. package/src/rbac/components/NavigationProvider.tsx +13 -11
  360. package/src/rbac/components/PagePermissionGuard.tsx +77 -203
  361. package/src/rbac/components/PagePermissionProvider.tsx +13 -11
  362. package/src/rbac/components/PermissionEnforcer.tsx +24 -62
  363. package/src/rbac/components/RoleBasedRouter.tsx +14 -12
  364. package/src/rbac/components/SecureDataProvider.tsx +13 -11
  365. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +104 -41
  366. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +49 -12
  367. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +22 -1
  368. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +161 -82
  369. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +22 -1
  370. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +77 -30
  371. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +39 -5
  372. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +47 -4
  373. package/src/rbac/engine.ts +4 -2
  374. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +144 -52
  375. package/src/rbac/hooks/index.ts +3 -0
  376. package/src/rbac/hooks/useCan.test.ts +101 -53
  377. package/src/rbac/hooks/usePermissions.ts +108 -41
  378. package/src/rbac/hooks/useRBAC.test.ts +11 -3
  379. package/src/rbac/hooks/useRBAC.ts +83 -40
  380. package/src/rbac/hooks/useResolvedScope.test.ts +189 -63
  381. package/src/rbac/hooks/useResolvedScope.ts +128 -70
  382. package/src/rbac/hooks/useSecureSupabase.ts +36 -19
  383. package/src/rbac/hooks/useSuperAdminBypass.ts +126 -0
  384. package/src/rbac/request-deduplication.ts +1 -1
  385. package/src/rbac/secureClient.ts +72 -12
  386. package/src/rbac/security.ts +29 -23
  387. package/src/rbac/types.ts +10 -0
  388. package/src/rbac/utils/__tests__/contextValidator.test.ts +150 -0
  389. package/src/rbac/utils/__tests__/deep-equal.test.ts +53 -0
  390. package/src/rbac/utils/__tests__/eventContext.test.ts +8 -3
  391. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +74 -12
  392. package/src/rbac/utils/contextValidator.ts +288 -0
  393. package/src/rbac/utils/eventContext.ts +52 -3
  394. package/src/services/AuthService.ts +37 -8
  395. package/src/services/EventService.ts +165 -21
  396. package/src/services/OrganisationService.ts +125 -137
  397. package/src/services/__tests__/EventService.test.ts +26 -21
  398. package/src/services/__tests__/OrganisationService.pagination.test.ts +34 -8
  399. package/src/services/__tests__/OrganisationService.test.ts +218 -86
  400. package/src/types/database.generated.ts +166 -201
  401. package/src/types/file-reference.ts +13 -10
  402. package/src/types/supabase.ts +2 -2
  403. package/src/utils/__tests__/secureDataAccess.unit.test.ts +3 -2
  404. package/src/utils/app/appNameResolver.test.ts +346 -73
  405. package/src/utils/context/superAdminOverride.ts +58 -0
  406. package/src/utils/file-reference/index.ts +65 -37
  407. package/src/utils/google-places/googlePlacesUtils.test.ts +98 -0
  408. package/src/utils/google-places/googlePlacesUtils.ts +1 -1
  409. package/src/utils/google-places/loadGoogleMapsScript.test.ts +83 -0
  410. package/src/utils/google-places/types.ts +1 -1
  411. package/src/utils/request-deduplication.ts +4 -4
  412. package/src/utils/security/secureDataAccess.test.ts +1 -1
  413. package/src/utils/security/secureDataAccess.ts +7 -4
  414. package/src/utils/storage/README.md +1 -1
  415. package/src/utils/storage/helpers.test.ts +1 -1
  416. package/src/utils/storage/helpers.ts +38 -19
  417. package/src/utils/storage/types.ts +15 -8
  418. package/src/utils/validation/__tests__/csrf.test.ts +105 -0
  419. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +92 -0
  420. package/src/vite-env.d.ts +2 -2
  421. package/dist/chunk-3GOZZZYH.js.map +0 -1
  422. package/dist/chunk-DDM4CCYT.js.map +0 -1
  423. package/dist/chunk-E7UAOUMY.js +0 -75
  424. package/dist/chunk-E7UAOUMY.js.map +0 -1
  425. package/dist/chunk-F2IMUDXZ.js.map +0 -1
  426. package/dist/chunk-HEHYGYOX.js.map +0 -1
  427. package/dist/chunk-IM4QE42D.js.map +0 -1
  428. package/dist/chunk-MX64ZF6I.js.map +0 -1
  429. package/dist/chunk-SAUPYVLF.js.map +0 -1
  430. package/dist/chunk-THRPYOFK.js.map +0 -1
  431. package/dist/chunk-UCQSRW7Z.js.map +0 -1
  432. package/dist/chunk-VGZZXKBR.js.map +0 -1
  433. package/dist/chunk-YGPFYGA6.js.map +0 -1
  434. package/dist/chunk-YHCN776L.js.map +0 -1
  435. /package/dist/{DataTable-GUFUNZ3N.js.map → DataTable-WKRZD47S.js.map} +0 -0
  436. /package/dist/{UnifiedAuthProvider-643PUAIM.js.map → UnifiedAuthProvider-FTSG5XH7.js.map} +0 -0
  437. /package/dist/{api-YP7XD5L6.js.map → api-IHKALJZD.js.map} +0 -0
  438. /package/dist/{chunk-HESYZWZW.js.map → chunk-QWWZ5CAQ.js.map} +0 -0
@@ -69,17 +69,24 @@ describe('useSecureSupabase Hook', () => {
69
69
  const mockUseResolvedScope = vi.mocked(useResolvedScope);
70
70
  const mockCreateSecureClient = vi.mocked(createSecureClient);
71
71
 
72
- const originalEnv = import.meta.env;
73
-
74
72
  beforeEach(() => {
75
73
  vi.clearAllMocks();
76
74
 
77
- // Setup environment variables - use the same pattern as other tests
75
+ // Clear the secure client cache by accessing it through a test helper
76
+ // The cache is module-level, so we need to ensure it's cleared
77
+ // We'll use unique org IDs in each test to avoid cache hits
78
+
79
+ // Setup environment variables - mock both import.meta.env and process.env
80
+ // The getSupabaseConfig function checks both
81
+ vi.stubEnv('VITE_SUPABASE_URL', 'https://test.supabase.co');
82
+ vi.stubEnv('VITE_SUPABASE_PUBLISHABLE_KEY', 'test-key');
83
+
84
+ // Also set import.meta.env directly since the function checks it first
78
85
  Object.defineProperty(import.meta, 'env', {
79
86
  value: {
80
87
  VITE_SUPABASE_URL: 'https://test.supabase.co',
81
- VITE_SUPABASE_ANON_KEY: 'test-key',
82
- ...originalEnv
88
+ VITE_SUPABASE_PUBLISHABLE_KEY: 'test-key',
89
+ ...import.meta.env
83
90
  },
84
91
  writable: true,
85
92
  configurable: true
@@ -128,9 +135,11 @@ describe('useSecureSupabase Hook', () => {
128
135
 
129
136
  afterEach(() => {
130
137
  vi.clearAllMocks();
131
- // Restore original environment
138
+ // Restore environment
139
+ vi.unstubAllEnvs();
140
+ // Restore import.meta.env
132
141
  Object.defineProperty(import.meta, 'env', {
133
- value: originalEnv,
142
+ value: import.meta.env,
134
143
  writable: true,
135
144
  configurable: true
136
145
  });
@@ -138,15 +147,36 @@ describe('useSecureSupabase Hook', () => {
138
147
 
139
148
  describe('Client Creation', () => {
140
149
  it('should create a secure client when context is available', async () => {
150
+ // Use a unique org ID to avoid cache hits from previous tests
151
+ const uniqueOrgId = `org-${Date.now()}`;
152
+ mockUseOrganisations.mockReturnValue({
153
+ selectedOrganisation: { id: uniqueOrgId },
154
+ organisations: [],
155
+ isLoading: false,
156
+ error: null,
157
+ selectOrganisation: vi.fn(),
158
+ refreshOrganisations: vi.fn()
159
+ } as any);
160
+
161
+ mockUseResolvedScope.mockReturnValue({
162
+ resolvedScope: {
163
+ organisationId: uniqueOrgId,
164
+ eventId: mockEventId,
165
+ appId: mockAppId
166
+ },
167
+ isLoading: false,
168
+ error: null
169
+ });
170
+
141
171
  const { result } = renderHook(() => useSecureSupabase());
142
172
 
143
173
  await waitFor(() => {
144
- expect(result.current).toBe(mockSupabaseClient);
145
- });
174
+ expect(mockCreateSecureClient).toHaveBeenCalled();
175
+ }, { timeout: 2000 });
146
176
 
147
- expect(mockCreateSecureClient).toHaveBeenCalled();
177
+ expect(result.current).toBe(mockSupabaseClient);
148
178
  const call = mockCreateSecureClient.mock.calls[0];
149
- expect(call[2]).toBe(mockOrgId);
179
+ expect(call[2]).toBe(uniqueOrgId);
150
180
  expect(call[3]).toBe(mockEventId);
151
181
  expect(call[4]).toBe(mockAppId);
152
182
  });
@@ -179,6 +209,13 @@ describe('useSecureSupabase Hook', () => {
179
209
  selectOrganisation: vi.fn(),
180
210
  refreshOrganisations: vi.fn()
181
211
  } as any);
212
+
213
+ // Mock useResolvedScope to return null scope when organisation is not available
214
+ mockUseResolvedScope.mockReturnValue({
215
+ resolvedScope: null,
216
+ isLoading: false,
217
+ error: null
218
+ });
182
219
 
183
220
  const baseClient = mockSupabaseClient;
184
221
  const { result } = renderHook(() => useSecureSupabase(baseClient));
@@ -256,18 +293,39 @@ describe('useSecureSupabase Hook', () => {
256
293
  });
257
294
 
258
295
  it('should create new client when context changes', async () => {
296
+ const uniqueOrgId1 = `org-${Date.now()}-1`;
297
+ mockUseOrganisations.mockReturnValue({
298
+ selectedOrganisation: { id: uniqueOrgId1 },
299
+ organisations: [],
300
+ isLoading: false,
301
+ error: null,
302
+ selectOrganisation: vi.fn(),
303
+ refreshOrganisations: vi.fn()
304
+ } as any);
305
+
306
+ mockUseResolvedScope.mockReturnValue({
307
+ resolvedScope: {
308
+ organisationId: uniqueOrgId1,
309
+ eventId: mockEventId,
310
+ appId: mockAppId
311
+ },
312
+ isLoading: false,
313
+ error: null
314
+ });
315
+
259
316
  const { result: result1, rerender: rerender1 } = renderHook(() => useSecureSupabase());
260
317
 
261
318
  await waitFor(() => {
262
- expect(result1.current).toBe(mockSupabaseClient);
263
- });
319
+ expect(mockCreateSecureClient).toHaveBeenCalled();
320
+ }, { timeout: 2000 });
264
321
 
265
322
  // Clear the mock to count new calls
266
323
  mockCreateSecureClient.mockClear();
267
324
 
268
325
  // Change organisation - this should create a new client with different cache key
326
+ const uniqueOrgId2 = `org-${Date.now()}-2`;
269
327
  mockUseOrganisations.mockReturnValue({
270
- selectedOrganisation: { id: 'org-456' },
328
+ selectedOrganisation: { id: uniqueOrgId2 },
271
329
  organisations: [],
272
330
  isLoading: false,
273
331
  error: null,
@@ -278,7 +336,7 @@ describe('useSecureSupabase Hook', () => {
278
336
  // Also update resolved scope to match
279
337
  mockUseResolvedScope.mockReturnValue({
280
338
  resolvedScope: {
281
- organisationId: 'org-456',
339
+ organisationId: uniqueOrgId2,
282
340
  eventId: mockEventId,
283
341
  appId: mockAppId
284
342
  },
@@ -296,14 +354,9 @@ describe('useSecureSupabase Hook', () => {
296
354
 
297
355
  describe('Environment Variables', () => {
298
356
  it('should fallback to base client when Supabase URL is missing', () => {
299
- Object.defineProperty(import.meta, 'env', {
300
- value: {
301
- VITE_SUPABASE_ANON_KEY: 'test-key',
302
- ...originalEnv
303
- },
304
- writable: true,
305
- configurable: true
306
- });
357
+ vi.unstubAllEnvs();
358
+ vi.stubEnv('VITE_SUPABASE_PUBLISHABLE_KEY', 'test-key');
359
+ // VITE_SUPABASE_URL is not set
307
360
 
308
361
  const baseClient = mockSupabaseClient;
309
362
  const { result } = renderHook(() => useSecureSupabase(baseClient));
@@ -313,14 +366,9 @@ describe('useSecureSupabase Hook', () => {
313
366
  });
314
367
 
315
368
  it('should fallback to base client when Supabase key is missing', () => {
316
- Object.defineProperty(import.meta, 'env', {
317
- value: {
318
- VITE_SUPABASE_URL: 'https://test.supabase.co',
319
- ...originalEnv
320
- },
321
- writable: true,
322
- configurable: true
323
- });
369
+ vi.unstubAllEnvs();
370
+ vi.stubEnv('VITE_SUPABASE_URL', 'https://test.supabase.co');
371
+ // VITE_SUPABASE_PUBLISHABLE_KEY is not set
324
372
 
325
373
  const baseClient = mockSupabaseClient;
326
374
  const { result } = renderHook(() => useSecureSupabase(baseClient));
@@ -342,30 +390,54 @@ describe('useSecureSupabase Hook', () => {
342
390
  expect(result.current).toBe(baseClient);
343
391
  });
344
392
 
345
- it('should handle missing resolved scope gracefully', () => {
393
+ it('should handle missing resolved scope gracefully', async () => {
394
+ // Use unique org ID to avoid cache
395
+ const uniqueOrgId = `org-${Date.now()}-missing-scope`;
396
+ mockUseOrganisations.mockReturnValue({
397
+ selectedOrganisation: { id: uniqueOrgId },
398
+ organisations: [],
399
+ isLoading: false,
400
+ error: null,
401
+ selectOrganisation: vi.fn(),
402
+ refreshOrganisations: vi.fn()
403
+ } as any);
404
+
405
+ // When resolvedScope is null but selectedOrganisation exists,
406
+ // useSecureSupabase should still create a client using selectedOrganisation.id
407
+ // This is a fallback behavior when scope resolution fails
346
408
  mockUseResolvedScope.mockReturnValue({
347
409
  resolvedScope: null,
348
410
  isLoading: false,
349
411
  error: null
350
412
  });
351
413
 
352
- const { result } = renderHook(() => useSecureSupabase());
414
+ const baseClient = mockSupabaseClient;
415
+ const { result } = renderHook(() => useSecureSupabase(baseClient));
353
416
 
354
- // Should still create client with undefined appId
355
- expect(mockCreateSecureClient).toHaveBeenCalled();
356
- const call = mockCreateSecureClient.mock.calls[0];
357
- expect(call[2]).toBe(mockOrgId);
358
- expect(call[3]).toBe(mockEventId);
359
- expect(call[4]).toBeUndefined();
417
+ // When resolvedScope is null, should return base client (fallback)
418
+ expect(result.current).toBe(baseClient);
419
+ // Should not create secure client when resolvedScope is null
420
+ expect(mockCreateSecureClient).not.toHaveBeenCalled();
360
421
  });
361
422
  });
362
423
 
363
424
  describe('Context Resolution', () => {
364
425
  it('should use appId from resolved scope', async () => {
426
+ const uniqueOrgId = `org-${Date.now()}-custom-app`;
365
427
  const customAppId = 'custom-app-123';
428
+
429
+ mockUseOrganisations.mockReturnValue({
430
+ selectedOrganisation: { id: uniqueOrgId },
431
+ organisations: [],
432
+ isLoading: false,
433
+ error: null,
434
+ selectOrganisation: vi.fn(),
435
+ refreshOrganisations: vi.fn()
436
+ } as any);
437
+
366
438
  mockUseResolvedScope.mockReturnValue({
367
439
  resolvedScope: {
368
- organisationId: mockOrgId,
440
+ organisationId: uniqueOrgId,
369
441
  eventId: mockEventId,
370
442
  appId: customAppId
371
443
  },
@@ -377,14 +449,17 @@ describe('useSecureSupabase Hook', () => {
377
449
 
378
450
  await waitFor(() => {
379
451
  expect(mockCreateSecureClient).toHaveBeenCalled();
380
- const call = mockCreateSecureClient.mock.calls[0];
381
- expect(call[2]).toBe(mockOrgId);
382
- expect(call[3]).toBe(mockEventId);
383
- expect(call[4]).toBe(customAppId);
384
- });
452
+ }, { timeout: 2000 });
453
+
454
+ const call = mockCreateSecureClient.mock.calls[0];
455
+ expect(call[2]).toBe(uniqueOrgId);
456
+ expect(call[3]).toBe(mockEventId);
457
+ expect(call[4]).toBe(customAppId);
385
458
  });
386
459
 
387
460
  it('should work without event context', async () => {
461
+ const uniqueOrgId = `org-${Date.now()}-no-event`;
462
+
388
463
  mockUseEvents.mockReturnValue({
389
464
  events: [],
390
465
  selectedEvent: null,
@@ -396,9 +471,18 @@ describe('useSecureSupabase Hook', () => {
396
471
  eventLoading: false
397
472
  } as any);
398
473
 
474
+ mockUseOrganisations.mockReturnValue({
475
+ selectedOrganisation: { id: uniqueOrgId },
476
+ organisations: [],
477
+ isLoading: false,
478
+ error: null,
479
+ selectOrganisation: vi.fn(),
480
+ refreshOrganisations: vi.fn()
481
+ } as any);
482
+
399
483
  mockUseResolvedScope.mockReturnValue({
400
484
  resolvedScope: {
401
- organisationId: mockOrgId,
485
+ organisationId: uniqueOrgId,
402
486
  eventId: undefined,
403
487
  appId: mockAppId
404
488
  },
@@ -410,11 +494,12 @@ describe('useSecureSupabase Hook', () => {
410
494
 
411
495
  await waitFor(() => {
412
496
  expect(mockCreateSecureClient).toHaveBeenCalled();
413
- const call = mockCreateSecureClient.mock.calls[0];
414
- expect(call[2]).toBe(mockOrgId);
415
- expect(call[3]).toBeUndefined();
416
- expect(call[4]).toBe(mockAppId);
417
- });
497
+ }, { timeout: 2000 });
498
+
499
+ const call = mockCreateSecureClient.mock.calls[0];
500
+ expect(call[2]).toBe(uniqueOrgId);
501
+ expect(call[3]).toBeUndefined();
502
+ expect(call[4]).toBe(mockAppId);
418
503
  });
419
504
  });
420
505
 
@@ -428,8 +513,15 @@ describe('useSecureSupabase Hook', () => {
428
513
  selectOrganisation: vi.fn(),
429
514
  refreshOrganisations: vi.fn()
430
515
  } as any);
516
+
517
+ // Mock useResolvedScope to return null scope when context is unavailable
518
+ mockUseResolvedScope.mockReturnValue({
519
+ resolvedScope: null,
520
+ isLoading: false,
521
+ error: null
522
+ });
431
523
 
432
- const customBaseClient = { from: vi.fn() } as unknown as SupabaseClient<Database>;
524
+ const customBaseClient = { from: vi.fn(), auth: { getUser: vi.fn(), getSession: vi.fn() } } as unknown as SupabaseClient<Database>;
433
525
  const { result } = renderHook(() => useSecureSupabase(customBaseClient));
434
526
 
435
527
  expect(result.current).toBe(customBaseClient);
@@ -35,3 +35,6 @@ export type {
35
35
 
36
36
  // Export secure Supabase client hook
37
37
  export { useSecureSupabase } from './useSecureSupabase';
38
+
39
+ // Export super admin bypass hook
40
+ export { useSuperAdminBypass } from './useSuperAdminBypass';
@@ -23,7 +23,8 @@ import { isPermitted, isPermittedCached } from '../api';
23
23
  const mockUserId = 'user-123';
24
24
  const mockScope = {
25
25
  organisationId: 'org-123',
26
- eventId: 'event-123'
26
+ eventId: 'event-123',
27
+ appId: 'app-123' // Required for page name resolution
27
28
  };
28
29
  const mockPermission = 'read:users';
29
30
  const mockPageId = 'dashboard';
@@ -32,6 +33,13 @@ describe('useCan Hook', () => {
32
33
  const mockIsPermitted = vi.mocked(isPermitted);
33
34
  const mockIsPermittedCached = vi.mocked(isPermittedCached);
34
35
 
36
+ beforeEach(() => {
37
+ vi.clearAllMocks();
38
+ // Reset mocks to return resolved promises by default
39
+ mockIsPermitted.mockResolvedValue(true);
40
+ mockIsPermittedCached.mockResolvedValue(true);
41
+ });
42
+
35
43
  describe('Permission Checking', () => {
36
44
  it('returns true for allowed permissions', async () => {
37
45
  mockIsPermitted.mockResolvedValue(true);
@@ -103,12 +111,16 @@ describe('useCan Hook', () => {
103
111
  await waitFor(() => {
104
112
  expect(result.current.isLoading).toBe(false);
105
113
  expect(result.current.can).toBe(true);
106
- expect(mockIsPermittedCached).toHaveBeenCalledWith({
107
- userId: mockUserId,
108
- scope: mockScope,
109
- permission: mockPermission,
110
- pageId: mockPageId
111
- });
114
+ expect(mockIsPermittedCached).toHaveBeenCalledWith(
115
+ {
116
+ userId: mockUserId,
117
+ scope: mockScope,
118
+ permission: mockPermission,
119
+ pageId: mockPageId
120
+ },
121
+ undefined,
122
+ undefined
123
+ );
112
124
  expect(mockIsPermitted).not.toHaveBeenCalled();
113
125
  });
114
126
  });
@@ -123,12 +135,16 @@ describe('useCan Hook', () => {
123
135
  await waitFor(() => {
124
136
  expect(result.current.isLoading).toBe(false);
125
137
  expect(result.current.can).toBe(true);
126
- expect(mockIsPermitted).toHaveBeenCalledWith({
127
- userId: mockUserId,
128
- scope: mockScope,
129
- permission: mockPermission,
130
- pageId: mockPageId
131
- });
138
+ expect(mockIsPermitted).toHaveBeenCalledWith(
139
+ {
140
+ userId: mockUserId,
141
+ scope: mockScope,
142
+ permission: mockPermission,
143
+ pageId: mockPageId
144
+ },
145
+ undefined,
146
+ undefined
147
+ );
132
148
  expect(mockIsPermittedCached).not.toHaveBeenCalled();
133
149
  });
134
150
  });
@@ -158,12 +174,16 @@ describe('useCan Hook', () => {
158
174
 
159
175
  await waitFor(() => {
160
176
  expect(result.current.isLoading).toBe(false);
161
- expect(mockIsPermitted).toHaveBeenCalledWith({
162
- userId: mockUserId,
163
- scope: mockScope,
164
- permission: mockPermission,
165
- pageId: 'custom-page'
166
- });
177
+ expect(mockIsPermitted).toHaveBeenCalledWith(
178
+ {
179
+ userId: mockUserId,
180
+ scope: mockScope,
181
+ permission: mockPermission,
182
+ pageId: 'custom-page'
183
+ },
184
+ undefined,
185
+ undefined
186
+ );
167
187
  });
168
188
  });
169
189
 
@@ -176,12 +196,16 @@ describe('useCan Hook', () => {
176
196
 
177
197
  await waitFor(() => {
178
198
  expect(result.current.isLoading).toBe(false);
179
- expect(mockIsPermitted).toHaveBeenCalledWith({
180
- userId: mockUserId,
181
- scope: mockScope,
182
- permission: mockPermission,
183
- pageId: undefined
184
- });
199
+ expect(mockIsPermitted).toHaveBeenCalledWith(
200
+ {
201
+ userId: mockUserId,
202
+ scope: mockScope,
203
+ permission: mockPermission,
204
+ pageId: undefined
205
+ },
206
+ undefined,
207
+ undefined
208
+ );
185
209
  });
186
210
  });
187
211
  });
@@ -214,12 +238,16 @@ describe('useCan Hook', () => {
214
238
 
215
239
  await waitFor(() => {
216
240
  expect(mockIsPermitted).toHaveBeenCalledTimes(2);
217
- expect(mockIsPermitted).toHaveBeenLastCalledWith({
218
- userId: 'user-456',
219
- scope: mockScope,
220
- permission: mockPermission,
221
- pageId: undefined
222
- });
241
+ expect(mockIsPermitted).toHaveBeenLastCalledWith(
242
+ {
243
+ userId: 'user-456',
244
+ scope: mockScope,
245
+ permission: mockPermission,
246
+ pageId: undefined
247
+ },
248
+ undefined,
249
+ undefined
250
+ );
223
251
  });
224
252
  });
225
253
 
@@ -251,12 +279,16 @@ describe('useCan Hook', () => {
251
279
 
252
280
  await waitFor(() => {
253
281
  expect(mockIsPermitted).toHaveBeenCalledTimes(2);
254
- expect(mockIsPermitted).toHaveBeenLastCalledWith({
255
- userId: mockUserId,
256
- scope: newScope,
257
- permission: mockPermission,
258
- pageId: undefined
259
- });
282
+ expect(mockIsPermitted).toHaveBeenLastCalledWith(
283
+ {
284
+ userId: mockUserId,
285
+ scope: newScope,
286
+ permission: mockPermission,
287
+ pageId: undefined
288
+ },
289
+ undefined,
290
+ undefined
291
+ );
260
292
  });
261
293
  });
262
294
 
@@ -287,12 +319,16 @@ describe('useCan Hook', () => {
287
319
 
288
320
  await waitFor(() => {
289
321
  expect(mockIsPermitted).toHaveBeenCalledTimes(2);
290
- expect(mockIsPermitted).toHaveBeenLastCalledWith({
291
- userId: mockUserId,
292
- scope: mockScope,
293
- permission: 'create:users',
294
- pageId: undefined
295
- });
322
+ expect(mockIsPermitted).toHaveBeenLastCalledWith(
323
+ {
324
+ userId: mockUserId,
325
+ scope: mockScope,
326
+ permission: 'create:users',
327
+ pageId: undefined
328
+ },
329
+ undefined,
330
+ undefined
331
+ );
296
332
  });
297
333
  });
298
334
  });
@@ -359,12 +395,16 @@ describe('useCan Hook', () => {
359
395
  expect(result.current.error).toBeNull();
360
396
  });
361
397
 
362
- expect(mockIsPermitted).toHaveBeenCalledWith({
398
+ expect(mockIsPermitted).toHaveBeenCalledWith(
399
+ {
363
400
  userId: mockUserId,
364
401
  scope: mockScope,
365
402
  permission: 'update:organisations',
366
403
  pageId: undefined
367
- });
404
+ },
405
+ undefined,
406
+ undefined
407
+ );
368
408
  });
369
409
 
370
410
  it('denies super admin permissions for regular users', async () => {
@@ -495,12 +535,16 @@ describe('useCan Hook', () => {
495
535
  expect(result.current.error).toBeNull();
496
536
  });
497
537
 
498
- expect(mockIsPermittedCached).toHaveBeenCalledWith({
538
+ expect(mockIsPermittedCached).toHaveBeenCalledWith(
539
+ {
499
540
  userId: mockUserId,
500
541
  scope: mockScope,
501
542
  permission: mockPermission,
502
543
  pageId: mockPageId
503
- });
544
+ },
545
+ undefined,
546
+ undefined
547
+ );
504
548
  });
505
549
 
506
550
  it('handles permission denied with fallback to false', async () => {
@@ -579,12 +623,16 @@ describe('useCan Hook', () => {
579
623
  await waitFor(() => {
580
624
  expect(result.current.isLoading).toBe(false);
581
625
  expect(result.current.can).toBe(false);
582
- expect(mockIsPermitted).toHaveBeenCalledWith({
583
- userId: mockUserId,
584
- scope: mockScope,
585
- permission: '',
586
- pageId: undefined
587
- });
626
+ expect(mockIsPermitted).toHaveBeenCalledWith(
627
+ {
628
+ userId: mockUserId,
629
+ scope: mockScope,
630
+ permission: '',
631
+ pageId: undefined
632
+ },
633
+ undefined,
634
+ undefined
635
+ );
588
636
  });
589
637
  });
590
638