@jmruthers/pace-core 0.6.9 → 0.6.11

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 (1182) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/audit-tool/00-dependencies.cjs +46 -13
  3. package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
  4. package/audit-tool/audits/02-project-structure.cjs +74 -2
  5. package/audit-tool/audits/03-architecture.cjs +220 -20
  6. package/audit-tool/audits/04-code-quality.cjs +95 -3
  7. package/audit-tool/audits/05-styling.cjs +19 -7
  8. package/audit-tool/audits/06-security-rbac.cjs +214 -25
  9. package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
  10. package/audit-tool/audits/08-testing-documentation.cjs +11 -3
  11. package/audit-tool/audits/09-operations.cjs +19 -7
  12. package/audit-tool/index.cjs +22 -11
  13. package/audit-tool/utils/report-utils.cjs +4 -0
  14. package/cursor-rules/01-pace-core-compliance.mdc +1 -0
  15. package/cursor-rules/02-project-structure.mdc +3 -26
  16. package/cursor-rules/03-architecture.mdc +3 -1
  17. package/cursor-rules/04-code-quality.mdc +1 -0
  18. package/cursor-rules/05-styling.mdc +120 -8
  19. package/cursor-rules/06-security-rbac.mdc +126 -2
  20. package/cursor-rules/07-api-tech-stack.mdc +1 -0
  21. package/cursor-rules/08-testing-documentation.mdc +1 -0
  22. package/cursor-rules/09-operations.mdc +1 -0
  23. package/dist/DataTable-EFYP2QLE.js +16 -0
  24. package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
  25. package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
  26. package/dist/api-BZR2CYXL.js +5 -0
  27. package/dist/api-result-USV1Czr-.d.ts +51 -0
  28. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  29. package/dist/assets/app-icons/base_favicon.svg +85 -0
  30. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  31. package/dist/assets/app-icons/core_favicon.svg +256 -0
  32. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  33. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  34. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  35. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  36. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  37. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  38. package/dist/assets/app-icons/team_favicon.svg +67 -0
  39. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  40. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  41. package/dist/audit-HI2DHUVU.js +4 -0
  42. package/dist/auth-JvdRVaud.d.ts +49 -0
  43. package/dist/chunk-2DL2WSOE.js +327 -0
  44. package/dist/chunk-2OEVOGGR.js +9598 -0
  45. package/dist/chunk-44CNXN4P.js +15 -0
  46. package/dist/chunk-4R3T5ENU.js +2943 -0
  47. package/dist/chunk-7A6IMHH2.js +2321 -0
  48. package/dist/chunk-BTHN5MKC.js +121 -0
  49. package/dist/chunk-CU2BU2MQ.js +2 -0
  50. package/dist/chunk-D6BMFMQZ.js +200 -0
  51. package/dist/chunk-DDMPHZ3D.js +58 -0
  52. package/dist/chunk-ENLXB7GP.js +721 -0
  53. package/dist/chunk-J2KQK6DG.js +2159 -0
  54. package/dist/chunk-KJXRL3XE.js +6434 -0
  55. package/dist/chunk-L5LFKKLJ.js +61 -0
  56. package/dist/chunk-PCSHBLPB.js +811 -0
  57. package/dist/chunk-QRYSEPHB.js +429 -0
  58. package/dist/chunk-RMLY6KB5.js +187 -0
  59. package/dist/chunk-SACF5YSM.js +31 -0
  60. package/dist/chunk-UZNAFKGW.js +125 -0
  61. package/dist/chunk-V7FTM2LU.js +1080 -0
  62. package/dist/chunk-WY6Y7KC3.js +264 -0
  63. package/dist/chunk-XOJME5T7.js +407 -0
  64. package/dist/chunk-XPFVT3GN.js +492 -0
  65. package/dist/chunk-YFTFFJIV.js +529 -0
  66. package/dist/chunk-YYTWKVHO.js +1334 -0
  67. package/dist/components.d.ts +12 -89
  68. package/dist/components.js +23 -55
  69. package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
  70. package/dist/eslint-rules/index.cjs +3 -0
  71. package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
  72. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  73. package/dist/eslint-rules/rules/06-security-rbac.cjs +84 -0
  74. package/dist/event-BfCox3N2.d.ts +265 -0
  75. package/dist/file-reference-DU1hcawx.d.ts +164 -0
  76. package/dist/functions-DH45k8ec.d.ts +208 -0
  77. package/dist/hooks.d.ts +28 -14
  78. package/dist/hooks.js +90 -56
  79. package/dist/icons/index.d.ts +1 -0
  80. package/dist/icons/index.js +1 -0
  81. package/dist/index.d.ts +392 -155
  82. package/dist/index.js +337 -347
  83. package/dist/pagination-BW1mqywp.d.ts +201 -0
  84. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  85. package/dist/providers.d.ts +29 -14
  86. package/dist/providers.js +7 -5
  87. package/dist/rbac/eslint-rules.js +2 -2
  88. package/dist/rbac/index.d.ts +180 -351
  89. package/dist/rbac/index.js +13 -11
  90. package/dist/theming/runtime.d.ts +28 -5
  91. package/dist/theming/runtime.js +2 -2
  92. package/dist/timezone-BTWWXKVY.d.ts +696 -0
  93. package/dist/types-BE2sEHKd.d.ts +55 -0
  94. package/dist/types-CvOPXWWZ.d.ts +111 -0
  95. package/dist/types-Dr8sNhER.d.ts +50 -0
  96. package/dist/types.d.ts +20 -13
  97. package/dist/types.js +1 -0
  98. package/dist/usePublicPageContext-B91dGYW1.d.ts +4367 -0
  99. package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
  100. package/dist/utils.d.ts +338 -156
  101. package/dist/utils.js +78 -60
  102. package/dist/validation-g5n0hDkh.d.ts +177 -0
  103. package/docs/api/modules.md +1226 -1094
  104. package/docs/api-reference/components.md +5 -5
  105. package/docs/api-reference/rpc-functions.md +12 -3
  106. package/docs/core-concepts/rbac-system.md +8 -0
  107. package/docs/getting-started/cursor-rules.md +17 -20
  108. package/docs/getting-started/dependencies.md +1 -1
  109. package/docs/getting-started/setup.md +235 -0
  110. package/docs/implementation-guides/authentication.md +27 -0
  111. package/docs/implementation-guides/data-tables.md +365 -10
  112. package/docs/migration/ApiResult-migration.md +25 -0
  113. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  114. package/docs/rbac/api-reference.md +33 -31
  115. package/docs/standards/0-standards-overview.md +50 -15
  116. package/docs/standards/1-pace-core-compliance-standards.md +62 -57
  117. package/docs/standards/2-project-structure-standards.md +45 -90
  118. package/docs/standards/3-architecture-standards.md +41 -1
  119. package/docs/standards/4-code-quality-standards.md +26 -6
  120. package/docs/standards/5-styling-standards.md +35 -1
  121. package/docs/standards/6-security-rbac-standards.md +288 -7
  122. package/docs/standards/7-api-tech-stack-standards.md +116 -17
  123. package/docs/standards/8-testing-documentation-standards.md +31 -0
  124. package/docs/standards/9-operations-standards.md +19 -0
  125. package/docs/standards/README.md +20 -201
  126. package/docs/testing/README.md +10 -0
  127. package/docs/testing/test-setup-for-consumers.md +916 -0
  128. package/docs/troubleshooting/common-issues.md +17 -1
  129. package/docs/troubleshooting/organisation-context-setup.md +8 -0
  130. package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
  131. package/eslint-config-pace-core.cjs +24 -0
  132. package/package.json +14 -20
  133. package/scripts/build-docs.js +180 -0
  134. package/scripts/setup.cjs +536 -0
  135. package/scripts/validate.cjs +480 -0
  136. package/src/__mocks__/lucide-react.ts +0 -2
  137. package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
  138. package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
  139. package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
  140. package/src/__tests__/helpers/test-providers.test.tsx +99 -0
  141. package/src/__tests__/helpers/test-providers.tsx +37 -39
  142. package/src/__tests__/helpers/test-utils.test.tsx +447 -0
  143. package/src/__tests__/helpers/timer-utils.test.ts +371 -0
  144. package/src/assets/app-icons/admin_favicon.svg +462 -0
  145. package/src/assets/app-icons/base_favicon.svg +85 -0
  146. package/src/assets/app-icons/cake_favicon.svg +68 -0
  147. package/src/assets/app-icons/core_favicon.svg +256 -0
  148. package/src/assets/app-icons/gear_favicon.svg +91 -0
  149. package/src/assets/app-icons/index.test.ts +304 -0
  150. package/src/assets/app-icons/index.ts +83 -0
  151. package/src/assets/app-icons/medi_favicon.svg +92 -0
  152. package/src/assets/app-icons/mint_favicon.svg +83 -0
  153. package/src/assets/app-icons/pace_favicon.svg +49 -0
  154. package/src/assets/app-icons/pump_favicon.svg +68 -0
  155. package/src/assets/app-icons/seed_favicon.svg +91 -0
  156. package/src/assets/app-icons/team_favicon.svg +67 -0
  157. package/src/assets/app-icons/trac_favicon.svg +112 -0
  158. package/src/assets/app-icons/trip_favicon.svg +102 -0
  159. package/src/components/AddressField/AddressField.test.tsx +379 -4
  160. package/src/components/AddressField/AddressField.tsx +239 -213
  161. package/src/components/AddressField/types.ts +2 -2
  162. package/src/components/Alert/Alert.test.tsx +35 -25
  163. package/src/components/Alert/Alert.tsx +8 -8
  164. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  165. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  166. package/src/components/Avatar/Avatar.test.tsx +11 -1
  167. package/src/components/Avatar/Avatar.tsx +3 -2
  168. package/src/components/Badge/Badge.test.tsx +11 -1
  169. package/src/components/Button/Button.test.tsx +13 -3
  170. package/src/components/Button/Button.tsx +1 -1
  171. package/src/components/Calendar/Calendar.test.tsx +523 -131
  172. package/src/components/Calendar/Calendar.tsx +107 -488
  173. package/src/components/Card/Card.test.tsx +384 -258
  174. package/src/components/Card/Card.tsx +19 -10
  175. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  176. package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
  177. package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
  178. package/src/components/ContextSelector/ContextSelector.tsx +66 -280
  179. package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
  180. package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
  181. package/src/components/DataTable/AUDIT_REPORT.md +59 -44
  182. package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
  183. package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
  184. package/src/components/DataTable/DataTable.export.test.tsx +705 -0
  185. package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
  186. package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
  187. package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
  188. package/src/components/DataTable/DataTable.test.tsx +787 -416
  189. package/src/components/DataTable/DataTable.tsx +14 -14
  190. package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
  191. package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
  192. package/src/components/DataTable/DataTableCore.test.tsx +970 -0
  193. package/src/components/DataTable/README.md +155 -0
  194. package/src/components/DataTable/TESTING.md +101 -0
  195. package/src/components/DataTable/a11y.basic.test.tsx +788 -0
  196. package/src/components/DataTable/components/DataTableCore.tsx +126 -894
  197. package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
  198. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -3
  199. package/src/components/DataTable/components/ImportModal.tsx +82 -408
  200. package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
  201. package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
  202. package/src/components/DataTable/context/DataTableContext.tsx +13 -13
  203. package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
  204. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  205. package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
  206. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  207. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
  208. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +15 -3
  211. package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
  212. package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
  213. package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
  214. package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
  215. package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
  216. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
  217. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
  218. package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
  219. package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
  220. package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
  221. package/src/components/DataTable/hooks/useDataTablePermissions.ts +81 -260
  222. package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
  223. package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
  224. package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
  225. package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
  226. package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
  227. package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
  228. package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
  229. package/src/components/DataTable/hooks/useDataTableState.ts +161 -114
  230. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
  231. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
  232. package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
  233. package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
  234. package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
  235. package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
  236. package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
  237. package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
  238. package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
  239. package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
  240. package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
  241. package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
  242. package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
  243. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +311 -271
  244. package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
  245. package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
  246. package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
  247. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +27 -4
  248. package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
  249. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  250. package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
  251. package/src/components/DataTable/hooks/useTableHandlers.ts +13 -22
  252. package/src/components/DataTable/index.ts +28 -5
  253. package/src/components/DataTable/keyboard.test.tsx +734 -0
  254. package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
  255. package/src/components/DataTable/pagination.modes.test.tsx +728 -0
  256. package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
  257. package/src/components/DataTable/styles.test.ts +379 -0
  258. package/src/components/DataTable/styles.ts +0 -1
  259. package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
  260. package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
  261. package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
  262. package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
  263. package/src/components/DataTable/test-utils.ts +94 -0
  264. package/src/components/DataTable/types/actions.ts +71 -0
  265. package/src/components/DataTable/types/base.ts +39 -0
  266. package/src/components/DataTable/types/columns.ts +125 -0
  267. package/src/components/DataTable/types/export.ts +32 -0
  268. package/src/components/DataTable/types/features.ts +81 -0
  269. package/src/components/DataTable/types/hierarchical.ts +44 -0
  270. package/src/components/DataTable/types/index.ts +43 -0
  271. package/src/components/DataTable/types/pagination.ts +85 -0
  272. package/src/components/DataTable/types/performance.ts +47 -0
  273. package/src/components/DataTable/types/props.ts +62 -0
  274. package/src/components/DataTable/types/rbac.ts +45 -0
  275. package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
  276. package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
  277. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
  278. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
  279. package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
  280. package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
  281. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
  282. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
  283. package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
  284. package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
  285. package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
  286. package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
  287. package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
  288. package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
  289. package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
  290. package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
  291. package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
  292. package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
  293. package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
  294. package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
  295. package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
  296. package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
  297. package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
  298. package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
  299. package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
  300. package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
  301. package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
  302. package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
  303. package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
  304. package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
  305. package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
  306. package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
  307. package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
  308. package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
  309. package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
  310. package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
  311. package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
  312. package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
  313. package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
  314. package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
  315. package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
  316. package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
  317. package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
  318. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
  319. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
  320. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
  321. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
  322. package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
  323. package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
  324. package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
  325. package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
  326. package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
  327. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  328. package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
  329. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  330. package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
  331. package/src/components/DataTable/utils/csvParse.test.ts +74 -0
  332. package/src/components/DataTable/utils/csvParse.ts +65 -0
  333. package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
  334. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  335. package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
  336. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  337. package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
  338. package/src/components/DataTable/utils/flexibleImport.ts +3 -186
  339. package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
  340. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  341. package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
  342. package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
  343. package/src/components/DataTable/utils/importDateParser.ts +114 -0
  344. package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
  345. package/src/components/DataTable/utils/importValueParser.ts +91 -0
  346. package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
  347. package/src/components/DataTable/utils/paginationUtils.ts +7 -4
  348. package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
  349. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  350. package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
  351. package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
  352. package/src/components/DataTable/utils/selectFieldUtils.ts +97 -67
  353. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +18 -25
  354. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  355. package/src/components/DateTimeField/DateTimeField.test.tsx +3 -16
  356. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  357. package/src/components/Dialog/Dialog.test-utils.ts +49 -0
  358. package/src/components/Dialog/Dialog.test.tsx +2865 -458
  359. package/src/components/Dialog/Dialog.tsx +183 -986
  360. package/src/components/Dialog/dialogLock.test.ts +238 -0
  361. package/src/components/Dialog/dialogLock.ts +98 -0
  362. package/src/components/Dialog/index.ts +2 -0
  363. package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
  364. package/src/components/Dialog/useDialogDimensions.ts +140 -0
  365. package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
  366. package/src/components/Dialog/useDialogLifecycle.ts +135 -0
  367. package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
  368. package/src/components/Dialog/useDialogPersistence.ts +357 -0
  369. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  370. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  371. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  372. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  373. package/src/components/ErrorBoundary/index.ts +3 -4
  374. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  375. package/src/components/FileDisplay/FileDisplay.test.tsx +479 -247
  376. package/src/components/FileDisplay/FileDisplay.tsx +29 -659
  377. package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
  378. package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
  379. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
  380. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
  381. package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
  382. package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
  383. package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
  384. package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
  385. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
  386. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
  387. package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
  388. package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
  389. package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
  390. package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
  391. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
  392. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
  393. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
  394. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
  395. package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
  396. package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
  397. package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
  398. package/src/components/FileDisplay/fallbackUtils.ts +44 -0
  399. package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
  400. package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
  401. package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
  402. package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
  403. package/src/components/FileDisplay/index.tsx +1 -1
  404. package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
  405. package/src/components/FileDisplay/useFileDisplay.ts +515 -0
  406. package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1438 -0
  407. package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
  408. package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
  409. package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
  410. package/src/components/FileUpload/FileUpload.test.tsx +69 -27
  411. package/src/components/FileUpload/FileUpload.tsx +112 -527
  412. package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
  413. package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
  414. package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
  415. package/src/components/FileUpload/index.tsx +1 -1
  416. package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
  417. package/src/components/FileUpload/useFileUploadManager.ts +454 -0
  418. package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
  419. package/src/components/FileUpload/useResolvedAppId.ts +77 -0
  420. package/src/components/Footer/Footer.test.tsx +15 -382
  421. package/src/components/Footer/Footer.tsx +8 -125
  422. package/src/components/Form/Form.test.tsx +425 -88
  423. package/src/components/Form/Form.tsx +91 -299
  424. package/src/components/Form/useFormPersistence.ts +257 -0
  425. package/src/components/Header/Header.test.tsx +653 -163
  426. package/src/components/Header/Header.tsx +62 -44
  427. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  428. package/src/components/Input/Input.test.tsx +34 -120
  429. package/src/components/Input/Input.tsx +1 -1
  430. package/src/components/Label/Label.test.tsx +46 -45
  431. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +8 -11
  432. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  433. package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
  434. package/src/components/NavigationMenu/NavigationMenu.test.tsx +2422 -102
  435. package/src/components/NavigationMenu/NavigationMenu.tsx +62 -362
  436. package/src/components/NavigationMenu/index.ts +6 -1
  437. package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
  438. package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
  439. package/src/components/NavigationMenu/useNavigationFiltering.ts +199 -308
  440. package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
  441. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1322 -0
  442. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +50 -49
  443. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  444. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +103 -85
  445. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +774 -44
  446. package/src/components/PaceAppLayout/PaceAppLayout.tsx +282 -764
  447. package/src/components/PaceAppLayout/README.md +0 -9
  448. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  449. package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
  450. package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
  451. package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
  452. package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
  453. package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
  454. package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
  455. package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
  456. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +782 -20
  457. package/src/components/PaceLoginPage/PaceLoginPage.tsx +33 -125
  458. package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
  459. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  460. package/src/components/Progress/Progress.test.tsx +127 -1
  461. package/src/components/Progress/Progress.tsx +1 -2
  462. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  463. package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -217
  464. package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
  465. package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
  466. package/src/components/PublicLayout/PublicLayout.test.tsx +1640 -38
  467. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  468. package/src/components/PublicLayout/PublicPageLayout.tsx +134 -75
  469. package/src/components/PublicLayout/PublicPageProvider.tsx +7 -42
  470. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  471. package/src/components/Select/Select.test.tsx +45 -8
  472. package/src/components/Select/Select.tsx +57 -40
  473. package/src/components/Select/context.test.tsx +56 -0
  474. package/src/components/Select/text.test.tsx +104 -0
  475. package/src/components/Select/text.ts +26 -0
  476. package/src/components/Select/types.ts +3 -0
  477. package/src/components/Select/useSelectEvents.test.ts +279 -0
  478. package/src/components/Select/useSelectEvents.ts +87 -0
  479. package/src/components/Select/useSelectSearch.test.tsx +295 -0
  480. package/src/components/Select/useSelectSearch.ts +91 -0
  481. package/src/components/Select/useSelectState.test.ts +268 -0
  482. package/src/components/Select/useSelectState.ts +104 -0
  483. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  484. package/src/components/Switch/Switch.test.tsx +57 -153
  485. package/src/components/Table/Table.test.tsx +395 -317
  486. package/src/components/Tabs/Tabs.test.tsx +270 -0
  487. package/src/components/Tabs/Tabs.tsx +4 -4
  488. package/src/components/Textarea/Textarea.test.tsx +11 -38
  489. package/src/components/Toast/Toast.test.tsx +425 -496
  490. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  491. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  492. package/src/components/UserMenu/UserMenu.tsx +0 -1
  493. package/src/components/index.test.ts +346 -0
  494. package/src/components/index.ts +12 -1
  495. package/src/constants/performance.test.ts +91 -0
  496. package/src/hooks/ServiceHooks.test.tsx +725 -0
  497. package/src/hooks/hooks.integration.test.tsx +608 -0
  498. package/src/hooks/index.ts +18 -3
  499. package/src/hooks/index.unit.test.ts +220 -0
  500. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  501. package/src/hooks/public/usePublicEvent.ts +11 -11
  502. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  503. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  504. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  505. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  506. package/src/hooks/services/useAuth.ts +9 -7
  507. package/src/hooks/services/useAuthService.ts +1 -1
  508. package/src/hooks/services/useEventService.ts +1 -1
  509. package/src/hooks/useAccessibleApps.test.ts +400 -0
  510. package/src/hooks/useAccessibleApps.ts +264 -0
  511. package/src/hooks/useAddressAutocomplete.test.ts +170 -47
  512. package/src/hooks/useAddressAutocomplete.ts +109 -81
  513. package/src/hooks/useApiFetch.unit.test.ts +111 -0
  514. package/src/hooks/useAppConfig.ts +13 -3
  515. package/src/hooks/useAppConfig.unit.test.ts +712 -0
  516. package/src/hooks/useComponentPerformance.unit.test.tsx +314 -0
  517. package/src/hooks/useDataTablePerformance.ts +111 -130
  518. package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
  519. package/src/hooks/useDataTableState.test.ts +170 -0
  520. package/src/hooks/useDataTableState.ts +5 -5
  521. package/src/hooks/useDebounce.unit.test.ts +157 -0
  522. package/src/hooks/useEventTheme.test.ts +70 -18
  523. package/src/hooks/useEventTheme.ts +50 -22
  524. package/src/hooks/useEvents.ts +49 -2
  525. package/src/hooks/useEvents.unit.test.ts +227 -0
  526. package/src/hooks/useFileReference.test.ts +388 -107
  527. package/src/hooks/useFileReference.ts +184 -179
  528. package/src/hooks/useFileUrl.ts +1 -1
  529. package/src/hooks/useFileUrl.unit.test.ts +686 -0
  530. package/src/hooks/useFileUrlCache.test.ts +319 -0
  531. package/src/hooks/useFileUrlCache.ts +5 -2
  532. package/src/hooks/useFocusManagement.unit.test.ts +604 -0
  533. package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
  534. package/src/hooks/useFormDialog.test.ts +307 -0
  535. package/src/hooks/useFormDialog.ts +2 -2
  536. package/src/hooks/useInactivityTracker.ts +141 -134
  537. package/src/hooks/useInactivityTracker.unit.test.ts +446 -0
  538. package/src/hooks/useIsMobile.unit.test.ts +317 -0
  539. package/src/hooks/useIsPrint.ts +62 -0
  540. package/src/hooks/useIsPrint.unit.test.ts +545 -0
  541. package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
  542. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  543. package/src/hooks/useOrganisationPermissions.ts +1 -4
  544. package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
  545. package/src/hooks/useOrganisationSecurity.test.ts +4 -33
  546. package/src/hooks/useOrganisationSecurity.ts +192 -203
  547. package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
  548. package/src/hooks/useOrganisations.ts +1 -1
  549. package/src/hooks/useOrganisations.unit.test.ts +369 -0
  550. package/src/hooks/usePerformanceMonitor.ts +1 -1
  551. package/src/hooks/usePerformanceMonitor.unit.test.ts +693 -0
  552. package/src/hooks/usePermissionCache.test.ts +298 -329
  553. package/src/hooks/usePermissionCache.ts +277 -276
  554. package/src/hooks/usePreventTabReload.test.ts +307 -0
  555. package/src/hooks/usePublicEvent.simple.test.ts +794 -0
  556. package/src/hooks/usePublicEvent.test.ts +670 -0
  557. package/src/hooks/usePublicEvent.unit.test.ts +638 -0
  558. package/src/hooks/usePublicFileDisplay.test.ts +948 -0
  559. package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
  560. package/src/hooks/useQueryCache.test.ts +391 -0
  561. package/src/hooks/useQueryCache.ts +7 -9
  562. package/src/hooks/useRBAC.unit.test.ts +253 -0
  563. package/src/hooks/useSessionDraft.test.ts +556 -0
  564. package/src/hooks/useSessionDraft.ts +14 -11
  565. package/src/hooks/useSessionRestoration.ts +1 -1
  566. package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
  567. package/src/hooks/useStorage.ts +94 -54
  568. package/src/hooks/useStorage.unit.test.ts +684 -0
  569. package/src/hooks/useToast.test.ts +413 -0
  570. package/src/hooks/useToast.ts +2 -2
  571. package/src/hooks/useToast.unit.test.tsx +481 -0
  572. package/src/hooks/useZodForm.ts +3 -3
  573. package/src/hooks/useZodForm.unit.test.tsx +191 -0
  574. package/src/icons/index.test.ts +133 -0
  575. package/src/icons/index.ts +3 -1
  576. package/src/index.test.ts +528 -0
  577. package/src/index.ts +56 -9
  578. package/src/providers/AuthProvider.test.tsx +218 -0
  579. package/src/providers/EventProvider.test.tsx +487 -0
  580. package/src/providers/InactivityProvider.test-helper.tsx +40 -0
  581. package/src/providers/InactivityProvider.test.tsx +421 -0
  582. package/src/providers/ProviderLifecycle.test.tsx +308 -0
  583. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  584. package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
  585. package/src/providers/index.test.ts +138 -0
  586. package/src/providers/services/AuthServiceContext.ts +27 -0
  587. package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
  588. package/src/providers/services/AuthServiceProvider.test.tsx +638 -0
  589. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  590. package/src/providers/services/EventServiceContext.ts +25 -0
  591. package/src/providers/services/EventServiceProvider.test.tsx +839 -0
  592. package/src/providers/services/EventServiceProvider.tsx +11 -20
  593. package/src/providers/services/InactivityServiceContext.ts +25 -0
  594. package/src/providers/services/InactivityServiceProvider.test.tsx +662 -0
  595. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  596. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  597. package/src/providers/services/OrganisationServiceProvider.test.tsx +440 -0
  598. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  599. package/src/providers/services/UnifiedAuthContext.ts +102 -0
  600. package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
  601. package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
  602. package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
  603. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  604. package/src/providers/services/UnifiedAuthProvider.tsx +147 -497
  605. package/src/providers/services/contexts.test.tsx +281 -0
  606. package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
  607. package/src/providers/services/useUnifiedAuth.ts +29 -0
  608. package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
  609. package/src/providers/useInactivity.test-helper.ts +27 -0
  610. package/src/rbac/README.md +5 -5
  611. package/src/rbac/adapters.comprehensive.test.tsx +429 -0
  612. package/src/rbac/adapters.test.tsx +654 -0
  613. package/src/rbac/adapters.tsx +53 -38
  614. package/src/rbac/api.test.ts +986 -259
  615. package/src/rbac/api.ts +260 -216
  616. package/src/rbac/audit-batched.test.ts +550 -0
  617. package/src/rbac/audit-batched.ts +5 -4
  618. package/src/rbac/audit.test.ts +225 -28
  619. package/src/rbac/audit.ts +26 -18
  620. package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
  621. package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
  622. package/src/rbac/cache-invalidation.test.ts +715 -0
  623. package/src/rbac/cache-invalidation.ts +18 -15
  624. package/src/rbac/cache.test.ts +123 -63
  625. package/src/rbac/cache.ts +3 -4
  626. package/src/rbac/components/AccessDenied.test.tsx +324 -0
  627. package/src/rbac/components/AccessDenied.tsx +20 -18
  628. package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
  629. package/src/rbac/components/NavigationGuard.tsx +10 -8
  630. package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
  631. package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
  632. package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
  633. package/src/rbac/components/PagePermissionGuard.test.tsx +1430 -0
  634. package/src/rbac/components/PagePermissionGuard.tsx +188 -381
  635. package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
  636. package/src/rbac/config.test.ts +131 -48
  637. package/src/rbac/config.ts +69 -26
  638. package/src/rbac/docs/event-based-apps.md +26 -13
  639. package/src/rbac/engine.comprehensive.test.ts +808 -0
  640. package/src/rbac/engine.test.ts +974 -130
  641. package/src/rbac/engine.ts +53 -13
  642. package/src/rbac/errors.test.ts +99 -87
  643. package/src/rbac/errors.ts +89 -55
  644. package/src/rbac/eslint-rules.js +2 -2
  645. package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
  646. package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
  647. package/src/rbac/hooks/permissions/useAccessLevel.ts +23 -14
  648. package/src/rbac/hooks/permissions/useCan.test.ts +798 -0
  649. package/src/rbac/hooks/permissions/useCan.ts +173 -253
  650. package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
  651. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +63 -10
  652. package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
  653. package/src/rbac/hooks/permissions/usePermissions.ts +50 -78
  654. package/src/rbac/hooks/useCan.test.ts +348 -32
  655. package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
  656. package/src/rbac/hooks/usePageGuardScope.ts +117 -0
  657. package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
  658. package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
  659. package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
  660. package/src/rbac/hooks/usePermissions.test.ts +459 -33
  661. package/src/rbac/hooks/usePermissions.ts +5 -7
  662. package/src/rbac/hooks/useRBAC.test.ts +1784 -21
  663. package/src/rbac/hooks/useRBAC.ts +148 -88
  664. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  665. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  666. package/src/rbac/hooks/useResourcePermissions.test.ts +561 -24
  667. package/src/rbac/hooks/useResourcePermissions.ts +76 -140
  668. package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
  669. package/src/rbac/hooks/useRoleManagement.test.ts +634 -61
  670. package/src/rbac/hooks/useRoleManagement.ts +158 -586
  671. package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
  672. package/src/rbac/hooks/useSecureSupabase.ts +21 -14
  673. package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
  674. package/src/rbac/index.test.ts +107 -0
  675. package/src/rbac/index.ts +32 -32
  676. package/src/rbac/performance.test.ts +451 -0
  677. package/src/rbac/permissions.test.ts +149 -68
  678. package/src/rbac/permissions.ts +0 -3
  679. package/src/rbac/rbac-core.test.tsx +276 -0
  680. package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
  681. package/src/rbac/rbac-engine-simplified.test.ts +252 -0
  682. package/src/rbac/rbac-functions.test.ts +703 -0
  683. package/src/rbac/rbac-integration.test.ts +523 -0
  684. package/src/rbac/rbac-role-isolation.test.ts +456 -0
  685. package/src/rbac/request-deduplication.test.ts +352 -0
  686. package/src/rbac/request-deduplication.ts +5 -4
  687. package/src/rbac/scenarios.user-role.test.tsx +271 -0
  688. package/src/rbac/secureClient.test.ts +499 -115
  689. package/src/rbac/secureClient.ts +54 -28
  690. package/src/rbac/security.test.ts +448 -44
  691. package/src/rbac/security.ts +7 -6
  692. package/src/rbac/types/roleManagement.ts +66 -0
  693. package/src/rbac/types.test.ts +236 -0
  694. package/src/rbac/types.ts +7 -5
  695. package/src/rbac/utils/clientSecurity.test.ts +192 -0
  696. package/src/rbac/utils/clientSecurity.ts +6 -4
  697. package/src/rbac/utils/contextValidator.test.ts +126 -0
  698. package/src/rbac/utils/contextValidator.ts +6 -3
  699. package/src/rbac/utils/deep-equal.test.ts +76 -0
  700. package/src/rbac/utils/eventContext.test.ts +401 -0
  701. package/src/rbac/utils/eventContext.ts +38 -34
  702. package/src/rbac/utils/fetchPermissionMap.ts +13 -0
  703. package/src/rbac/utils/permissionMapHelpers.ts +34 -0
  704. package/src/rbac/utils/roleManagementRpc.ts +303 -0
  705. package/src/services/AuthService.edge-cases.test.ts +746 -0
  706. package/src/services/AuthService.restoreSession.test.ts +59 -0
  707. package/src/services/AuthService.test.ts +1362 -0
  708. package/src/services/AuthService.ts +197 -216
  709. package/src/services/BaseService.edge-cases.test.ts +506 -0
  710. package/src/services/BaseService.test.ts +363 -0
  711. package/src/services/EventService.edge-cases.test.ts +636 -0
  712. package/src/services/EventService.eventColours.test.ts +64 -0
  713. package/src/services/EventService.test.ts +1250 -0
  714. package/src/services/EventService.ts +244 -315
  715. package/src/services/InactivityService.edge-cases.test.ts +492 -0
  716. package/src/services/InactivityService.lifecycle.test.ts +406 -0
  717. package/src/services/InactivityService.test.ts +829 -0
  718. package/src/services/InactivityService.ts +172 -213
  719. package/src/services/OrganisationService.edge-cases.test.ts +633 -0
  720. package/src/services/OrganisationService.pagination.test.ts +409 -0
  721. package/src/services/OrganisationService.test.ts +1579 -0
  722. package/src/services/OrganisationService.ts +186 -257
  723. package/src/services/base/BaseService.test.ts +214 -0
  724. package/src/services/interfaces/IAuthService.test.ts +184 -0
  725. package/src/services/interfaces/IAuthService.ts +10 -9
  726. package/src/services/interfaces/IEventService.test.ts +176 -0
  727. package/src/services/interfaces/IInactivityService.test.ts +183 -0
  728. package/src/services/interfaces/IOrganisationService.test.ts +207 -0
  729. package/src/services/interfaces/IOrganisationService.ts +0 -1
  730. package/src/styles/core.css +244 -12
  731. package/src/theming/parseEventColours.test.ts +321 -0
  732. package/src/theming/parseEventColours.ts +18 -9
  733. package/src/theming/runtime.test.ts +495 -0
  734. package/src/theming/runtime.ts +72 -7
  735. package/src/types/api-result.ts +53 -0
  736. package/src/types/auth.ts +0 -1
  737. package/src/types/core.test.ts +397 -0
  738. package/src/types/database-generated.test.ts +78 -0
  739. package/src/types/database.generated.ts +45 -10
  740. package/src/types/event.ts +39 -19
  741. package/src/types/file-reference.test.ts +351 -0
  742. package/src/types/file-reference.ts +37 -12
  743. package/src/types/guards.test.ts +246 -0
  744. package/src/types/index.test.ts +265 -0
  745. package/src/types/index.ts +3 -0
  746. package/src/types/organisation.roles.test.ts +55 -0
  747. package/src/types/organisation.test.ts +1105 -0
  748. package/src/types/organisation.ts +15 -15
  749. package/src/types/rpc-responses.ts +33 -0
  750. package/src/types/supabase.ts +14 -6
  751. package/src/types/theme.test.ts +830 -0
  752. package/src/types/type-validation.test.ts +526 -0
  753. package/src/types/validation.test.ts +729 -0
  754. package/src/types/vitest-globals.d.ts +1 -1
  755. package/src/utils/app/appConfig.test.ts +235 -0
  756. package/src/utils/app/appIdResolver.test.ts +252 -57
  757. package/src/utils/app/appIdResolver.ts +31 -20
  758. package/src/utils/app/appNameResolver.test.ts +18 -10
  759. package/src/utils/app/appNameResolver.ts +11 -9
  760. package/src/utils/app/appPortMap.test.ts +125 -0
  761. package/src/utils/app/appPortMap.ts +51 -0
  762. package/src/utils/app/buildAppUrl.test.ts +273 -0
  763. package/src/utils/app/buildAppUrl.ts +114 -0
  764. package/src/utils/appConfig.unit.test.ts +55 -0
  765. package/src/utils/audit/audit.test.ts +354 -39
  766. package/src/utils/audit.unit.test.ts +69 -0
  767. package/src/utils/auth-utils.unit.test.ts +69 -0
  768. package/src/utils/bundleAnalysis.unit.test.ts +326 -0
  769. package/src/utils/cn.unit.test.ts +34 -0
  770. package/src/utils/context/organisationContext.test.ts +115 -95
  771. package/src/utils/context/organisationContext.ts +32 -43
  772. package/src/utils/context/sessionTracking.test.ts +354 -0
  773. package/src/utils/core/cn.test.ts +66 -0
  774. package/src/utils/core/debugLogger.test.ts +113 -0
  775. package/src/utils/core/debugLogger.ts +15 -8
  776. package/src/utils/core/logger.test.ts +217 -0
  777. package/src/utils/core/logger.ts +20 -16
  778. package/src/utils/core/mergeRefs.ts +24 -0
  779. package/src/utils/debugLogger.test.ts +417 -0
  780. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  781. package/src/utils/device/deviceFingerprint.ts +3 -3
  782. package/src/utils/deviceFingerprint.unit.test.ts +818 -0
  783. package/src/utils/dynamic/createLazyComponent.tsx +46 -0
  784. package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
  785. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  786. package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
  787. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  788. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  789. package/src/utils/dynamicUtils.unit.test.ts +331 -0
  790. package/src/utils/file-reference/file-reference.test.ts +1238 -0
  791. package/src/utils/file-reference/index.ts +330 -348
  792. package/src/utils/formatDate.unit.test.ts +109 -0
  793. package/src/utils/formatting/formatDate.test.ts +22 -148
  794. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  795. package/src/utils/formatting/formatDateTimeTimezone.test.ts +41 -85
  796. package/src/utils/formatting/formatNumber.test.ts +259 -0
  797. package/src/utils/formatting/formatTime.test.ts +36 -128
  798. package/src/utils/formatting/formatting.ts +1 -1
  799. package/src/utils/formatting.unit.test.ts +99 -0
  800. package/src/utils/google-places/googlePlacesUtils.test.ts +127 -36
  801. package/src/utils/google-places/googlePlacesUtils.ts +67 -86
  802. package/src/utils/google-places/loadGoogleMapsScript.test.ts +68 -8
  803. package/src/utils/google-places/loadGoogleMapsScript.ts +140 -118
  804. package/src/utils/index.ts +52 -11
  805. package/src/utils/index.unit.test.ts +251 -0
  806. package/src/utils/lazyLoad.unit.test.tsx +319 -0
  807. package/src/utils/location/location.test.ts +19 -116
  808. package/src/utils/logger.unit.test.ts +398 -0
  809. package/src/utils/organisationContext.unit.test.ts +180 -0
  810. package/src/utils/performance/bundleAnalysis.test.ts +148 -0
  811. package/src/utils/performance/bundleAnalysis.ts +16 -22
  812. package/src/utils/performance/performanceBenchmark.test.ts +251 -0
  813. package/src/utils/performance/performanceBenchmark.ts +12 -4
  814. package/src/utils/performance/performanceBudgets.test.ts +241 -0
  815. package/src/utils/performance/performanceBudgets.ts +9 -6
  816. package/src/utils/performanceBenchmark.test.ts +174 -0
  817. package/src/utils/performanceBudgets.unit.test.ts +288 -0
  818. package/src/utils/permissionTypes.unit.test.ts +250 -0
  819. package/src/utils/permissionUtils.unit.test.ts +362 -0
  820. package/src/utils/permissions/permissionTypes.test.ts +149 -0
  821. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  822. package/src/utils/persistence/keyDerivation.test.ts +306 -0
  823. package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
  824. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  825. package/src/utils/request-deduplication.test.ts +349 -0
  826. package/src/utils/request-deduplication.ts +6 -4
  827. package/src/utils/sanitization.unit.test.ts +346 -0
  828. package/src/utils/schemaUtils.unit.test.ts +441 -0
  829. package/src/utils/secureDataAccess.unit.test.ts +334 -0
  830. package/src/utils/secureErrors.unit.test.ts +390 -0
  831. package/src/utils/secureStorage.unit.test.ts +289 -0
  832. package/src/utils/security/auth-utils.ts +38 -27
  833. package/src/utils/security/secureDataAccess.test.ts +22 -191
  834. package/src/utils/security/secureDataAccess.ts +241 -281
  835. package/src/utils/security/secureErrors.test.ts +163 -0
  836. package/src/utils/security/secureStorage.test.ts +156 -0
  837. package/src/utils/security/secureStorage.ts +1 -1
  838. package/src/utils/security/security.test.ts +212 -0
  839. package/src/utils/security/security.ts +15 -18
  840. package/src/utils/security/securityMonitor.test.ts +90 -0
  841. package/src/utils/security/securityMonitor.ts +1 -1
  842. package/src/utils/security.unit.test.ts +155 -0
  843. package/src/utils/securityMonitor.unit.test.ts +276 -0
  844. package/src/utils/sessionTracking.unit.test.ts +218 -0
  845. package/src/utils/storage/config.unit.test.ts +239 -0
  846. package/src/utils/storage/helpers.test.ts +769 -456
  847. package/src/utils/storage/helpers.ts +174 -253
  848. package/src/utils/storage/index.unit.test.ts +68 -0
  849. package/src/utils/storage/storageUtils.ts +32 -0
  850. package/src/utils/storage/types.ts +9 -2
  851. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  852. package/src/utils/supabase/createBaseClient.ts +2 -1
  853. package/src/utils/timezone/timezone.test.ts +26 -44
  854. package/src/utils/timezone.test.ts +345 -0
  855. package/src/utils/validation/common.test.ts +115 -0
  856. package/src/utils/validation/csrf.test.ts +198 -0
  857. package/src/utils/validation/csrf.ts +42 -41
  858. package/src/utils/validation/htmlSanitization.ts +27 -31
  859. package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
  860. package/src/utils/validation/passwordSchema.test.ts +164 -0
  861. package/src/utils/validation/schema.test.ts +127 -0
  862. package/src/utils/validation/schema.ts +6 -3
  863. package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
  864. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  865. package/src/utils/validation/user.test.ts +173 -0
  866. package/src/utils/validation/validation.test.ts +197 -0
  867. package/src/utils/validation/validationUtils.test.ts +294 -0
  868. package/src/utils/validation.unit.test.ts +307 -0
  869. package/src/utils/validationUtils.unit.test.ts +558 -0
  870. package/src/vite-env.d.ts +6 -0
  871. package/dist/AuthService-DmfO5rGS.d.ts +0 -524
  872. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  873. package/dist/DataTable-SOAFXIWY.js +0 -15
  874. package/dist/PublicPageProvider-CIGSujI2.d.ts +0 -4147
  875. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  876. package/dist/UnifiedAuthProvider-CKvHP1MK.d.ts +0 -139
  877. package/dist/api-7P7DI652.js +0 -4
  878. package/dist/audit-MYQXYZFU.js +0 -3
  879. package/dist/auth-BZOJqrdd.d.ts +0 -49
  880. package/dist/chunk-4DDCYDQ3.js +0 -544
  881. package/dist/chunk-5HNSDQWH.js +0 -5046
  882. package/dist/chunk-5W2A3DRC.js +0 -164
  883. package/dist/chunk-6GLLNA6U.js +0 -31
  884. package/dist/chunk-7ILTDCL2.js +0 -80
  885. package/dist/chunk-A3W6LW53.js +0 -70
  886. package/dist/chunk-AHU7G2R5.js +0 -423
  887. package/dist/chunk-C7ZQ5O4C.js +0 -481
  888. package/dist/chunk-EF2UGZWY.js +0 -611
  889. package/dist/chunk-FEJLJNWA.js +0 -181
  890. package/dist/chunk-FYHN4DD5.js +0 -415
  891. package/dist/chunk-GS5672WG.js +0 -2003
  892. package/dist/chunk-HF6O3O37.js +0 -187
  893. package/dist/chunk-J2U36LHD.js +0 -8517
  894. package/dist/chunk-LX6U42O3.js +0 -2177
  895. package/dist/chunk-MPBLMWVR.js +0 -2161
  896. package/dist/chunk-OJ4SKRSV.js +0 -105
  897. package/dist/chunk-S6ZQKDY6.js +0 -62
  898. package/dist/chunk-S7DKJPLT.js +0 -699
  899. package/dist/chunk-T5CVK4R3.js +0 -2816
  900. package/dist/chunk-TTRFSOKR.js +0 -121
  901. package/dist/chunk-Z2FNRKF3.js +0 -994
  902. package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
  903. package/dist/event-CW5YB_2p.d.ts +0 -239
  904. package/dist/file-reference-BavO2eQj.d.ts +0 -148
  905. package/dist/functions-lBy5L2ry.d.ts +0 -208
  906. package/dist/timezone-0AyangqX.d.ts +0 -697
  907. package/dist/types-BeoeWV5I.d.ts +0 -110
  908. package/dist/types-DXstZpNI.d.ts +0 -614
  909. package/dist/types-t9H8qKRw.d.ts +0 -55
  910. package/dist/usePublicRouteParams-DQLrDqDb.d.ts +0 -876
  911. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  912. package/dist/validation-643vUDZW.d.ts +0 -177
  913. package/scripts/build-docs-incremental.js +0 -179
  914. package/scripts/eslint-audit.cjs +0 -123
  915. package/scripts/generate-docs.js +0 -157
  916. package/scripts/install-cursor-rules.cjs +0 -255
  917. package/scripts/install-eslint-config.cjs +0 -349
  918. package/scripts/setup-build-cache.js +0 -73
  919. package/scripts/validate-pre-publish.js +0 -145
  920. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
  921. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
  922. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
  923. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
  924. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -448
  925. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
  926. package/src/__tests__/hooks/usePermissions.test.ts +0 -268
  927. package/src/__tests__/integration/UserProfile.test.tsx +0 -124
  928. package/src/__tests__/public-recipe-view.test.ts +0 -228
  929. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -220
  930. package/src/__tests__/rls-policies.test.ts +0 -471
  931. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
  932. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
  933. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
  934. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
  935. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
  936. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -483
  937. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
  938. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
  939. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -1474
  940. package/src/components/DataTable/__tests__/README.md +0 -145
  941. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
  942. package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
  943. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
  944. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -730
  945. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -325
  946. package/src/components/DataTable/__tests__/styles.test.ts +0 -382
  947. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
  948. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -380
  949. package/src/components/DataTable/__tests__/test-utils.ts +0 -94
  950. package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
  951. package/src/components/DataTable/components/ActionButtons.tsx +0 -190
  952. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
  953. package/src/components/DataTable/components/ColumnFilter.tsx +0 -118
  954. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
  955. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
  956. package/src/components/DataTable/components/DataTableLayout.tsx +0 -573
  957. package/src/components/DataTable/components/DataTableModals.tsx +0 -245
  958. package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
  959. package/src/components/DataTable/components/EditFields.tsx +0 -327
  960. package/src/components/DataTable/components/EditableRow.tsx +0 -462
  961. package/src/components/DataTable/components/EmptyState.tsx +0 -79
  962. package/src/components/DataTable/components/FilterRow.tsx +0 -141
  963. package/src/components/DataTable/components/LoadingState.tsx +0 -17
  964. package/src/components/DataTable/components/PaginationControls.tsx +0 -289
  965. package/src/components/DataTable/components/RowComponent.tsx +0 -403
  966. package/src/components/DataTable/components/SortIndicator.tsx +0 -50
  967. package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -355
  968. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -657
  969. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -913
  970. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -572
  971. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -612
  972. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -708
  973. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -479
  974. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -475
  975. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -157
  976. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -1061
  977. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -437
  978. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -474
  979. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -617
  980. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -1093
  981. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -139
  982. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -519
  983. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -1004
  984. package/src/components/DataTable/components/cellValueUtils.ts +0 -40
  985. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
  986. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
  987. package/src/components/DataTable/components/index.ts +0 -16
  988. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -342
  989. package/src/components/DataTable/core/ActionManager.ts +0 -235
  990. package/src/components/DataTable/core/ColumnManager.ts +0 -205
  991. package/src/components/DataTable/core/DataManager.ts +0 -188
  992. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
  993. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  994. package/src/components/DataTable/core/StateManager.ts +0 -312
  995. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -123
  996. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -305
  997. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -84
  998. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -115
  999. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -100
  1000. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -120
  1001. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -104
  1002. package/src/components/DataTable/core/index.ts +0 -1
  1003. package/src/components/DataTable/core/interfaces.ts +0 -338
  1004. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -521
  1005. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -167
  1006. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -124
  1007. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -117
  1008. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -102
  1009. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -596
  1010. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -53
  1011. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -214
  1012. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -448
  1013. package/src/components/DataTable/hooks/index.ts +0 -13
  1014. package/src/components/DataTable/types.ts +0 -761
  1015. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -612
  1016. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
  1017. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -266
  1018. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
  1019. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
  1020. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -247
  1021. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -570
  1022. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
  1023. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -251
  1024. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -207
  1025. package/src/components/DataTable/utils/index.ts +0 -10
  1026. package/src/components/PublicLayout/index.ts +0 -32
  1027. package/src/components/Select/hooks/useSelectEvents.ts +0 -87
  1028. package/src/components/Select/hooks/useSelectSearch.ts +0 -91
  1029. package/src/components/Select/hooks/useSelectState.ts +0 -104
  1030. package/src/components/Select/utils/text.ts +0 -26
  1031. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -615
  1032. package/src/hooks/__tests__/hooks.integration.test.tsx +0 -607
  1033. package/src/hooks/__tests__/index.unit.test.ts +0 -220
  1034. package/src/hooks/__tests__/useApiFetch.unit.test.ts +0 -111
  1035. package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -347
  1036. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -144
  1037. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -776
  1038. package/src/hooks/__tests__/useDataTableState.test.ts +0 -76
  1039. package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -82
  1040. package/src/hooks/__tests__/useEvents.unit.test.ts +0 -252
  1041. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1112
  1042. package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -916
  1043. package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -129
  1044. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -230
  1045. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -828
  1046. package/src/hooks/__tests__/useFormDialog.test.ts +0 -478
  1047. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
  1048. package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
  1049. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -910
  1050. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -294
  1051. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
  1052. package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
  1053. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
  1054. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  1055. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  1056. package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -88
  1057. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -785
  1058. package/src/hooks/__tests__/usePublicEvent.test.ts +0 -678
  1059. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -630
  1060. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -951
  1061. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -443
  1062. package/src/hooks/__tests__/useQueryCache.test.ts +0 -144
  1063. package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
  1064. package/src/hooks/__tests__/useSessionDraft.test.ts +0 -163
  1065. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
  1066. package/src/hooks/__tests__/useStorage.unit.test.ts +0 -751
  1067. package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
  1068. package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -37
  1069. package/src/hooks/public/index.ts +0 -36
  1070. package/src/hooks/public/usePublicFileDisplay.ts +0 -504
  1071. package/src/hooks/useFileDisplay.ts +0 -715
  1072. package/src/providers/OrganisationProvider.tsx +0 -92
  1073. package/src/providers/__tests__/AuthProvider.test.tsx +0 -287
  1074. package/src/providers/__tests__/EventProvider.test.tsx +0 -551
  1075. package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
  1076. package/src/providers/__tests__/InactivityProvider.test.tsx +0 -572
  1077. package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -617
  1078. package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -424
  1079. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -596
  1080. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -263
  1081. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -294
  1082. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -434
  1083. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -313
  1084. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -486
  1085. package/src/rbac/__tests__/cache-invalidation.test.ts +0 -399
  1086. package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -813
  1087. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  1088. package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
  1089. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -392
  1090. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -258
  1091. package/src/rbac/__tests__/rbac-functions.test.ts +0 -647
  1092. package/src/rbac/__tests__/rbac-integration.test.ts +0 -524
  1093. package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
  1094. package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -282
  1095. package/src/rbac/audit-enhanced.ts +0 -384
  1096. package/src/rbac/compliance/database-validator.ts +0 -165
  1097. package/src/rbac/compliance/index.ts +0 -48
  1098. package/src/rbac/compliance/pattern-detector.ts +0 -553
  1099. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  1100. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  1101. package/src/rbac/compliance/setup-validator.ts +0 -131
  1102. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -975
  1103. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -248
  1104. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -242
  1105. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1107
  1106. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -184
  1107. package/src/rbac/components/index.ts +0 -26
  1108. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -432
  1109. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -579
  1110. package/src/rbac/hooks/index.ts +0 -34
  1111. package/src/rbac/hooks/permissions/index.ts +0 -4
  1112. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  1113. package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -128
  1114. package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -53
  1115. package/src/rbac/utils/__tests__/eventContext.test.ts +0 -433
  1116. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  1117. package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -39
  1118. package/src/services/__tests__/AuthService.test.ts +0 -1332
  1119. package/src/services/__tests__/BaseService.test.ts +0 -314
  1120. package/src/services/__tests__/EventService.eventColours.test.ts +0 -76
  1121. package/src/services/__tests__/EventService.test.ts +0 -1025
  1122. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -411
  1123. package/src/services/__tests__/InactivityService.test.ts +0 -654
  1124. package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
  1125. package/src/services/__tests__/OrganisationService.test.ts +0 -1176
  1126. package/src/theming/__tests__/parseEventColours.test.ts +0 -321
  1127. package/src/theming/__tests__/runtime.test.ts +0 -569
  1128. package/src/types/__tests__/file-reference.test.ts +0 -447
  1129. package/src/types/__tests__/guards.test.ts +0 -246
  1130. package/src/types/__tests__/organisation.roles.test.ts +0 -55
  1131. package/src/types/__tests__/organisation.test.ts +0 -1133
  1132. package/src/types/__tests__/theme.test.ts +0 -830
  1133. package/src/types/__tests__/type-validation.test.ts +0 -526
  1134. package/src/types/__tests__/validation.test.ts +0 -731
  1135. package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
  1136. package/src/utils/__tests__/audit.unit.test.ts +0 -69
  1137. package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
  1138. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -339
  1139. package/src/utils/__tests__/cn.unit.test.ts +0 -34
  1140. package/src/utils/__tests__/debugLogger.test.ts +0 -417
  1141. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
  1142. package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -318
  1143. package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
  1144. package/src/utils/__tests__/formatting.unit.test.ts +0 -99
  1145. package/src/utils/__tests__/index.unit.test.ts +0 -251
  1146. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -321
  1147. package/src/utils/__tests__/logger.unit.test.ts +0 -398
  1148. package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
  1149. package/src/utils/__tests__/performanceBenchmark.test.ts +0 -175
  1150. package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -253
  1151. package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
  1152. package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
  1153. package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
  1154. package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
  1155. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -335
  1156. package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
  1157. package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
  1158. package/src/utils/__tests__/security.unit.test.ts +0 -149
  1159. package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
  1160. package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
  1161. package/src/utils/__tests__/timezone.test.ts +0 -345
  1162. package/src/utils/__tests__/validation.unit.test.ts +0 -308
  1163. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
  1164. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  1165. package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -875
  1166. package/src/utils/google-places/index.ts +0 -26
  1167. package/src/utils/location/index.ts +0 -16
  1168. package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -135
  1169. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -123
  1170. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  1171. package/src/utils/storage/__tests__/index.unit.test.ts +0 -16
  1172. package/src/utils/storage/index.ts +0 -67
  1173. package/src/utils/timezone/index.ts +0 -17
  1174. package/src/utils/validation/__tests__/csrf.test.ts +0 -105
  1175. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -598
  1176. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -92
  1177. package/src/utils/validation/__tests__/validationUtils.test.ts +0 -72
  1178. package/src/utils/validation/index.ts +0 -73
  1179. /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
  1180. /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
  1181. /package/src/providers/{__tests__/README.md → README.md} +0 -0
  1182. /package/src/types/{__tests__/README.md → README.md} +0 -0
@@ -246,23 +246,6 @@ describe('RBAC API', () => {
246
246
 
247
247
  expect(mockCreateRBACEngine).toHaveBeenCalledWith(mockSupabase, undefined);
248
248
  });
249
-
250
- it('handles multiple initialization calls', () => {
251
- const mockEngine = { id: 'test-engine' };
252
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
253
- mockCreateAuditManager.mockReturnValue({} as any);
254
- mockGetRBACLogger.mockReturnValue({
255
- info: vi.fn(),
256
- warn: vi.fn(),
257
- error: vi.fn(),
258
- debug: vi.fn()
259
- });
260
-
261
- setupRBAC(mockSupabase as any);
262
- setupRBAC(mockSupabase as any);
263
-
264
- expect(mockCreateRBACEngine).toHaveBeenCalledTimes(2);
265
- });
266
249
  });
267
250
 
268
251
  describe('Environment Detection', () => {
@@ -326,7 +309,7 @@ describe('RBAC API', () => {
326
309
  });
327
310
 
328
311
  describe('Error Handling', () => {
329
- it('handles missing supabase client', () => {
312
+ it('handles missing supabase client gracefully', () => {
330
313
  const mockEngine = { id: 'test-engine' };
331
314
  const mockAuditManager = { id: 'test-audit' };
332
315
  const mockLogger = {
@@ -347,175 +330,10 @@ describe('RBAC API', () => {
347
330
  setupRBAC(null as any);
348
331
  }).not.toThrow();
349
332
  });
350
-
351
- it('handles invalid supabase client', () => {
352
- const invalidSupabase = { invalid: 'client' };
353
- const mockEngine = { id: 'test-engine' };
354
- const mockAuditManager = { id: 'test-audit' };
355
- const mockLogger = {
356
- info: vi.fn(),
357
- warn: vi.fn(),
358
- error: vi.fn(),
359
- debug: vi.fn()
360
- };
361
-
362
- // Ensure mocks don't throw
363
- mockCreateRBACConfig.mockImplementation((config) => config);
364
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
365
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
366
- mockGetRBACLogger.mockReturnValue(mockLogger);
367
-
368
- // The function doesn't throw, it just creates config with invalid client
369
- expect(() => {
370
- setupRBAC(invalidSupabase as any);
371
- }).not.toThrow();
372
- });
373
- });
374
-
375
- describe('Multiple Initialization', () => {
376
- it('handles multiple setupRBAC calls gracefully', () => {
377
- const mockEngine = { id: 'test-engine' };
378
- const mockAuditManager = { id: 'test-audit' };
379
- const mockLogger = {
380
- info: vi.fn(),
381
- warn: vi.fn(),
382
- error: vi.fn(),
383
- debug: vi.fn()
384
- };
385
-
386
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
387
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
388
- mockGetRBACLogger.mockReturnValue(mockLogger);
389
-
390
- // First call
391
- setupRBAC(mockSupabase as any);
392
-
393
- // Second call should not throw
394
- expect(() => {
395
- setupRBAC(mockSupabase as any);
396
- }).not.toThrow();
397
-
398
- expect(mockCreateRBACEngine).toHaveBeenCalledTimes(2);
399
- });
400
- });
401
-
402
- describe('Configuration Validation', () => {
403
- it('validates required supabase client', () => {
404
- const mockEngine = { id: 'test-engine' };
405
- const mockAuditManager = { id: 'test-audit' };
406
- const mockLogger = {
407
- info: vi.fn(),
408
- warn: vi.fn(),
409
- error: vi.fn(),
410
- debug: vi.fn()
411
- };
412
-
413
- // Ensure mocks don't throw
414
- mockCreateRBACConfig.mockImplementation((config) => config);
415
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
416
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
417
- mockGetRBACLogger.mockReturnValue(mockLogger);
418
-
419
- // The function doesn't throw, it just creates config with undefined
420
- expect(() => {
421
- setupRBAC(undefined as any);
422
- }).not.toThrow();
423
- });
424
-
425
- it('validates supabase client structure', () => {
426
- const invalidSupabase = {
427
- from: 'not-a-function',
428
- auth: 'not-an-object'
429
- };
430
- const mockEngine = { id: 'test-engine' };
431
- const mockAuditManager = { id: 'test-audit' };
432
- const mockLogger = {
433
- info: vi.fn(),
434
- warn: vi.fn(),
435
- error: vi.fn(),
436
- debug: vi.fn()
437
- };
438
-
439
- // Ensure mocks don't throw
440
- mockCreateRBACConfig.mockImplementation((config) => config);
441
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
442
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
443
- mockGetRBACLogger.mockReturnValue(mockLogger);
444
-
445
- // The function doesn't throw, it just creates config with invalid client
446
- expect(() => {
447
- setupRBAC(invalidSupabase as any);
448
- }).not.toThrow();
449
- });
450
- });
451
-
452
- describe('Logging Integration', () => {
453
- it('logs initialization success', () => {
454
- const mockLogger = {
455
- info: vi.fn(),
456
- warn: vi.fn(),
457
- error: vi.fn(),
458
- debug: vi.fn()
459
- };
460
-
461
- mockCreateRBACEngine.mockReturnValue({} as any);
462
- mockCreateAuditManager.mockReturnValue({} as any);
463
- mockGetRBACLogger.mockReturnValue(mockLogger);
464
-
465
- setupRBAC(mockSupabase as any);
466
-
467
- // Note: setupRBAC doesn't log "RBAC system initialized successfully" - logging is handled by the logger setup
468
- });
469
-
470
- it('logs configuration details in development', () => {
471
- const originalEnv = process.env.NODE_ENV;
472
- process.env.NODE_ENV = 'development';
473
-
474
- const mockLogger = {
475
- info: vi.fn(),
476
- warn: vi.fn(),
477
- error: vi.fn(),
478
- debug: vi.fn()
479
- };
480
-
481
- mockCreateRBACEngine.mockReturnValue({} as any);
482
- mockCreateAuditManager.mockReturnValue({} as any);
483
- mockGetRBACLogger.mockReturnValue(mockLogger);
484
-
485
- setupRBAC(mockSupabase as any, { debug: true });
486
-
487
- // The function may or may not call debug, so we just check it was called
488
- expect(mockGetRBACLogger).toHaveBeenCalled();
489
-
490
- process.env.NODE_ENV = originalEnv;
491
- });
492
333
  });
493
334
 
494
- describe('Type Safety', () => {
495
- it('accepts valid Supabase client types', () => {
496
- const validSupabase = {
497
- from: vi.fn(),
498
- auth: { getUser: vi.fn() },
499
- rpc: vi.fn()
500
- };
501
- const mockEngine = { id: 'test-engine' };
502
- const mockAuditManager = { id: 'test-audit' };
503
- const mockLogger = {
504
- info: vi.fn(),
505
- warn: vi.fn(),
506
- error: vi.fn(),
507
- debug: vi.fn()
508
- };
509
335
 
510
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
511
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
512
- mockGetRBACLogger.mockReturnValue(mockLogger);
513
336
 
514
- expect(() => {
515
- setupRBAC(validSupabase as any);
516
- }).not.toThrow();
517
- });
518
- });
519
337
 
520
338
  describe('Cache Integration', () => {
521
339
  it('initializes cache correctly', () => {
@@ -539,37 +357,6 @@ describe('RBAC API', () => {
539
357
  });
540
358
  });
541
359
 
542
- describe('Type Safety', () => {
543
- it('accepts valid Supabase client types', () => {
544
- const validSupabase = {
545
- from: vi.fn(),
546
- auth: {
547
- getUser: vi.fn()
548
- },
549
- rpc: vi.fn()
550
- };
551
-
552
- const mockEngine = { id: 'test-engine' };
553
- const mockAuditManager = { id: 'test-audit' };
554
- const mockLogger = {
555
- info: vi.fn(),
556
- warn: vi.fn(),
557
- error: vi.fn(),
558
- debug: vi.fn()
559
- };
560
-
561
- // Ensure mocks don't throw
562
- mockCreateRBACConfig.mockImplementation((config) => config);
563
- mockCreateRBACEngine.mockReturnValue(mockEngine as any);
564
- mockCreateAuditManager.mockReturnValue(mockAuditManager as any);
565
- mockGetRBACLogger.mockReturnValue(mockLogger);
566
-
567
- expect(() => {
568
- setupRBAC(validSupabase as any);
569
- }).not.toThrow();
570
- });
571
- });
572
-
573
360
  describe('Permission Functions', () => {
574
361
  let mockEngine: any;
575
362
 
@@ -599,12 +386,21 @@ describe('RBAC API', () => {
599
386
  builder.single = vi.fn().mockResolvedValue({ data: { id: 'app-123' }, error: null });
600
387
  }
601
388
  } else if (table === 'rbac_app_pages') {
602
- if (selectField === 'id') {
389
+ if (selectField === 'id' || selectField === 'id, page_name, app_id') {
603
390
  // Pattern: select('id').eq('app_id', ...).eq('page_name', ...).maybeSingle()
391
+ // or select('id, page_name, app_id').eq('app_id', ...).eq('page_name', ...).maybeSingle()
604
392
  builder.maybeSingle = vi.fn().mockResolvedValue({ data: { id: '123e4567-e89b-12d3-a456-426614174000' }, error: null });
605
- } else if (selectField === 'scope_type') {
393
+ } else if (selectField === 'scope_type' || (selectField && selectField.includes('scope_type'))) {
606
394
  // Pattern: select('scope_type').eq('id', ...).single()
607
- builder.single = vi.fn().mockResolvedValue({ data: { scope_type: 'organisation' }, error: null });
395
+ // or select('scope_type, page_name, app_id').eq('id', ...).single()
396
+ builder.single = vi.fn().mockResolvedValue({
397
+ data: {
398
+ scope_type: 'organisation',
399
+ page_name: 'test-page',
400
+ app_id: 'app-123'
401
+ },
402
+ error: null
403
+ });
608
404
  }
609
405
  }
610
406
 
@@ -617,7 +413,7 @@ describe('RBAC API', () => {
617
413
  };
618
414
 
619
415
  const mockSupabaseForEngine = {
620
- from: vi.fn((table: string) => createQueryBuilder(table)),
416
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
621
417
  rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
622
418
  auth: mockSupabase.auth
623
419
  };
@@ -656,7 +452,8 @@ describe('RBAC API', () => {
656
452
  scope: { organisationId: 'org-456' }
657
453
  });
658
454
 
659
- expect(result).toBe(mockAccessLevel);
455
+ expect(result.ok).toBe(true);
456
+ expect(result.ok && result.data).toBe(mockAccessLevel);
660
457
  expect(mockEngine.getAccessLevel).toHaveBeenCalledWith({
661
458
  userId: 'user-123',
662
459
  scope: { organisationId: 'org-456' }
@@ -669,10 +466,12 @@ describe('RBAC API', () => {
669
466
  const error = new Error('Engine error');
670
467
  mockEngine.getAccessLevel.mockRejectedValue(error);
671
468
 
672
- await expect(getAccessLevel({
469
+ const result = await getAccessLevel({
673
470
  userId: 'user-123',
674
471
  scope: { organisationId: 'org-456' }
675
- })).rejects.toThrow('Engine error');
472
+ });
473
+ expect(result.ok).toBe(false);
474
+ expect(result.ok === false && result.error.message).toContain('Engine error');
676
475
  });
677
476
  });
678
477
 
@@ -691,7 +490,8 @@ describe('RBAC API', () => {
691
490
  scope: { organisationId: 'org-456' }
692
491
  });
693
492
 
694
- expect(result).toEqual(mockPermissionMap);
493
+ expect(result.ok).toBe(true);
494
+ expect(result.ok && result.data).toEqual(mockPermissionMap);
695
495
  expect(mockEngine.getPermissionMap).toHaveBeenCalledWith({
696
496
  userId: 'user-123',
697
497
  scope: { organisationId: 'org-456' }
@@ -704,10 +504,11 @@ describe('RBAC API', () => {
704
504
  const error = new Error('Engine error');
705
505
  mockEngine.getPermissionMap.mockRejectedValue(error);
706
506
 
707
- await expect(getPermissionMap({
507
+ const result = await getPermissionMap({
708
508
  userId: 'user-123',
709
509
  scope: { organisationId: 'org-456' }
710
- })).rejects.toThrow('Engine error');
510
+ });
511
+ expect(result.ok).toBe(false);
711
512
  });
712
513
  });
713
514
 
@@ -719,7 +520,8 @@ describe('RBAC API', () => {
719
520
 
720
521
  const result = await resolveAppContext({ userId: 'user-1', appName: 'test-app' });
721
522
 
722
- expect(result).toEqual(context);
523
+ expect(result.ok).toBe(true);
524
+ expect(result.ok && result.data).toEqual(context);
723
525
  expect(mockEngine.resolveAppContext).toHaveBeenCalledWith({ userId: 'user-1', appName: 'test-app' });
724
526
  });
725
527
 
@@ -729,7 +531,8 @@ describe('RBAC API', () => {
729
531
 
730
532
  const result = await resolveAppContext({ userId: 'user-1', appName: 'test-app' });
731
533
 
732
- expect(result).toBeNull();
534
+ expect(result.ok).toBe(true);
535
+ expect(result.ok && result.data).toBeNull();
733
536
  });
734
537
  });
735
538
 
@@ -749,7 +552,8 @@ describe('RBAC API', () => {
749
552
  scope: { organisationId: 'org-456' },
750
553
  });
751
554
 
752
- expect(result).toEqual(roleContext);
555
+ expect(result.ok).toBe(true);
556
+ expect(result.ok && result.data).toEqual(roleContext);
753
557
  expect(mockEngine.getRoleContext).toHaveBeenCalledWith({
754
558
  userId: 'user-123',
755
559
  scope: { organisationId: 'org-456' },
@@ -770,7 +574,7 @@ describe('RBAC API', () => {
770
574
  pageId: '123e4567-e89b-12d3-a456-426614174000' // Valid UUID format
771
575
  });
772
576
 
773
- expect(result).toBe(true);
577
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
774
578
  expect(mockEngine.isPermitted).toHaveBeenCalled();
775
579
  });
776
580
 
@@ -780,31 +584,35 @@ describe('RBAC API', () => {
780
584
  const error = new Error('Engine error');
781
585
  mockEngine.isPermitted.mockRejectedValue(error);
782
586
 
783
- await expect(isPermitted({
587
+ const result = await isPermitted({
784
588
  userId: 'user-123',
785
589
  scope: { organisationId: 'org-456' },
786
590
  permission: 'read:users'
787
- })).rejects.toThrow('Engine error');
591
+ });
592
+ expect(result.ok).toBe(false);
593
+ expect(result.ok === false && result.error.message).toContain('Engine error');
788
594
  });
789
595
 
790
596
  it('throws OrganisationContextRequiredError when organisationId is missing', async () => {
791
- const { isPermitted, OrganisationContextRequiredError } = await import('./api');
597
+ const { isPermitted } = await import('./api');
792
598
 
793
- await expect(isPermitted({
599
+ const result = await isPermitted({
794
600
  userId: 'user-123',
795
601
  scope: {}, // Missing organisationId
796
602
  permission: 'read:users'
797
- })).rejects.toThrow(OrganisationContextRequiredError);
603
+ });
604
+ expect(result.ok).toBe(false);
798
605
  });
799
606
 
800
607
  it('throws OrganisationContextRequiredError when organisationId is undefined', async () => {
801
- const { isPermitted, OrganisationContextRequiredError } = await import('./api');
608
+ const { isPermitted } = await import('./api');
802
609
 
803
- await expect(isPermitted({
610
+ const result = await isPermitted({
804
611
  userId: 'user-123',
805
612
  scope: { organisationId: undefined },
806
613
  permission: 'read:users'
807
- })).rejects.toThrow(OrganisationContextRequiredError);
614
+ });
615
+ expect(result.ok).toBe(false);
808
616
  });
809
617
  });
810
618
 
@@ -823,7 +631,7 @@ describe('RBAC API', () => {
823
631
  pageId: '123e4567-e89b-12d3-a456-426614174000' // Valid UUID format
824
632
  });
825
633
 
826
- expect(result).toBe(true);
634
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
827
635
  expect(rbacCache.get).toHaveBeenCalledWith(cacheKey, true);
828
636
  expect(mockEngine.isPermitted).not.toHaveBeenCalled();
829
637
  });
@@ -841,7 +649,7 @@ describe('RBAC API', () => {
841
649
  pageId: '123e4567-e89b-12d3-a456-426614174000' // Valid UUID format
842
650
  });
843
651
 
844
- expect(result).toBe(true);
652
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
845
653
  expect(mockEngine.isPermitted).toHaveBeenCalled();
846
654
  // Check that cache.set was called - pageId presence makes it a page-level check
847
655
  expect(rbacCache.set).toHaveBeenCalled();
@@ -869,7 +677,7 @@ describe('RBAC API', () => {
869
677
  permissions: ['read:users', 'write:users']
870
678
  });
871
679
 
872
- expect(result).toBe(true);
680
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
873
681
  expect(mockEngine.isPermitted).toHaveBeenCalledTimes(2);
874
682
  });
875
683
 
@@ -884,7 +692,7 @@ describe('RBAC API', () => {
884
692
  permissions: ['read:users', 'write:users']
885
693
  });
886
694
 
887
- expect(result).toBe(false);
695
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(false);
888
696
  expect(mockEngine.isPermitted).toHaveBeenCalledTimes(2);
889
697
  });
890
698
  });
@@ -901,7 +709,7 @@ describe('RBAC API', () => {
901
709
  permissions: ['read:users', 'write:users']
902
710
  });
903
711
 
904
- expect(result).toBe(true);
712
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
905
713
  expect(mockEngine.isPermitted).toHaveBeenCalledTimes(2);
906
714
  });
907
715
 
@@ -918,7 +726,7 @@ describe('RBAC API', () => {
918
726
  permissions: ['read:users', 'write:users']
919
727
  });
920
728
 
921
- expect(result).toBe(false);
729
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(false);
922
730
  expect(mockEngine.isPermitted).toHaveBeenCalledTimes(2);
923
731
  });
924
732
  });
@@ -931,7 +739,7 @@ describe('RBAC API', () => {
931
739
 
932
740
  const result = await isSuperAdmin('user-123');
933
741
 
934
- expect(result).toBe(true);
742
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
935
743
  expect(mockEngine.checkSuperAdmin).toHaveBeenCalledWith('user-123');
936
744
  });
937
745
 
@@ -941,7 +749,9 @@ describe('RBAC API', () => {
941
749
  const error = new Error('Engine error');
942
750
  mockEngine.checkSuperAdmin.mockRejectedValue(error);
943
751
 
944
- await expect(isSuperAdmin('user-123')).rejects.toThrow('Engine error');
752
+ const result = await isSuperAdmin('user-123');
753
+ expect(result.ok).toBe(false);
754
+ expect(result.ok === false && result.error.message).toContain('Engine error');
945
755
  });
946
756
  });
947
757
 
@@ -956,7 +766,7 @@ describe('RBAC API', () => {
956
766
 
957
767
  const result = await isOrganisationAdmin('user-123', 'org-456');
958
768
 
959
- expect(result).toBe(true);
769
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
960
770
  expect(mockEngine.getAccessLevel).toHaveBeenCalledWith({
961
771
  userId: 'user-123',
962
772
  scope: { organisationId: 'org-456' }
@@ -970,7 +780,7 @@ describe('RBAC API', () => {
970
780
 
971
781
  const result = await isOrganisationAdmin('user-123', 'org-456');
972
782
 
973
- expect(result).toBe(true);
783
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
974
784
  });
975
785
 
976
786
  it('returns false for other access levels', async () => {
@@ -980,7 +790,7 @@ describe('RBAC API', () => {
980
790
 
981
791
  const result = await isOrganisationAdmin('user-123', 'org-456');
982
792
 
983
- expect(result).toBe(false);
793
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(false);
984
794
  });
985
795
  });
986
796
 
@@ -996,7 +806,7 @@ describe('RBAC API', () => {
996
806
  appId: 'app-101'
997
807
  });
998
808
 
999
- expect(result).toBe(true);
809
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1000
810
  expect(mockEngine.getAccessLevel).toHaveBeenCalledWith({
1001
811
  userId: 'user-123',
1002
812
  scope: {
@@ -1016,7 +826,7 @@ describe('RBAC API', () => {
1016
826
  appId: 'app-101'
1017
827
  });
1018
828
 
1019
- expect(result).toBe(false);
829
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(false);
1020
830
  expect(mockEngine.getAccessLevel).not.toHaveBeenCalled();
1021
831
  });
1022
832
 
@@ -1029,7 +839,7 @@ describe('RBAC API', () => {
1029
839
  appId: undefined
1030
840
  });
1031
841
 
1032
- expect(result).toBe(false);
842
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(false);
1033
843
  expect(mockEngine.getAccessLevel).not.toHaveBeenCalled();
1034
844
  });
1035
845
  });
@@ -1130,17 +940,934 @@ describe('RBAC API', () => {
1130
940
  });
1131
941
  });
1132
942
 
1133
- describe('Error Handling', () => {
1134
- it('throws RBACNotInitializedError when engine not available', async () => {
1135
- // Reset global engine by clearing the module cache
1136
- vi.resetModules();
943
+ describe('getPageScopeType', () => {
944
+ let mockEngine: any;
945
+
946
+ beforeEach(() => {
947
+ const createQueryBuilder = (table: string, selectField?: string) => {
948
+ const builder: any = {
949
+ select: vi.fn().mockReturnThis(),
950
+ eq: vi.fn().mockReturnThis(),
951
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
952
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
953
+ };
954
+
955
+ if (table === 'rbac_apps') {
956
+ if (selectField === 'id, name, is_active') {
957
+ builder.maybeSingle = vi.fn().mockResolvedValue({
958
+ data: { id: 'app-123', name: 'test-app', is_active: true },
959
+ error: null
960
+ });
961
+ }
962
+ } else if (table === 'rbac_app_pages') {
963
+ if (selectField === 'id, page_name, app_id') {
964
+ builder.maybeSingle = vi.fn().mockResolvedValue({
965
+ data: { id: '123e4567-e89b-12d3-a456-426614174000', page_name: 'test-page', app_id: 'app-123' },
966
+ error: null
967
+ });
968
+ } else if (selectField === 'scope_type, page_name, app_id') {
969
+ builder.single = vi.fn().mockResolvedValue({
970
+ data: { scope_type: 'organisation', page_name: 'test-page', app_id: 'app-123' },
971
+ error: null
972
+ });
973
+ }
974
+ }
975
+
976
+ builder.select = vi.fn((fields: string) => {
977
+ return createQueryBuilder(table, fields);
978
+ });
979
+
980
+ return builder;
981
+ };
1137
982
 
1138
- const { getAccessLevel } = await import('./api');
983
+ const mockSupabaseForEngine = {
984
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
985
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
986
+ auth: mockSupabase.auth
987
+ };
988
+
989
+ mockEngine = {
990
+ getAccessLevel: vi.fn(),
991
+ getPermissionMap: vi.fn(),
992
+ isPermitted: vi.fn(),
993
+ resolveAppContext: vi.fn(),
994
+ getRoleContext: vi.fn(),
995
+ checkSuperAdmin: vi.fn(),
996
+ supabase: mockSupabaseForEngine as any
997
+ };
998
+
999
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1000
+ mockCreateAuditManager.mockReturnValue({} as any);
1001
+ mockGetRBACLogger.mockReturnValue({
1002
+ info: vi.fn(),
1003
+ warn: vi.fn(),
1004
+ error: vi.fn(),
1005
+ debug: vi.fn()
1006
+ });
1007
+
1008
+ setupRBAC(mockSupabase as any);
1009
+ });
1010
+
1011
+ it('returns scope type for UUID pageId', async () => {
1012
+ // Update mockEngine.supabase before importing (globalEngine references mockEngine)
1013
+ const mockSupabaseForQuery = {
1014
+ from: vi.fn((table: string) => {
1015
+ if (table === 'rbac_app_pages') {
1016
+ return {
1017
+ select: vi.fn().mockReturnThis(),
1018
+ eq: vi.fn().mockReturnThis(),
1019
+ single: vi.fn().mockResolvedValue({
1020
+ data: { scope_type: 'organisation', page_name: 'test-page', app_id: 'app-123' },
1021
+ error: null
1022
+ })
1023
+ };
1024
+ }
1025
+ return {
1026
+ select: vi.fn().mockReturnThis(),
1027
+ eq: vi.fn().mockReturnThis(),
1028
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1029
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1030
+ };
1031
+ }),
1032
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1033
+ auth: mockSupabase.auth
1034
+ };
1139
1035
 
1140
- await expect(getAccessLevel({
1141
- userId: 'user-123',
1142
- scope: { organisationId: 'org-456' }
1143
- })).rejects.toThrow('RBAC system not initialized');
1036
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1037
+ mockEngine.supabase = mockSupabaseForQuery as any;
1038
+
1039
+ const { getPageScopeType } = await import('./api');
1040
+
1041
+ const result = await getPageScopeType('123e4567-e89b-12d3-a456-426614174000', 'app-123');
1042
+
1043
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe('organisation');
1044
+ });
1045
+
1046
+ it('resolves page name to UUID and returns scope type', async () => {
1047
+ // Update mockEngine.supabase before importing (globalEngine references mockEngine)
1048
+ const createQueryBuilder = (table: string, selectField?: string) => {
1049
+ const builder: any = {
1050
+ select: vi.fn().mockReturnThis(),
1051
+ eq: vi.fn().mockReturnThis(),
1052
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1053
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1054
+ };
1055
+
1056
+ if (table === 'rbac_app_pages') {
1057
+ if (selectField === 'id, page_name, app_id') {
1058
+ builder.maybeSingle = vi.fn().mockResolvedValue({
1059
+ data: { id: '123e4567-e89b-12d3-a456-426614174000', page_name: 'test-page', app_id: 'app-123' },
1060
+ error: null
1061
+ });
1062
+ } else if (selectField === 'scope_type, page_name, app_id') {
1063
+ builder.single = vi.fn().mockResolvedValue({
1064
+ data: { scope_type: 'organisation', page_name: 'test-page', app_id: 'app-123' },
1065
+ error: null
1066
+ });
1067
+ }
1068
+ }
1069
+
1070
+ builder.select = vi.fn((fields: string) => {
1071
+ return createQueryBuilder(table, fields);
1072
+ });
1073
+
1074
+ return builder;
1075
+ };
1076
+
1077
+ const mockSupabaseForQuery = {
1078
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1079
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1080
+ auth: mockSupabase.auth
1081
+ };
1082
+
1083
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1084
+ mockEngine.supabase = mockSupabaseForQuery as any;
1085
+
1086
+ const { getPageScopeType } = await import('./api');
1087
+
1088
+ const result = await getPageScopeType('test-page', 'app-123');
1089
+
1090
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe('organisation');
1091
+ });
1092
+
1093
+ it('resolves appId from appName', async () => {
1094
+ // Update mockEngine.supabase before importing (globalEngine references mockEngine)
1095
+ const createQueryBuilder = (table: string, selectField?: string) => {
1096
+ const builder: any = {
1097
+ select: vi.fn().mockReturnThis(),
1098
+ eq: vi.fn().mockReturnThis(),
1099
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1100
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1101
+ };
1102
+
1103
+ if (table === 'rbac_apps') {
1104
+ if (selectField === 'id, name, is_active') {
1105
+ builder.maybeSingle = vi.fn().mockResolvedValue({
1106
+ data: { id: 'app-123', name: 'test-app', is_active: true },
1107
+ error: null
1108
+ });
1109
+ }
1110
+ } else if (table === 'rbac_app_pages') {
1111
+ if (selectField === 'id, page_name, app_id') {
1112
+ builder.maybeSingle = vi.fn().mockResolvedValue({
1113
+ data: { id: '123e4567-e89b-12d3-a456-426614174000', page_name: 'test-page', app_id: 'app-123' },
1114
+ error: null
1115
+ });
1116
+ } else if (selectField === 'scope_type, page_name, app_id') {
1117
+ builder.single = vi.fn().mockResolvedValue({
1118
+ data: { scope_type: 'event', page_name: 'test-page', app_id: 'app-123' },
1119
+ error: null
1120
+ });
1121
+ }
1122
+ }
1123
+
1124
+ builder.select = vi.fn((fields: string) => {
1125
+ return createQueryBuilder(table, fields);
1126
+ });
1127
+
1128
+ return builder;
1129
+ };
1130
+
1131
+ const mockSupabaseForQuery = {
1132
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1133
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1134
+ auth: mockSupabase.auth
1135
+ };
1136
+
1137
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1138
+ mockEngine.supabase = mockSupabaseForQuery as any;
1139
+
1140
+ const { getPageScopeType } = await import('./api');
1141
+
1142
+ const result = await getPageScopeType('test-page', undefined, 'test-app');
1143
+
1144
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe('event');
1145
+ });
1146
+
1147
+ it('handles errors when app not found', async () => {
1148
+ const createQueryBuilder = (table: string) => {
1149
+ const builder: any = {
1150
+ select: vi.fn().mockReturnThis(),
1151
+ eq: vi.fn().mockReturnThis(),
1152
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1153
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1154
+ };
1155
+
1156
+ if (table === 'rbac_apps') {
1157
+ builder.maybeSingle = vi.fn().mockResolvedValue({
1158
+ data: null,
1159
+ error: null
1160
+ });
1161
+ }
1162
+
1163
+ builder.select = vi.fn(() => builder);
1164
+
1165
+ return builder;
1166
+ };
1167
+
1168
+ const mockSupabaseForEngine = {
1169
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1170
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1171
+ auth: mockSupabase.auth
1172
+ };
1173
+
1174
+ // Update the existing mockEngine's supabase property (globalEngine references the same object)
1175
+ mockEngine.supabase = mockSupabaseForEngine as any;
1176
+
1177
+ const { getPageScopeType } = await import('./api');
1178
+
1179
+ const result = await getPageScopeType('test-page', undefined, 'nonexistent-app');
1180
+ expect(result.ok).toBe(false);
1181
+ });
1182
+
1183
+ it('handles errors when page not found', async () => {
1184
+ const createQueryBuilder = (table: string) => {
1185
+ const builder: any = {
1186
+ select: vi.fn().mockReturnThis(),
1187
+ eq: vi.fn().mockReturnThis(),
1188
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1189
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1190
+ };
1191
+
1192
+ if (table === 'rbac_app_pages') {
1193
+ builder.single = vi.fn().mockResolvedValue({
1194
+ data: null,
1195
+ error: { message: 'Page not found' }
1196
+ });
1197
+ }
1198
+
1199
+ builder.select = vi.fn(() => builder);
1200
+
1201
+ return builder;
1202
+ };
1203
+
1204
+ const mockSupabaseForEngine = {
1205
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1206
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1207
+ auth: mockSupabase.auth
1208
+ };
1209
+
1210
+ // Update the existing mockEngine's supabase property (globalEngine references the same object)
1211
+ mockEngine.supabase = mockSupabaseForEngine as any;
1212
+
1213
+ const { getPageScopeType } = await import('./api');
1214
+
1215
+ const result = await getPageScopeType('nonexistent-page', 'app-123');
1216
+ expect(result.ok).toBe(false);
1217
+ });
1218
+
1219
+ it('handles database errors gracefully', async () => {
1220
+ // Update mockEngine.supabase before importing (globalEngine references mockEngine)
1221
+ const createQueryBuilder = (_table: string) => {
1222
+ const builder: any = {
1223
+ select: vi.fn().mockReturnThis(),
1224
+ eq: vi.fn().mockReturnThis(),
1225
+ single: vi.fn().mockResolvedValue({
1226
+ data: null,
1227
+ error: { message: 'Database error', code: 'PGRST116' }
1228
+ })
1229
+ };
1230
+
1231
+ builder.select = vi.fn(() => builder);
1232
+
1233
+ return builder;
1234
+ };
1235
+
1236
+ const mockSupabaseForQuery = {
1237
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1238
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1239
+ auth: mockSupabase.auth
1240
+ };
1241
+
1242
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1243
+ mockEngine.supabase = mockSupabaseForQuery as any;
1244
+
1245
+ const { getPageScopeType } = await import('./api');
1246
+
1247
+ const result = await getPageScopeType('123e4567-e89b-12d3-a456-426614174000', 'app-123');
1248
+ expect(result.ok).toBe(false);
1249
+ });
1250
+
1251
+ it('returns "both" scope type when page has both scope', async () => {
1252
+ // Update mockEngine.supabase before importing (globalEngine references mockEngine)
1253
+ const createQueryBuilder = (table: string, selectField?: string) => {
1254
+ const builder: any = {
1255
+ select: vi.fn().mockReturnThis(),
1256
+ eq: vi.fn().mockReturnThis(),
1257
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1258
+ };
1259
+
1260
+ if (table === 'rbac_app_pages' && selectField === 'scope_type, page_name, app_id') {
1261
+ builder.single = vi.fn().mockResolvedValue({
1262
+ data: { scope_type: 'both', page_name: 'test-page', app_id: 'app-123' },
1263
+ error: null
1264
+ });
1265
+ }
1266
+
1267
+ builder.select = vi.fn((fields: string) => {
1268
+ return createQueryBuilder(table, fields);
1269
+ });
1270
+
1271
+ return builder;
1272
+ };
1273
+
1274
+ const mockSupabaseForQuery = {
1275
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1276
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1277
+ auth: mockSupabase.auth
1278
+ };
1279
+
1280
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1281
+ mockEngine.supabase = mockSupabaseForQuery as any;
1282
+
1283
+ const { getPageScopeType } = await import('./api');
1284
+
1285
+ const result = await getPageScopeType('123e4567-e89b-12d3-a456-426614174000', 'app-123');
1286
+
1287
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe('both');
1288
+ });
1289
+ });
1290
+
1291
+ describe('isPermitted - Advanced Cases', () => {
1292
+ let mockEngine: any;
1293
+
1294
+ beforeEach(() => {
1295
+ const createQueryBuilder = (table: string, selectField?: string) => {
1296
+ const builder: any = {
1297
+ select: vi.fn().mockReturnThis(),
1298
+ eq: vi.fn().mockReturnThis(),
1299
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1300
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1301
+ };
1302
+
1303
+ if (table === 'rbac_apps') {
1304
+ if (selectField === 'name') {
1305
+ builder.single = vi.fn().mockResolvedValue({ data: { name: 'test-app' }, error: null });
1306
+ }
1307
+ } else if (table === 'rbac_app_pages') {
1308
+ if (selectField === 'scope_type, page_name, app_id') {
1309
+ builder.single = vi.fn().mockResolvedValue({
1310
+ data: { scope_type: 'organisation', page_name: 'test-page', app_id: 'app-123' },
1311
+ error: null
1312
+ });
1313
+ }
1314
+ }
1315
+
1316
+ builder.select = vi.fn((fields: string) => {
1317
+ return createQueryBuilder(table, fields);
1318
+ });
1319
+
1320
+ return builder;
1321
+ };
1322
+
1323
+ const mockSupabaseForEngine = {
1324
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1325
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1326
+ auth: mockSupabase.auth
1327
+ };
1328
+
1329
+ mockEngine = {
1330
+ getAccessLevel: vi.fn(),
1331
+ getPermissionMap: vi.fn(),
1332
+ isPermitted: vi.fn(),
1333
+ resolveAppContext: vi.fn(),
1334
+ getRoleContext: vi.fn(),
1335
+ checkSuperAdmin: vi.fn(),
1336
+ supabase: mockSupabaseForEngine as any
1337
+ };
1338
+
1339
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1340
+ mockCreateAuditManager.mockReturnValue({} as any);
1341
+ mockGetRBACLogger.mockReturnValue({
1342
+ info: vi.fn(),
1343
+ warn: vi.fn(),
1344
+ error: vi.fn(),
1345
+ debug: vi.fn()
1346
+ });
1347
+
1348
+ setupRBAC(mockSupabase as any);
1349
+ });
1350
+
1351
+ it('uses precomputed super admin status when provided as true', async () => {
1352
+ const { isPermitted } = await import('./api');
1353
+
1354
+ mockEngine.isPermitted.mockResolvedValue(true);
1355
+
1356
+ const result = await isPermitted({
1357
+ userId: 'user-123',
1358
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1359
+ permission: 'read:users',
1360
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1361
+ }, undefined, true);
1362
+
1363
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1364
+ expect(mockEngine.checkSuperAdmin).not.toHaveBeenCalled();
1365
+ });
1366
+
1367
+ it('checks super admin when precomputed is null', async () => {
1368
+ const { isPermitted } = await import('./api');
1369
+
1370
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1371
+ mockEngine.isPermitted.mockResolvedValue(true);
1372
+
1373
+ const result = await isPermitted({
1374
+ userId: 'user-123',
1375
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1376
+ permission: 'read:users',
1377
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1378
+ }, undefined, null);
1379
+
1380
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1381
+ expect(mockEngine.checkSuperAdmin).toHaveBeenCalled();
1382
+ });
1383
+
1384
+ it('handles "both" scope type pages correctly', async () => {
1385
+ const createQueryBuilder = (table: string, selectField?: string) => {
1386
+ const builder: any = {
1387
+ select: vi.fn().mockReturnThis(),
1388
+ eq: vi.fn().mockReturnThis(),
1389
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1390
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1391
+ };
1392
+
1393
+ if (table === 'rbac_apps') {
1394
+ if (selectField === 'name') {
1395
+ builder.single = vi.fn().mockResolvedValue({ data: { name: 'test-app' }, error: null });
1396
+ }
1397
+ } else if (table === 'rbac_app_pages') {
1398
+ if (selectField === 'scope_type, page_name, app_id') {
1399
+ builder.single = vi.fn().mockResolvedValue({
1400
+ data: { scope_type: 'both', page_name: 'test-page', app_id: 'app-123' },
1401
+ error: null
1402
+ });
1403
+ }
1404
+ }
1405
+
1406
+ builder.select = vi.fn((fields: string) => {
1407
+ return createQueryBuilder(table, fields);
1408
+ });
1409
+
1410
+ return builder;
1411
+ };
1412
+
1413
+ const mockSupabaseForEngine = {
1414
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1415
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1416
+ auth: mockSupabase.auth
1417
+ };
1418
+
1419
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1420
+ mockEngine.supabase = mockSupabaseForEngine as any;
1421
+
1422
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1423
+ mockEngine.isPermitted
1424
+ .mockResolvedValueOnce(true) // Event scope check
1425
+ .mockResolvedValueOnce(false); // Org scope check
1426
+
1427
+ const { isPermitted } = await import('./api');
1428
+
1429
+ const result = await isPermitted({
1430
+ userId: 'user-123',
1431
+ scope: { organisationId: 'org-456', eventId: 'event-789', appId: 'app-123' },
1432
+ permission: 'read:users',
1433
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1434
+ });
1435
+
1436
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true); // Union: true || false = true
1437
+ });
1438
+
1439
+ it('resolves appName from appId when not provided', async () => {
1440
+ const { isPermitted } = await import('./api');
1441
+
1442
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1443
+ mockEngine.isPermitted.mockResolvedValue(true);
1444
+
1445
+ const result = await isPermitted({
1446
+ userId: 'user-123',
1447
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1448
+ permission: 'read:users',
1449
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1450
+ });
1451
+
1452
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1453
+ });
1454
+
1455
+ it('handles errors in getPageScopeType gracefully', async () => {
1456
+ const createQueryBuilder = (_table: string) => {
1457
+ const builder: any = {
1458
+ select: vi.fn().mockReturnThis(),
1459
+ eq: vi.fn().mockReturnThis(),
1460
+ single: vi.fn().mockResolvedValue({
1461
+ data: null,
1462
+ error: { message: 'Database error' }
1463
+ })
1464
+ };
1465
+
1466
+ builder.select = vi.fn(() => builder);
1467
+
1468
+ return builder;
1469
+ };
1470
+
1471
+ const mockSupabaseForEngine = {
1472
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1473
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1474
+ auth: mockSupabase.auth
1475
+ };
1476
+
1477
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1478
+ mockEngine.supabase = mockSupabaseForEngine as any;
1479
+
1480
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1481
+
1482
+ const { isPermitted } = await import('./api');
1483
+
1484
+ const result = await isPermitted({
1485
+ userId: 'user-123',
1486
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1487
+ permission: 'read:users',
1488
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1489
+ });
1490
+ expect(result.ok).toBe(false);
1491
+ });
1492
+ });
1493
+
1494
+ describe('isPermittedCached - Edge Cases', () => {
1495
+ let mockEngine: any;
1496
+
1497
+ beforeEach(() => {
1498
+ const createQueryBuilder = (table: string, selectField?: string) => {
1499
+ const builder: any = {
1500
+ select: vi.fn().mockReturnThis(),
1501
+ eq: vi.fn().mockReturnThis(),
1502
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1503
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1504
+ };
1505
+
1506
+ if (table === 'rbac_apps') {
1507
+ if (selectField === 'name') {
1508
+ builder.single = vi.fn().mockResolvedValue({ data: { name: 'test-app' }, error: null });
1509
+ }
1510
+ } else if (table === 'rbac_app_pages') {
1511
+ if (selectField === 'scope_type, page_name, app_id') {
1512
+ builder.single = vi.fn().mockResolvedValue({
1513
+ data: { scope_type: 'organisation', page_name: 'test-page', app_id: 'app-123' },
1514
+ error: null
1515
+ });
1516
+ }
1517
+ }
1518
+
1519
+ builder.select = vi.fn((fields: string) => {
1520
+ return createQueryBuilder(table, fields);
1521
+ });
1522
+
1523
+ return builder;
1524
+ };
1525
+
1526
+ const mockSupabaseForEngine = {
1527
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1528
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1529
+ auth: mockSupabase.auth
1530
+ };
1531
+
1532
+ mockEngine = {
1533
+ getAccessLevel: vi.fn(),
1534
+ getPermissionMap: vi.fn(),
1535
+ isPermitted: vi.fn(),
1536
+ resolveAppContext: vi.fn(),
1537
+ getRoleContext: vi.fn(),
1538
+ checkSuperAdmin: vi.fn(),
1539
+ supabase: mockSupabaseForEngine as any
1540
+ };
1541
+
1542
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1543
+ mockCreateAuditManager.mockReturnValue({} as any);
1544
+ mockGetRBACLogger.mockReturnValue({
1545
+ info: vi.fn(),
1546
+ warn: vi.fn(),
1547
+ error: vi.fn(),
1548
+ debug: vi.fn()
1549
+ });
1550
+
1551
+ setupRBAC(mockSupabase as any);
1552
+ });
1553
+
1554
+ it('uses session cache for page-level checks', async () => {
1555
+ const { isPermittedCached } = await import('./api');
1556
+
1557
+ rbacCache.get.mockReturnValue(null);
1558
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1559
+ mockEngine.isPermitted.mockResolvedValue(true);
1560
+
1561
+ const result = await isPermittedCached({
1562
+ userId: 'user-123',
1563
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1564
+ permission: 'read:users',
1565
+ pageId: '123e4567-e89b-12d3-a456-426614174000'
1566
+ });
1567
+
1568
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1569
+ expect(rbacCache.set).toHaveBeenCalledWith(
1570
+ expect.any(String),
1571
+ true,
1572
+ undefined,
1573
+ true // useSessionCache = true for page-level checks
1574
+ );
1575
+ });
1576
+
1577
+ it('uses regular cache for non-page-level checks', async () => {
1578
+ const { isPermittedCached } = await import('./api');
1579
+
1580
+ rbacCache.get.mockReturnValue(null);
1581
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1582
+ mockEngine.isPermitted.mockResolvedValue(true);
1583
+
1584
+ const result = await isPermittedCached({
1585
+ userId: 'user-123',
1586
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1587
+ permission: 'read:users'
1588
+ // No pageId
1589
+ });
1590
+
1591
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1592
+ expect(rbacCache.set).toHaveBeenCalledWith(
1593
+ expect.any(String),
1594
+ true,
1595
+ undefined,
1596
+ false // useSessionCache = false for non-page-level checks
1597
+ );
1598
+ });
1599
+
1600
+ it('detects page-level check by permission pattern', async () => {
1601
+ const { isPermittedCached } = await import('./api');
1602
+
1603
+ rbacCache.get.mockReturnValue(null);
1604
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1605
+ mockEngine.isPermitted.mockResolvedValue(true);
1606
+
1607
+ const result = await isPermittedCached({
1608
+ userId: 'user-123',
1609
+ scope: { organisationId: 'org-456', appId: 'app-123' },
1610
+ permission: 'read:page.meals'
1611
+ // No pageId, but permission contains 'page.'
1612
+ });
1613
+
1614
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe(true);
1615
+ expect(rbacCache.set).toHaveBeenCalledWith(
1616
+ expect.any(String),
1617
+ true,
1618
+ undefined,
1619
+ true // useSessionCache = true for page-level checks
1620
+ );
1621
+ });
1622
+ });
1623
+
1624
+ describe('getAccessLevel - Super Admin Cases', () => {
1625
+ let mockEngine: any;
1626
+
1627
+ beforeEach(() => {
1628
+ const createQueryBuilder = (_table: string) => {
1629
+ const builder: any = {
1630
+ select: vi.fn().mockReturnThis(),
1631
+ eq: vi.fn().mockReturnThis(),
1632
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1633
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1634
+ };
1635
+
1636
+ builder.select = vi.fn(() => builder);
1637
+
1638
+ return builder;
1639
+ };
1640
+
1641
+ const mockSupabaseForEngine = {
1642
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1643
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1644
+ auth: mockSupabase.auth
1645
+ };
1646
+
1647
+ mockEngine = {
1648
+ getAccessLevel: vi.fn(),
1649
+ getPermissionMap: vi.fn(),
1650
+ isPermitted: vi.fn(),
1651
+ resolveAppContext: vi.fn(),
1652
+ getRoleContext: vi.fn(),
1653
+ checkSuperAdmin: vi.fn(),
1654
+ supabase: mockSupabaseForEngine as any
1655
+ };
1656
+
1657
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1658
+ mockCreateAuditManager.mockReturnValue({} as any);
1659
+ mockGetRBACLogger.mockReturnValue({
1660
+ info: vi.fn(),
1661
+ warn: vi.fn(),
1662
+ error: vi.fn(),
1663
+ debug: vi.fn()
1664
+ });
1665
+
1666
+ setupRBAC(mockSupabase as any);
1667
+ });
1668
+
1669
+ it('returns super for super admin users', async () => {
1670
+ const { getAccessLevel } = await import('./api');
1671
+
1672
+ mockEngine.checkSuperAdmin.mockResolvedValue(true);
1673
+
1674
+ const result = await getAccessLevel({
1675
+ userId: 'user-123',
1676
+ scope: { organisationId: 'org-456' }
1677
+ });
1678
+
1679
+ expect(result.ok).toBe(true); expect(result.ok && result.data).toBe('super');
1680
+ expect(mockEngine.getAccessLevel).not.toHaveBeenCalled();
1681
+ });
1682
+
1683
+ it('handles context validation errors', async () => {
1684
+ const { getAccessLevel } = await import('./api');
1685
+
1686
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1687
+ mockEngine.getAccessLevel.mockRejectedValue(new Error('Context validation failed'));
1688
+
1689
+ const result = await getAccessLevel({
1690
+ userId: 'user-123',
1691
+ scope: {} // Invalid scope
1692
+ });
1693
+ expect(result.ok).toBe(false);
1694
+ });
1695
+ });
1696
+
1697
+ describe('getPermissionMap - Error Cases', () => {
1698
+ let mockEngine: any;
1699
+
1700
+ beforeEach(() => {
1701
+ const createQueryBuilder = (_table: string) => {
1702
+ const builder: any = {
1703
+ select: vi.fn().mockReturnThis(),
1704
+ eq: vi.fn().mockReturnThis(),
1705
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1706
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1707
+ };
1708
+
1709
+ builder.select = vi.fn(() => builder);
1710
+
1711
+ return builder;
1712
+ };
1713
+
1714
+ const mockSupabaseForEngine = {
1715
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1716
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1717
+ auth: mockSupabase.auth
1718
+ };
1719
+
1720
+ mockEngine = {
1721
+ getAccessLevel: vi.fn(),
1722
+ getPermissionMap: vi.fn(),
1723
+ isPermitted: vi.fn(),
1724
+ resolveAppContext: vi.fn(),
1725
+ getRoleContext: vi.fn(),
1726
+ checkSuperAdmin: vi.fn(),
1727
+ supabase: mockSupabaseForEngine as any
1728
+ };
1729
+
1730
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1731
+ mockCreateAuditManager.mockReturnValue({} as any);
1732
+ mockGetRBACLogger.mockReturnValue({
1733
+ info: vi.fn(),
1734
+ warn: vi.fn(),
1735
+ error: vi.fn(),
1736
+ debug: vi.fn()
1737
+ });
1738
+
1739
+ setupRBAC(mockSupabase as any);
1740
+ });
1741
+
1742
+ it('handles context validation errors', async () => {
1743
+ const { getPermissionMap } = await import('./api');
1744
+
1745
+ mockEngine.checkSuperAdmin.mockResolvedValue(false);
1746
+ mockEngine.getPermissionMap.mockRejectedValue(new Error('Context validation failed'));
1747
+
1748
+ const result = await getPermissionMap({
1749
+ userId: 'user-123',
1750
+ scope: {} // Invalid scope
1751
+ });
1752
+ expect(result.ok).toBe(false);
1753
+ });
1754
+ });
1755
+
1756
+ describe('Error Handling', () => {
1757
+ let mockEngine: any;
1758
+
1759
+ beforeEach(() => {
1760
+ const createQueryBuilder = (_table: string) => {
1761
+ const builder: any = {
1762
+ select: vi.fn().mockReturnThis(),
1763
+ eq: vi.fn().mockReturnThis(),
1764
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1765
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1766
+ };
1767
+
1768
+ builder.select = vi.fn(() => builder);
1769
+
1770
+ return builder;
1771
+ };
1772
+
1773
+ const mockSupabaseForEngine = {
1774
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1775
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1776
+ auth: mockSupabase.auth
1777
+ };
1778
+
1779
+ mockEngine = {
1780
+ getAccessLevel: vi.fn(),
1781
+ getPermissionMap: vi.fn(),
1782
+ isPermitted: vi.fn(),
1783
+ resolveAppContext: vi.fn(),
1784
+ getRoleContext: vi.fn(),
1785
+ checkSuperAdmin: vi.fn(),
1786
+ supabase: mockSupabaseForEngine as any
1787
+ };
1788
+
1789
+ mockCreateRBACEngine.mockReturnValue(mockEngine);
1790
+ mockCreateAuditManager.mockReturnValue({} as any);
1791
+ mockGetRBACLogger.mockReturnValue({
1792
+ info: vi.fn(),
1793
+ warn: vi.fn(),
1794
+ error: vi.fn(),
1795
+ debug: vi.fn()
1796
+ });
1797
+
1798
+ setupRBAC(mockSupabase as any);
1799
+ });
1800
+
1801
+ it('throws RBACNotInitializedError when engine not available', async () => {
1802
+ // Reset global engine by clearing the module cache
1803
+ vi.resetModules();
1804
+
1805
+ const { getAccessLevel } = await import('./api');
1806
+
1807
+ const result = await getAccessLevel({
1808
+ userId: 'user-123',
1809
+ scope: { organisationId: 'org-456' }
1810
+ });
1811
+ expect(result.ok).toBe(false);
1812
+ expect(result.ok === false && result.error.code).toBe('RBAC_NOT_INITIALIZED');
1813
+ });
1814
+
1815
+ it('handles errors in resolveAppContext', async () => {
1816
+ // Re-initialize RBAC after potential resetModules() in previous test
1817
+ mockEngine.resolveAppContext.mockRejectedValue(new Error('Database error'));
1818
+
1819
+ // Re-import setupRBAC to get fresh reference after potential resetModules()
1820
+ const { setupRBAC: freshSetupRBAC } = await import('./api');
1821
+ freshSetupRBAC(mockSupabase as any);
1822
+
1823
+ // Dynamic import after setup
1824
+ const { resolveAppContext } = await import('./api');
1825
+
1826
+ const result = await resolveAppContext({
1827
+ userId: 'user-123',
1828
+ appName: 'test-app'
1829
+ });
1830
+ expect(result.ok).toBe(false);
1831
+ expect(result.ok === false && result.error.message).toContain('Database error');
1832
+ });
1833
+
1834
+ it('handles errors in getRoleContext', async () => {
1835
+ // Ensure engine is set up before importing
1836
+ // getRoleContext calls ContextValidator.resolveScopeForPage which needs engine.supabase
1837
+ const createQueryBuilder = (_table: string) => {
1838
+ const builder: any = {
1839
+ select: vi.fn().mockReturnThis(),
1840
+ eq: vi.fn().mockReturnThis(),
1841
+ maybeSingle: vi.fn().mockResolvedValue({ data: null, error: null }),
1842
+ single: vi.fn().mockResolvedValue({ data: null, error: null })
1843
+ };
1844
+ builder.select = vi.fn(() => builder);
1845
+ return builder;
1846
+ };
1847
+
1848
+ const mockSupabaseForQuery = {
1849
+ from: vi.fn((_table: string) => createQueryBuilder(_table)),
1850
+ rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
1851
+ auth: mockSupabase.auth
1852
+ };
1853
+
1854
+ // Update the mockEngine's supabase property (globalEngine references the same object)
1855
+ mockEngine.supabase = mockSupabaseForQuery as any;
1856
+ mockEngine.getRoleContext.mockRejectedValue(new Error('Database error'));
1857
+
1858
+ // Re-import setupRBAC to get fresh reference after potential resetModules()
1859
+ const { setupRBAC: freshSetupRBAC } = await import('./api');
1860
+ freshSetupRBAC(mockSupabase as any);
1861
+
1862
+ // Dynamic import after setup
1863
+ const { getRoleContext } = await import('./api');
1864
+
1865
+ const result = await getRoleContext({
1866
+ userId: 'user-123',
1867
+ scope: { organisationId: 'org-456' }
1868
+ });
1869
+ expect(result.ok).toBe(false);
1870
+ expect(result.ok === false && result.error.message).toContain('Database error');
1144
1871
  });
1145
1872
  });
1146
1873
  });