@jmruthers/pace-core 0.6.9 → 0.6.10

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 (665) hide show
  1. package/audit-tool/audits/02-project-structure.cjs +62 -0
  2. package/audit-tool/audits/03-architecture.cjs +145 -19
  3. package/audit-tool/audits/04-code-quality.cjs +86 -1
  4. package/audit-tool/audits/06-security-rbac.cjs +109 -11
  5. package/cursor-rules/02-project-structure.mdc +2 -26
  6. package/cursor-rules/05-styling.mdc +84 -6
  7. package/cursor-rules/06-security-rbac.mdc +124 -1
  8. package/dist/{DataTable-SOAFXIWY.js → DataTable-SAXFG4XI.js} +11 -13
  9. package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
  10. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
  11. package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
  12. package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
  13. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  14. package/dist/assets/app-icons/base_favicon.svg +85 -0
  15. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  16. package/dist/assets/app-icons/core_favicon.svg +256 -0
  17. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  18. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  19. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  20. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  21. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  22. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  23. package/dist/assets/app-icons/team_favicon.svg +67 -0
  24. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  25. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  26. package/dist/audit-Z6ZZBWLU.js +3 -0
  27. package/dist/chunk-3GWSPISD.js +61 -0
  28. package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
  29. package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
  30. package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
  31. package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
  32. package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
  33. package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
  34. package/dist/chunk-FN52B75D.js +246 -0
  35. package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
  36. package/dist/chunk-KPYQWGFQ.js +183 -0
  37. package/dist/{chunk-C7ZQ5O4C.js → chunk-KSNLMI7N.js} +3 -3
  38. package/dist/chunk-KYURMOQM.js +977 -0
  39. package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
  40. package/dist/{chunk-J2U36LHD.js → chunk-MPY44PWB.js} +620 -627
  41. package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
  42. package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
  43. package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
  44. package/dist/{chunk-5HNSDQWH.js → chunk-TFIPNIPE.js} +865 -532
  45. package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
  46. package/dist/chunk-W46INAVW.js +1216 -0
  47. package/dist/chunk-X5EAU5G7.js +793 -0
  48. package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
  49. package/dist/components.d.ts +8 -86
  50. package/dist/components.js +21 -55
  51. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  52. package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
  53. package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
  54. package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
  55. package/dist/hooks.d.ts +11 -10
  56. package/dist/hooks.js +69 -44
  57. package/dist/index.d.ts +379 -31
  58. package/dist/index.js +46 -32
  59. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  60. package/dist/providers.d.ts +28 -14
  61. package/dist/providers.js +5 -5
  62. package/dist/rbac/eslint-rules.js +2 -2
  63. package/dist/rbac/index.d.ts +57 -213
  64. package/dist/rbac/index.js +11 -11
  65. package/dist/theming/runtime.d.ts +9 -3
  66. package/dist/theming/runtime.js +2 -2
  67. package/dist/{timezone-0AyangqX.d.ts → timezone-K-ptz3HO.d.ts} +21 -22
  68. package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
  69. package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
  70. package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
  71. package/dist/types-Dr8sNhER.d.ts +50 -0
  72. package/dist/types.d.ts +4 -4
  73. package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
  74. package/dist/{usePublicRouteParams-DQLrDqDb.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +7 -6
  75. package/dist/utils.d.ts +300 -136
  76. package/dist/utils.js +42 -41
  77. package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
  78. package/docs/api/modules.md +542 -549
  79. package/docs/api-reference/components.md +5 -5
  80. package/docs/implementation-guides/data-tables.md +190 -8
  81. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  82. package/docs/standards/2-project-structure-standards.md +12 -74
  83. package/docs/standards/6-security-rbac-standards.md +222 -7
  84. package/docs/standards/7-api-tech-stack-standards.md +91 -3
  85. package/docs/testing/README.md +10 -0
  86. package/docs/testing/test-setup-for-consumers.md +914 -0
  87. package/eslint-config-pace-core.cjs +4 -0
  88. package/package.json +1 -1
  89. package/scripts/eslint-audit.cjs +110 -11
  90. package/src/__mocks__/lucide-react.ts +0 -2
  91. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
  92. package/src/__tests__/index.test.ts +532 -0
  93. package/src/__tests__/integration/UserProfile.test.tsx +1 -1
  94. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
  95. package/src/__tests__/rls-policies.test.ts +3 -2
  96. package/src/assets/app-icons/admin_favicon.svg +462 -0
  97. package/src/assets/app-icons/base_favicon.svg +85 -0
  98. package/src/assets/app-icons/cake_favicon.svg +68 -0
  99. package/src/assets/app-icons/core_favicon.svg +256 -0
  100. package/src/assets/app-icons/gear_favicon.svg +91 -0
  101. package/src/assets/app-icons/index.ts +83 -0
  102. package/src/assets/app-icons/medi_favicon.svg +92 -0
  103. package/src/assets/app-icons/mint_favicon.svg +83 -0
  104. package/src/assets/app-icons/pace_favicon.svg +49 -0
  105. package/src/assets/app-icons/pump_favicon.svg +68 -0
  106. package/src/assets/app-icons/seed_favicon.svg +91 -0
  107. package/src/assets/app-icons/team_favicon.svg +67 -0
  108. package/src/assets/app-icons/trac_favicon.svg +112 -0
  109. package/src/assets/app-icons/trip_favicon.svg +102 -0
  110. package/src/components/AddressField/AddressField.test.tsx +378 -3
  111. package/src/components/AddressField/AddressField.tsx +2 -2
  112. package/src/components/AddressField/types.ts +2 -2
  113. package/src/components/Alert/Alert.test.tsx +35 -25
  114. package/src/components/Alert/Alert.tsx +8 -8
  115. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  116. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  117. package/src/components/Avatar/Avatar.test.tsx +11 -1
  118. package/src/components/Avatar/Avatar.tsx +3 -2
  119. package/src/components/Badge/Badge.test.tsx +11 -1
  120. package/src/components/Button/Button.test.tsx +13 -3
  121. package/src/components/Calendar/Calendar.test.tsx +523 -131
  122. package/src/components/Calendar/Calendar.tsx +107 -488
  123. package/src/components/Card/Card.test.tsx +220 -249
  124. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  125. package/src/components/ContextSelector/ContextSelector.tsx +3 -3
  126. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
  127. package/src/components/DataTable/DataTable.tsx +2 -2
  128. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
  129. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
  130. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
  131. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +16 -14
  132. package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
  133. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
  134. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
  135. package/src/components/DataTable/__tests__/README.md +1 -1
  136. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
  138. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
  139. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
  140. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
  141. package/src/components/DataTable/components/ActionButtons.tsx +9 -4
  142. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
  143. package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
  144. package/src/components/DataTable/components/DataTableCore.tsx +44 -52
  145. package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
  146. package/src/components/DataTable/components/DataTableModals.tsx +118 -30
  147. package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
  148. package/src/components/DataTable/components/EditFields.tsx +6 -47
  149. package/src/components/DataTable/components/EditableRow.tsx +8 -8
  150. package/src/components/DataTable/components/EmptyState.tsx +6 -3
  151. package/src/components/DataTable/components/FilterRow.tsx +18 -11
  152. package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
  153. package/src/components/DataTable/components/ImportModal.tsx +305 -133
  154. package/src/components/DataTable/components/LoadingState.tsx +2 -2
  155. package/src/components/DataTable/components/PaginationControls.tsx +0 -4
  156. package/src/components/DataTable/components/RowComponent.tsx +42 -22
  157. package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
  158. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
  159. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
  160. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
  161. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
  162. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
  163. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
  164. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
  165. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
  166. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
  167. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
  168. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
  169. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
  170. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
  171. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
  172. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
  173. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
  174. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
  175. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
  176. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
  177. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
  178. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
  179. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
  180. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
  181. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
  182. package/src/components/DataTable/context/DataTableContext.tsx +9 -10
  183. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
  184. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  185. package/src/components/DataTable/core/ColumnManager.ts +0 -1
  186. package/src/components/DataTable/core/DataManager.ts +4 -2
  187. package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
  188. package/src/components/DataTable/core/PluginRegistry.ts +2 -2
  189. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
  190. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
  191. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
  192. package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
  193. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
  194. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
  195. package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
  196. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
  197. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
  198. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
  199. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
  200. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
  201. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
  202. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
  203. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
  204. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
  205. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
  206. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +128 -77
  207. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
  208. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
  212. package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
  213. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
  214. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
  215. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  216. package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
  217. package/src/components/DataTable/index.ts +24 -2
  218. package/src/components/DataTable/types.ts +6 -3
  219. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
  220. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
  221. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
  222. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
  223. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
  224. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
  225. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
  226. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
  227. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +1 -0
  228. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  229. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  230. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  231. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  232. package/src/components/DataTable/utils/flexibleImport.ts +2 -2
  233. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  234. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  235. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  236. package/src/components/DataTable/utils/selectFieldUtils.ts +0 -7
  237. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
  238. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  239. package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
  240. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  241. package/src/components/Dialog/Dialog.test.tsx +2007 -407
  242. package/src/components/Dialog/Dialog.tsx +97 -192
  243. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  244. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  245. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  246. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  247. package/src/components/ErrorBoundary/index.ts +3 -4
  248. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  249. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
  250. package/src/components/FileDisplay/FileDisplay.tsx +14 -12
  251. package/src/components/FileDisplay/index.tsx +1 -1
  252. package/src/components/FileUpload/FileUpload.test.tsx +54 -18
  253. package/src/components/FileUpload/FileUpload.tsx +10 -7
  254. package/src/components/FileUpload/index.tsx +1 -1
  255. package/src/components/Footer/Footer.test.tsx +33 -114
  256. package/src/components/Form/Form.test.tsx +388 -68
  257. package/src/components/Form/Form.tsx +57 -42
  258. package/src/components/Header/Header.test.tsx +645 -154
  259. package/src/components/Header/Header.tsx +52 -43
  260. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  261. package/src/components/Input/Input.test.tsx +34 -120
  262. package/src/components/Label/Label.test.tsx +47 -46
  263. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
  264. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  265. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
  266. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  267. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
  268. package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
  269. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
  270. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
  271. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  272. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
  273. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
  274. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
  275. package/src/components/PaceAppLayout/README.md +0 -9
  276. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  277. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
  278. package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
  279. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  280. package/src/components/Progress/Progress.test.tsx +127 -1
  281. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  282. package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
  283. package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
  284. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  285. package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
  286. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
  287. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  288. package/src/components/Select/Select.test.tsx +46 -9
  289. package/src/components/Select/Select.tsx +31 -24
  290. package/src/components/Select/__tests__/context.test.tsx +56 -0
  291. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
  292. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
  293. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
  294. package/src/components/Select/hooks/useSelectState.ts +16 -16
  295. package/src/components/Select/types.ts +3 -0
  296. package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
  297. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  298. package/src/components/Switch/Switch.test.tsx +57 -153
  299. package/src/components/Table/Table.test.tsx +47 -317
  300. package/src/components/Tabs/Tabs.tsx +3 -3
  301. package/src/components/Textarea/Textarea.test.tsx +11 -38
  302. package/src/components/Toast/Toast.test.tsx +78 -569
  303. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  304. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  305. package/src/components/UserMenu/UserMenu.tsx +0 -1
  306. package/src/components/__tests__/index.test.ts +346 -0
  307. package/src/components/index.ts +12 -1
  308. package/src/constants/__tests__/performance.test.ts +91 -0
  309. package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
  310. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
  311. package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
  312. package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
  313. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
  314. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
  315. package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
  316. package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
  317. package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
  318. package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
  319. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
  320. package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
  321. package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
  322. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
  323. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
  324. package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
  325. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
  326. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
  327. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
  328. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
  329. package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
  330. package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
  331. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
  332. package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
  333. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
  334. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
  335. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
  336. package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
  337. package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
  338. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
  339. package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
  340. package/src/hooks/__tests__/useToast.test.ts +413 -0
  341. package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
  342. package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
  343. package/src/hooks/index.ts +13 -1
  344. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  345. package/src/hooks/public/usePublicEvent.ts +11 -11
  346. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  347. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  348. package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
  349. package/src/hooks/public/usePublicFileDisplay.ts +79 -49
  350. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  351. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  352. package/src/hooks/services/useAuthService.ts +1 -1
  353. package/src/hooks/services/useEventService.ts +1 -1
  354. package/src/hooks/useAccessibleApps.test.ts +400 -0
  355. package/src/hooks/useAccessibleApps.ts +264 -0
  356. package/src/hooks/useAddressAutocomplete.test.ts +165 -42
  357. package/src/hooks/useAddressAutocomplete.ts +41 -28
  358. package/src/hooks/useAppConfig.ts +13 -3
  359. package/src/hooks/useDataTablePerformance.ts +13 -12
  360. package/src/hooks/useDataTableState.ts +5 -5
  361. package/src/hooks/useEventTheme.test.ts +66 -17
  362. package/src/hooks/useEventTheme.ts +1 -1
  363. package/src/hooks/useEvents.ts +8 -1
  364. package/src/hooks/useFileDisplay.ts +66 -33
  365. package/src/hooks/useFileReference.test.ts +365 -87
  366. package/src/hooks/useFileReference.ts +2 -6
  367. package/src/hooks/useFileUrlCache.ts +4 -1
  368. package/src/hooks/useFormDialog.ts +2 -2
  369. package/src/hooks/useInactivityTracker.ts +3 -3
  370. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  371. package/src/hooks/useOrganisationPermissions.ts +1 -4
  372. package/src/hooks/useOrganisationSecurity.test.ts +1 -30
  373. package/src/hooks/useOrganisationSecurity.ts +3 -3
  374. package/src/hooks/useOrganisations.ts +1 -1
  375. package/src/hooks/usePerformanceMonitor.ts +1 -1
  376. package/src/hooks/usePermissionCache.ts +2 -6
  377. package/src/hooks/useQueryCache.ts +7 -7
  378. package/src/hooks/useSessionDraft.ts +14 -11
  379. package/src/hooks/useSessionRestoration.ts +1 -1
  380. package/src/hooks/useStorage.ts +75 -40
  381. package/src/hooks/useToast.ts +2 -2
  382. package/src/hooks/useZodForm.ts +3 -3
  383. package/src/icons/__tests__/index.test.ts +133 -0
  384. package/src/icons/index.ts +1 -1
  385. package/src/index.ts +43 -4
  386. package/src/providers/OrganisationProvider.test.tsx +40 -0
  387. package/src/providers/OrganisationProvider.tsx +5 -5
  388. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  389. package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
  390. package/src/providers/__tests__/EventProvider.test.tsx +16 -80
  391. package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
  392. package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
  393. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
  394. package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
  395. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
  396. package/src/providers/__tests__/index.test.ts +138 -0
  397. package/src/providers/services/AuthServiceContext.ts +27 -0
  398. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  399. package/src/providers/services/EventServiceContext.ts +25 -0
  400. package/src/providers/services/EventServiceProvider.tsx +11 -20
  401. package/src/providers/services/InactivityServiceContext.ts +25 -0
  402. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  403. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  404. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  405. package/src/providers/services/UnifiedAuthContext.ts +99 -0
  406. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  407. package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
  408. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
  409. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
  410. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
  411. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
  412. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
  413. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
  414. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
  415. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
  416. package/src/providers/services/__tests__/contexts.test.tsx +281 -0
  417. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
  418. package/src/providers/services/useUnifiedAuth.ts +29 -0
  419. package/src/rbac/README.md +5 -5
  420. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
  421. package/src/rbac/__tests__/audit-batched.test.ts +550 -0
  422. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
  423. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
  424. package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
  425. package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
  426. package/src/rbac/__tests__/index.test.ts +107 -0
  427. package/src/rbac/__tests__/performance.test.ts +451 -0
  428. package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
  429. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
  430. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
  431. package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
  432. package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
  433. package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
  434. package/src/rbac/adapters.test.tsx +654 -0
  435. package/src/rbac/adapters.tsx +24 -9
  436. package/src/rbac/api.test.ts +13 -217
  437. package/src/rbac/api.ts +85 -16
  438. package/src/rbac/audit-batched.ts +5 -4
  439. package/src/rbac/audit.test.ts +225 -28
  440. package/src/rbac/audit.ts +22 -17
  441. package/src/rbac/cache-invalidation.ts +18 -15
  442. package/src/rbac/cache.test.ts +123 -63
  443. package/src/rbac/cache.ts +3 -4
  444. package/src/rbac/components/AccessDenied.tsx +20 -18
  445. package/src/rbac/components/NavigationGuard.tsx +10 -8
  446. package/src/rbac/components/PagePermissionGuard.tsx +27 -25
  447. package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
  448. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
  449. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
  450. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
  451. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
  452. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
  453. package/src/rbac/config.test.ts +131 -48
  454. package/src/rbac/config.ts +11 -8
  455. package/src/rbac/docs/event-based-apps.md +26 -13
  456. package/src/rbac/engine.test.ts +496 -146
  457. package/src/rbac/engine.ts +53 -13
  458. package/src/rbac/errors.test.ts +99 -87
  459. package/src/rbac/eslint-rules.js +2 -2
  460. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
  461. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
  462. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
  463. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
  464. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
  465. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
  466. package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
  467. package/src/rbac/hooks/permissions/useCan.ts +12 -10
  468. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
  469. package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
  470. package/src/rbac/hooks/useCan.test.ts +319 -3
  471. package/src/rbac/hooks/usePermissions.test.ts +426 -0
  472. package/src/rbac/hooks/usePermissions.ts +5 -7
  473. package/src/rbac/hooks/useRBAC.test.ts +1669 -2
  474. package/src/rbac/hooks/useRBAC.ts +7 -11
  475. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  476. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  477. package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
  478. package/src/rbac/hooks/useResourcePermissions.ts +9 -7
  479. package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
  480. package/src/rbac/hooks/useRoleManagement.ts +16 -12
  481. package/src/rbac/hooks/useSecureSupabase.ts +11 -12
  482. package/src/rbac/index.ts +32 -32
  483. package/src/rbac/permissions.test.ts +149 -68
  484. package/src/rbac/permissions.ts +0 -3
  485. package/src/rbac/request-deduplication.test.ts +347 -0
  486. package/src/rbac/secureClient.test.ts +112 -159
  487. package/src/rbac/secureClient.ts +46 -26
  488. package/src/rbac/security.test.ts +125 -44
  489. package/src/rbac/security.ts +7 -6
  490. package/src/rbac/types.test.ts +236 -0
  491. package/src/rbac/types.ts +7 -5
  492. package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
  493. package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
  494. package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
  495. package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
  496. package/src/rbac/utils/clientSecurity.ts +6 -4
  497. package/src/rbac/utils/contextValidator.ts +1 -2
  498. package/src/rbac/utils/eventContext.ts +2 -2
  499. package/src/services/AuthService.ts +13 -11
  500. package/src/services/EventService.ts +4 -5
  501. package/src/services/OrganisationService.ts +13 -30
  502. package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
  503. package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
  504. package/src/services/__tests__/AuthService.test.ts +4 -8
  505. package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
  506. package/src/services/__tests__/BaseService.test.ts +49 -0
  507. package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
  508. package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
  509. package/src/services/__tests__/EventService.test.ts +0 -7
  510. package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
  511. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
  512. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
  513. package/src/services/base/BaseService.test.ts +214 -0
  514. package/src/services/interfaces/IOrganisationService.ts +0 -1
  515. package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
  516. package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
  517. package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
  518. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
  519. package/src/styles/core.css +1 -0
  520. package/src/theming/__tests__/runtime.test.ts +29 -94
  521. package/src/theming/parseEventColours.ts +18 -9
  522. package/src/theming/runtime.ts +1 -5
  523. package/src/types/__tests__/core.test.ts +397 -0
  524. package/src/types/__tests__/database-generated.test.ts +78 -0
  525. package/src/types/__tests__/file-reference.test.ts +270 -366
  526. package/src/types/__tests__/guards.test.ts +26 -26
  527. package/src/types/__tests__/index.test.ts +265 -0
  528. package/src/types/__tests__/type-validation.test.ts +3 -3
  529. package/src/types/__tests__/validation.test.ts +0 -2
  530. package/src/types/auth.ts +0 -1
  531. package/src/types/event.ts +1 -1
  532. package/src/types/rpc-responses.ts +33 -0
  533. package/src/types/supabase.ts +1 -2
  534. package/src/types/vitest-globals.d.ts +1 -1
  535. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
  536. package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
  537. package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
  538. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
  539. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  540. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
  541. package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
  542. package/src/utils/__tests__/request-deduplication.test.ts +349 -0
  543. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
  544. package/src/utils/__tests__/timezone.test.ts +1 -1
  545. package/src/utils/__tests__/validation.unit.test.ts +1 -2
  546. package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
  547. package/src/utils/app/appConfig.test.ts +235 -0
  548. package/src/utils/app/appIdResolver.test.ts +188 -20
  549. package/src/utils/app/appNameResolver.test.ts +18 -10
  550. package/src/utils/app/appNameResolver.ts +11 -9
  551. package/src/utils/app/appPortMap.test.ts +125 -0
  552. package/src/utils/app/appPortMap.ts +51 -0
  553. package/src/utils/app/buildAppUrl.test.ts +273 -0
  554. package/src/utils/app/buildAppUrl.ts +114 -0
  555. package/src/utils/audit/audit.test.ts +354 -39
  556. package/src/utils/context/organisationContext.test.ts +10 -4
  557. package/src/utils/context/organisationContext.ts +5 -5
  558. package/src/utils/context/sessionTracking.test.ts +354 -0
  559. package/src/utils/core/__tests__/cn.test.ts +66 -0
  560. package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
  561. package/src/utils/core/__tests__/logger.test.ts +217 -0
  562. package/src/utils/core/debugLogger.ts +15 -8
  563. package/src/utils/core/logger.ts +20 -16
  564. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  565. package/src/utils/device/deviceFingerprint.ts +3 -3
  566. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
  567. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
  568. package/src/utils/dynamic/createLazyComponent.tsx +38 -0
  569. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  570. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  571. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  572. package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
  573. package/src/utils/file-reference/index.ts +0 -1
  574. package/src/utils/formatting/formatDate.test.ts +22 -148
  575. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  576. package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
  577. package/src/utils/formatting/formatNumber.test.ts +259 -0
  578. package/src/utils/formatting/formatTime.test.ts +36 -128
  579. package/src/utils/formatting/formatting.ts +1 -1
  580. package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
  581. package/src/utils/google-places/googlePlacesUtils.ts +15 -2
  582. package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
  583. package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
  584. package/src/utils/index.ts +52 -11
  585. package/src/utils/location/location.test.ts +18 -115
  586. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
  587. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
  588. package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
  589. package/src/utils/performance/bundleAnalysis.ts +16 -22
  590. package/src/utils/performance/performanceBenchmark.ts +12 -4
  591. package/src/utils/performance/performanceBudgets.ts +9 -6
  592. package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
  593. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  594. package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
  595. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
  596. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  597. package/src/utils/request-deduplication.ts +6 -4
  598. package/src/utils/security/auth-utils.ts +7 -7
  599. package/src/utils/security/secureDataAccess.test.ts +22 -191
  600. package/src/utils/security/secureErrors.test.ts +163 -0
  601. package/src/utils/security/secureStorage.test.ts +156 -0
  602. package/src/utils/security/secureStorage.ts +1 -1
  603. package/src/utils/security/security.test.ts +204 -0
  604. package/src/utils/security/securityMonitor.test.ts +90 -0
  605. package/src/utils/security/securityMonitor.ts +1 -1
  606. package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
  607. package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
  608. package/src/utils/storage/helpers.test.ts +757 -430
  609. package/src/utils/storage/helpers.ts +1 -2
  610. package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
  611. package/src/utils/storage/types.ts +2 -2
  612. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  613. package/src/utils/supabase/createBaseClient.ts +2 -1
  614. package/src/utils/timezone/timezone.test.ts +25 -43
  615. package/src/utils/validation/__tests__/common.test.ts +115 -0
  616. package/src/utils/validation/__tests__/csrf.test.ts +65 -0
  617. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
  618. package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
  619. package/src/utils/validation/__tests__/schema.test.ts +127 -0
  620. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
  621. package/src/utils/validation/__tests__/user.test.ts +173 -0
  622. package/src/utils/validation/__tests__/validation.test.ts +197 -0
  623. package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
  624. package/src/utils/validation/htmlSanitization.ts +27 -31
  625. package/src/utils/validation/schema.ts +6 -3
  626. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  627. package/src/vite-env.d.ts +6 -0
  628. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  629. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  630. package/dist/audit-MYQXYZFU.js +0 -3
  631. package/dist/chunk-7ILTDCL2.js +0 -80
  632. package/dist/chunk-EF2UGZWY.js +0 -611
  633. package/dist/chunk-FEJLJNWA.js +0 -181
  634. package/dist/chunk-GS5672WG.js +0 -2003
  635. package/dist/chunk-S6ZQKDY6.js +0 -62
  636. package/dist/chunk-Z2FNRKF3.js +0 -994
  637. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  638. package/src/components/DataTable/components/index.ts +0 -16
  639. package/src/components/DataTable/core/index.ts +0 -1
  640. package/src/components/DataTable/hooks/index.ts +0 -13
  641. package/src/components/DataTable/utils/index.ts +0 -10
  642. package/src/components/PublicLayout/index.ts +0 -32
  643. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  644. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  645. package/src/hooks/public/index.ts +0 -36
  646. package/src/hooks/usePermissionCache.test.ts +0 -536
  647. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  648. package/src/rbac/audit-enhanced.ts +0 -384
  649. package/src/rbac/compliance/database-validator.ts +0 -165
  650. package/src/rbac/compliance/index.ts +0 -48
  651. package/src/rbac/compliance/pattern-detector.ts +0 -553
  652. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  653. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  654. package/src/rbac/compliance/setup-validator.ts +0 -131
  655. package/src/rbac/components/index.ts +0 -26
  656. package/src/rbac/hooks/index.ts +0 -34
  657. package/src/rbac/hooks/permissions/index.ts +0 -4
  658. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  659. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  660. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  661. package/src/utils/google-places/index.ts +0 -26
  662. package/src/utils/location/index.ts +0 -16
  663. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  664. package/src/utils/timezone/index.ts +0 -17
  665. package/src/utils/validation/index.ts +0 -73
@@ -198,6 +198,67 @@ function checkTestColocation(consumingAppPath) {
198
198
  return issues;
199
199
  }
200
200
 
201
+ /**
202
+ * Check for domain-based organization (Pattern 2 - not allowed)
203
+ * Feature-based organization is the only standard
204
+ */
205
+ function checkFeatureBasedOrganization(consumingAppPath) {
206
+ const issues = [];
207
+
208
+ const srcDir = path.join(consumingAppPath, 'src');
209
+ if (!directoryExists(srcDir)) {
210
+ return issues;
211
+ }
212
+
213
+ // Check for src/domains/ directory (Pattern 2 structure - not allowed)
214
+ const domainsDir = path.join(srcDir, 'domains');
215
+ if (directoryExists(domainsDir)) {
216
+ issues.push({
217
+ type: 'organizationPattern',
218
+ file: 'src/domains',
219
+ line: 0,
220
+ message: 'Domain-based organization (src/domains/) is not allowed. Use feature-based organization instead (src/components/[feature]/, src/hooks/[feature]/, etc.)',
221
+ severity: 'error',
222
+ fix: 'Reorganize to feature-based structure: move components from src/domains/[domain]/components/ to src/components/[domain]/, hooks to src/hooks/[domain]/, etc.',
223
+ });
224
+ }
225
+
226
+ // Check components directory for type-based organization (anti-pattern)
227
+ const componentsDir = path.join(srcDir, 'components');
228
+ if (directoryExists(componentsDir)) {
229
+ const componentDirs = [];
230
+ function scanComponentsDir(dir) {
231
+ if (!fs.existsSync(dir)) return;
232
+ const entries = fs.readdirSync(dir);
233
+ entries.forEach(entry => {
234
+ const entryPath = path.join(dir, entry);
235
+ const stat = fs.statSync(entryPath);
236
+ if (stat.isDirectory()) {
237
+ componentDirs.push(entry);
238
+ }
239
+ });
240
+ }
241
+ scanComponentsDir(componentsDir);
242
+
243
+ // Common type-based directory names that should not exist
244
+ const typeBasedPatterns = ['buttons', 'button', 'inputs', 'input', 'cards', 'card', 'forms', 'form', 'modals', 'modal', 'dialogs', 'dialog'];
245
+ const foundTypeBased = componentDirs.filter(dir => typeBasedPatterns.includes(dir.toLowerCase()));
246
+
247
+ if (foundTypeBased.length > 0) {
248
+ issues.push({
249
+ type: 'organizationPattern',
250
+ file: `src/components/${foundTypeBased[0]}`,
251
+ line: 0,
252
+ message: `Components organized by type (${foundTypeBased.join(', ')}) instead of feature. Use pace-core components for UI primitives and organize app components by feature.`,
253
+ severity: 'error',
254
+ fix: `Reorganize components by feature. Use pace-core for ${foundTypeBased.join(', ')} components. Move feature-specific components to src/components/[feature]/`,
255
+ });
256
+ }
257
+ }
258
+
259
+ return issues;
260
+ }
261
+
201
262
  /**
202
263
  * Check Supabase structure
203
264
  * Note: Consuming apps don't need migrations directory - only pace-core handles migrations
@@ -224,6 +285,7 @@ function runStandard2Audit(consumingAppPath) {
224
285
  issues.push(...checkConfigFiles(consumingAppPath));
225
286
  issues.push(...checkImportPaths(consumingAppPath));
226
287
  issues.push(...checkTestColocation(consumingAppPath));
288
+ issues.push(...checkFeatureBasedOrganization(consumingAppPath));
227
289
  issues.push(...checkSupabaseStructure(consumingAppPath));
228
290
  } catch (error) {
229
291
  return {
@@ -13,6 +13,66 @@ const path = require('path');
13
13
  const { findSourceFiles, readFileSafe, getRelativePath } = require('../utils/file-utils.cjs');
14
14
  const { getLineNumber, getCodeSnippet, isInCommentOrString, parseImports } = require('../utils/code-utils.cjs');
15
15
 
16
+ /**
17
+ * Check if a file is a test file or test utility file
18
+ * @param {string} filePath - Full path to the file
19
+ * @returns {boolean} - True if file is a test file
20
+ */
21
+ function isTestFile(filePath) {
22
+ const fileName = path.basename(filePath, path.extname(filePath));
23
+ const fileNameLower = fileName.toLowerCase();
24
+ const filePathLower = filePath.toLowerCase();
25
+
26
+ // Standard test file patterns
27
+ if (filePath.includes('.test.') || filePath.includes('.spec.')) {
28
+ return true;
29
+ }
30
+
31
+ // Files in test directories
32
+ if (filePath.includes('/test/') ||
33
+ filePath.includes('/tests/') ||
34
+ filePath.includes('__tests__') ||
35
+ filePath.includes('__test__')) {
36
+ return true;
37
+ }
38
+
39
+ // Files starting with "test" prefix
40
+ if (fileNameLower.startsWith('test')) {
41
+ return true;
42
+ }
43
+
44
+ // Test utility patterns in filename
45
+ const testUtilityPatterns = [
46
+ 'testassertion', 'testverifier', 'testhelper', 'testutility',
47
+ 'testsetup', 'testteardown', 'testmock', 'testfixture',
48
+ 'testdata', 'testutil', 'testhelper', 'testutils'
49
+ ];
50
+
51
+ if (testUtilityPatterns.some(pattern => fileNameLower.includes(pattern))) {
52
+ return true;
53
+ }
54
+
55
+ // Test utility patterns in path
56
+ const testPathPatterns = [
57
+ 'testutils', 'testhelpers', 'testassertions', 'testverifiers',
58
+ 'testsetup', 'testmocks', 'testfixtures', 'testdata'
59
+ ];
60
+
61
+ if (testPathPatterns.some(pattern => filePathLower.includes(pattern))) {
62
+ return true;
63
+ }
64
+
65
+ // Files ending with test utility suffixes
66
+ if (fileNameLower.endsWith('testutil') ||
67
+ fileNameLower.endsWith('testhelper') ||
68
+ fileNameLower.endsWith('testassertion') ||
69
+ fileNameLower.endsWith('testverifier')) {
70
+ return true;
71
+ }
72
+
73
+ return false;
74
+ }
75
+
16
76
  /**
17
77
  * Check for component boundary violations (domain logic in components)
18
78
  */
@@ -25,29 +85,37 @@ function checkComponentBoundaries(consumingAppPath) {
25
85
  }
26
86
 
27
87
  const componentFiles = findSourceFiles(srcDir).filter(file => {
28
- // Only check actual component files, not test files or utility files
29
- const isTestFile = file.includes('.test.') || file.includes('.spec.');
30
- const isUtilityFile = file.endsWith('Utils.ts') ||
31
- file.endsWith('Utils.tsx') ||
32
- file.endsWith('Helpers.ts') ||
33
- file.endsWith('Helpers.tsx') ||
34
- file.includes('testUtils') ||
35
- file.includes('testHelpers') ||
36
- file.includes('testAssertions') ||
37
- file.includes('testSetup');
38
-
39
- if (isTestFile || isUtilityFile) {
88
+ // Skip all test files
89
+ if (isTestFile(file)) {
40
90
  return false;
41
91
  }
42
92
 
43
93
  const dir = path.dirname(file);
44
94
  const isComponentDir = dir.includes('/components/') || dir.includes('/pages/');
45
- const isComponentFile = file.endsWith('.tsx') || (file.endsWith('.ts') && !isUtilityFile);
95
+ // Only check .tsx files for component boundaries (React components)
96
+ // .ts files are utilities, hooks, or test files and shouldn't be checked
97
+ const isComponentFile = file.endsWith('.tsx');
46
98
 
47
99
  return isComponentDir && isComponentFile;
48
100
  });
49
101
 
50
- componentFiles.forEach(filePath => {
102
+ // For data fetching checks, also include .ts files (to catch data fetching in hooks)
103
+ const filesForDataFetchingCheck = findSourceFiles(srcDir).filter(file => {
104
+ // Skip all test files
105
+ if (isTestFile(file)) {
106
+ return false;
107
+ }
108
+
109
+ const dir = path.dirname(file);
110
+ const isComponentDir = dir.includes('/components/') || dir.includes('/pages/');
111
+ const isComponentFile = file.endsWith('.tsx') || file.endsWith('.ts');
112
+
113
+ return isComponentDir && isComponentFile;
114
+ });
115
+
116
+ // Check for data fetching in components (should be in hooks)
117
+ // Check both .tsx and .ts files for data fetching
118
+ filesForDataFetchingCheck.forEach(filePath => {
51
119
  const content = readFileSafe(filePath);
52
120
  if (!content) {
53
121
  return;
@@ -55,7 +123,6 @@ function checkComponentBoundaries(consumingAppPath) {
55
123
 
56
124
  const relativePath = getRelativePath(filePath, consumingAppPath);
57
125
 
58
- // Check for data fetching in components (should be in hooks)
59
126
  const dataFetchingPatterns = [
60
127
  /\.from\s*\([^)]*\)\s*\.select/i,
61
128
  /\.rpc\s*\(/i,
@@ -87,8 +154,29 @@ function checkComponentBoundaries(consumingAppPath) {
87
154
  }
88
155
  }
89
156
  });
157
+ });
158
+
159
+ // Check for complex business logic in components
160
+ // Only check .tsx files (React components), not .ts files (utilities/hooks/test files)
161
+ componentFiles.forEach(filePath => {
162
+ // Safety check: explicitly skip .ts files (should already be filtered, but double-check)
163
+ if (!filePath.endsWith('.tsx')) {
164
+ return;
165
+ }
166
+
167
+ // Also skip test files as an extra safety measure
168
+ if (isTestFile(filePath)) {
169
+ return;
170
+ }
171
+
172
+ const content = readFileSafe(filePath);
173
+ if (!content) {
174
+ return;
175
+ }
176
+
177
+ const relativePath = getRelativePath(filePath, consumingAppPath);
90
178
 
91
- // Check for complex business logic in components
179
+ // All files in componentFiles are .tsx files, so we can check them directly
92
180
  // Only flag actual business logic patterns, not UI text or comments
93
181
  const businessLogicPatterns = [
94
182
  /if\s*\([^)]*permission[^)]*\)/i, // Permission checks
@@ -98,10 +186,43 @@ function checkComponentBoundaries(consumingAppPath) {
98
186
  /process\w+\s*\(/i, // Process functions (not "Processing..." text)
99
187
  ];
100
188
 
189
+ // Exclude test utility functions - functions that start with test/verify/get/create
190
+ // These are test helpers, not business logic
191
+ const isTestUtilityFunction = (match, content, index) => {
192
+ // Look backwards to extract the function name being called
193
+ const beforeMatch = content.substring(Math.max(0, index - 200), index);
194
+
195
+ // Extract identifier before the match (function name)
196
+ // Look for word characters, dots, and spaces before the match
197
+ const identifierMatch = beforeMatch.match(/(\w+)\s*$/);
198
+ if (identifierMatch) {
199
+ const functionName = identifierMatch[1];
200
+ // Check if function name starts with test utility prefixes
201
+ const testUtilityPrefixes = /^(verify|get|test|create|assert|check|expect|mock|setup|teardown)/i;
202
+ if (testUtilityPrefixes.test(functionName)) {
203
+ return true;
204
+ }
205
+ }
206
+
207
+ // Also check if it's a function definition with test utility prefix
208
+ return /(?:export\s+)?(?:async\s+)?function\s+(verify|get|test|create|assert|check|expect|mock|setup|teardown)\w*\s*\(/i.test(beforeMatch) ||
209
+ // Check if it's a const/let/var assignment
210
+ /(?:export\s+)?(?:const|let|var)\s+(verify|get|test|create|assert|check|expect|mock|setup|teardown)\w*\s*=\s*(?:async\s+)?\(/i.test(beforeMatch);
211
+ };
212
+
101
213
  // This is a heuristic - look for complex logic that should be in hooks/utils
102
214
  // Exclude common UI text patterns
103
215
  const hasUIOnlyText = /Processing\.\.\.|processing\.\.\./i.test(content);
104
- const hasComplexLogic = businessLogicPatterns.some(pattern => pattern.test(content));
216
+ const hasComplexLogic = businessLogicPatterns.some(pattern => {
217
+ const matches = content.matchAll(new RegExp(pattern.source, pattern.flags + 'g'));
218
+ for (const match of matches) {
219
+ const index = match.index;
220
+ if (!isInCommentOrString(content, index) && !isTestUtilityFunction(match, content, index)) {
221
+ return true;
222
+ }
223
+ }
224
+ return false;
225
+ });
105
226
 
106
227
  if (hasComplexLogic && !hasUIOnlyText) {
107
228
  // Check if logic is in a hook call (acceptable)
@@ -155,6 +276,11 @@ function checkApiResultUsage(consumingAppPath) {
155
276
 
156
277
  // Check for API functions that don't use ApiResult
157
278
  sourceFiles.forEach(filePath => {
279
+ // Skip test files
280
+ if (isTestFile(filePath)) {
281
+ return;
282
+ }
283
+
158
284
  const content = readFileSafe(filePath);
159
285
  if (!content) {
160
286
  return;
@@ -168,8 +294,8 @@ function checkApiResultUsage(consumingAppPath) {
168
294
  const functionName = match[1];
169
295
  const functionIndex = match.index;
170
296
 
171
- // Skip if it's a test file or hook
172
- if (filePath.includes('.test.') || functionName.startsWith('use')) {
297
+ // Skip if it's a hook
298
+ if (functionName.startsWith('use')) {
173
299
  return;
174
300
  }
175
301
 
@@ -11,7 +11,8 @@
11
11
  */
12
12
 
13
13
  const path = require('path');
14
- const { findConfigFiles, readFileSafe, getRelativePath } = require('../utils/file-utils.cjs');
14
+ const { findConfigFiles, readFileSafe, getRelativePath, findSourceFiles } = require('../utils/file-utils.cjs');
15
+ const { getLineNumber, isInCommentOrString } = require('../utils/code-utils.cjs');
15
16
 
16
17
  /**
17
18
  * Check TypeScript configuration
@@ -120,6 +121,89 @@ function checkTestCoverageConfig(consumingAppPath) {
120
121
  return issues;
121
122
  }
122
123
 
124
+ /**
125
+ * Check for excessive console logging in production code
126
+ */
127
+ function checkConsoleLogging(consumingAppPath) {
128
+ const issues = [];
129
+
130
+ const srcDir = path.join(consumingAppPath, 'src');
131
+ if (!require('fs').existsSync(srcDir)) {
132
+ return issues;
133
+ }
134
+
135
+ const sourceFiles = findSourceFiles(srcDir).filter(file => {
136
+ // Skip test files
137
+ const isTestFile = file.includes('.test.') ||
138
+ file.includes('.spec.') ||
139
+ file.includes('/test/') ||
140
+ file.includes('/tests/') ||
141
+ file.includes('__tests__') ||
142
+ file.includes('__test__') ||
143
+ path.basename(file, path.extname(file)).toLowerCase().startsWith('test');
144
+
145
+ return !isTestFile;
146
+ });
147
+
148
+ sourceFiles.forEach(filePath => {
149
+ const content = readFileSafe(filePath);
150
+ if (!content) {
151
+ return;
152
+ }
153
+
154
+ const relativePath = getRelativePath(filePath, consumingAppPath);
155
+
156
+ // Count console.log, console.debug, console.warn, console.error statements
157
+ const consolePatterns = [
158
+ { pattern: /console\.(log|debug)\s*\(/gi, name: 'console.log/debug', threshold: 3 },
159
+ { pattern: /console\.warn\s*\(/gi, name: 'console.warn', threshold: 5 },
160
+ { pattern: /console\.error\s*\(/gi, name: 'console.error', threshold: 10 }, // Errors are usually OK
161
+ ];
162
+
163
+ consolePatterns.forEach(({ pattern, name, threshold }) => {
164
+ const matches = [...content.matchAll(pattern)];
165
+ const validMatches = matches.filter(match => {
166
+ const index = match.index;
167
+ return !isInCommentOrString(content, index);
168
+ });
169
+
170
+ if (validMatches.length > threshold) {
171
+ const firstMatch = validMatches[0];
172
+ issues.push({
173
+ type: 'excessiveConsoleLogging',
174
+ file: relativePath,
175
+ line: getLineNumber(content, firstMatch.index),
176
+ message: `Excessive ${name} usage detected (${validMatches.length} instances). Consider removing debug logs or using a proper logging library.`,
177
+ severity: 'warning',
178
+ fix: `Remove or replace ${name} statements. Use a logging library or remove debug logs before production.`,
179
+ });
180
+ }
181
+ });
182
+
183
+ // Special check for DEBUG logging (common pattern)
184
+ const debugLogPattern = /console\.(log|debug)\s*\(\s*['"`]\[DEBUG\]/gi;
185
+ const debugMatches = [...content.matchAll(debugLogPattern)];
186
+ const validDebugMatches = debugMatches.filter(match => {
187
+ const index = match.index;
188
+ return !isInCommentOrString(content, index);
189
+ });
190
+
191
+ if (validDebugMatches.length > 0) {
192
+ const firstMatch = validDebugMatches[0];
193
+ issues.push({
194
+ type: 'debugConsoleLogging',
195
+ file: relativePath,
196
+ line: getLineNumber(content, firstMatch.index),
197
+ message: `Debug console logging detected (${validDebugMatches.length} instances). Debug logs should be removed or disabled in production.`,
198
+ severity: 'warning',
199
+ fix: 'Remove debug console.log statements or use environment-based logging that can be disabled in production.',
200
+ });
201
+ }
202
+ });
203
+
204
+ return issues;
205
+ }
206
+
123
207
  /**
124
208
  * Run audit for Standard 4: Code Quality
125
209
  * @param {string} consumingAppPath - Path to consuming app
@@ -131,6 +215,7 @@ function runStandard4Audit(consumingAppPath) {
131
215
  try {
132
216
  issues.push(...checkTypeScriptConfig(consumingAppPath));
133
217
  issues.push(...checkTestCoverageConfig(consumingAppPath));
218
+ issues.push(...checkConsoleLogging(consumingAppPath));
134
219
  } catch (error) {
135
220
  return {
136
221
  standard: '04-code-quality',
@@ -293,16 +293,36 @@ function checkRLSPolicies(consumingAppPath) {
293
293
  });
294
294
  }
295
295
 
296
+ // Check if function queries RLS-protected tables to determine if SECURITY DEFINER is needed
297
+ const funcBodyStart = content.indexOf('AS $$', funcStart);
298
+ let needsSecurityDefiner = false;
299
+ if (funcBodyStart !== -1) {
300
+ const funcBodyEnd = content.indexOf('$$;', funcBodyStart);
301
+ if (funcBodyEnd !== -1) {
302
+ const funcBody = content.substring(funcBodyStart, funcBodyEnd);
303
+ const rlsProtectedTables = ['rbac_organisation_roles', 'rbac_global_roles', 'rbac_event_app_roles', 'rbac_user_profiles', 'rbac_apps', 'rbac_app_pages', 'rbac_page_permissions'];
304
+ needsSecurityDefiner = rlsProtectedTables.some(table => {
305
+ const tablePattern = new RegExp(`\\b${table}\\b`, 'i');
306
+ return tablePattern.test(funcBody);
307
+ });
308
+ }
309
+ }
310
+
296
311
  if (!hasSecurityDefiner) {
297
- issues.push({
298
- type: 'rlsPolicy',
299
- file: relativePath,
300
- line: getLineNumber(content, funcStart),
301
- message: `Helper function '${funcName}' missing SECURITY DEFINER attribute. RLS helper functions must be SECURITY DEFINER to bypass RLS recursion.`,
302
- code: getCodeSnippet(content, funcStart, 0, 150),
303
- severity: 'error',
304
- fix: 'Add SECURITY DEFINER attribute to function definition.',
305
- });
312
+ if (needsSecurityDefiner) {
313
+ issues.push({
314
+ type: 'rlsPolicy',
315
+ file: relativePath,
316
+ line: getLineNumber(content, funcStart),
317
+ message: `Helper function '${funcName}' queries RLS-protected tables but missing SECURITY DEFINER attribute. REQUIRED: SECURITY DEFINER is needed to bypass RLS and avoid circular dependencies when querying RLS-protected tables from within RLS policies.`,
318
+ code: getCodeSnippet(content, funcStart, 0, 150),
319
+ severity: 'error',
320
+ fix: 'Add SECURITY DEFINER attribute to function definition. Also ensure SET search_path TO public is present.',
321
+ });
322
+ } else {
323
+ // Function doesn't query RLS-protected tables, SECURITY DEFINER might not be needed
324
+ // This is just informational, not an error
325
+ }
306
326
  }
307
327
 
308
328
  if (!hasSearchPath) {
@@ -310,12 +330,90 @@ function checkRLSPolicies(consumingAppPath) {
310
330
  type: 'rlsPolicy',
311
331
  file: relativePath,
312
332
  line: getLineNumber(content, funcStart),
313
- message: `Helper function '${funcName}' missing SET search_path TO public. Required to prevent search path injection.`,
333
+ message: `Helper function '${funcName}' missing SET search_path TO public. MANDATORY for SECURITY DEFINER functions to prevent search path hijacking attacks.`,
314
334
  code: getCodeSnippet(content, funcStart, 0, 150),
315
335
  severity: 'error',
316
- fix: 'Add SET search_path TO public to function definition.',
336
+ fix: 'Add SET search_path TO public to function definition. This is MANDATORY for SECURITY DEFINER functions to prevent search path hijacking.',
317
337
  });
318
338
  }
339
+
340
+ // Additional security checks for SECURITY DEFINER functions
341
+ if (hasSecurityDefiner) {
342
+ // Get function body to check for unqualified references
343
+ const funcBodyStart = content.indexOf('AS $$', funcStart);
344
+ if (funcBodyStart !== -1) {
345
+ const funcBodyEnd = content.indexOf('$$;', funcBodyStart);
346
+ if (funcBodyEnd !== -1) {
347
+ const funcBody = content.substring(funcBodyStart, funcBodyEnd);
348
+
349
+ // Check for unqualified table references (security risk)
350
+ // Look for FROM/JOIN without schema qualification
351
+ const unqualifiedTablePattern = /(?:FROM|JOIN)\s+([a-z_][a-z0-9_]*)\s+(?!WHERE|ON|,|$)/gi;
352
+ let tableMatch;
353
+ const rlsProtectedTables = ['rbac_organisation_roles', 'rbac_global_roles', 'rbac_event_app_roles', 'rbac_user_profiles', 'rbac_apps', 'rbac_app_pages', 'rbac_page_permissions'];
354
+
355
+ while ((tableMatch = unqualifiedTablePattern.exec(funcBody)) !== null) {
356
+ const tableName = tableMatch[1].toLowerCase();
357
+ // Check if it's a known RLS-protected table without schema qualification
358
+ if (rlsProtectedTables.some(t => t.toLowerCase() === tableName)) {
359
+ // Check if it's already schema-qualified (public.table_name)
360
+ const beforeMatch = funcBody.substring(Math.max(0, tableMatch.index - 20), tableMatch.index);
361
+ if (!/public\./i.test(beforeMatch)) {
362
+ issues.push({
363
+ type: 'rlsPolicy',
364
+ file: relativePath,
365
+ line: getLineNumber(content, funcStart + tableMatch.index),
366
+ message: `SECURITY DEFINER function '${funcName}' uses unqualified table reference '${tableName}'. MANDATORY: All table references in SECURITY DEFINER functions must be schema-qualified (e.g., public.${tableName}) to prevent search path hijacking.`,
367
+ code: getCodeSnippet(content, funcStart + tableMatch.index, 0, 100),
368
+ severity: 'error',
369
+ fix: `Schema-qualify the table reference: public.${tableName}`,
370
+ });
371
+ }
372
+ }
373
+ }
374
+
375
+ // Check if function queries RLS-protected tables (justification for SECURITY DEFINER)
376
+ const queriesRLSProtected = rlsProtectedTables.some(table => {
377
+ const tablePattern = new RegExp(`\\b${table}\\b`, 'i');
378
+ return tablePattern.test(funcBody);
379
+ });
380
+
381
+ // Check if function has any table queries at all
382
+ const hasTableQueries = /(?:FROM|JOIN|INTO|UPDATE)\s+\w+/i.test(funcBody);
383
+
384
+ if (!queriesRLSProtected && hasTableQueries) {
385
+ // Function has SECURITY DEFINER but doesn't query RLS-protected tables
386
+ // This might be okay if it needs elevated privileges, but should be documented
387
+ const hasComment = /COMMENT\s+ON\s+FUNCTION.*SECURITY\s+DEFINER/i.test(content.substring(funcStart, funcStart + 2000));
388
+ if (!hasComment) {
389
+ issues.push({
390
+ type: 'rlsPolicy',
391
+ file: relativePath,
392
+ line: getLineNumber(content, funcStart),
393
+ message: `SECURITY DEFINER function '${funcName}' does not query RLS-protected tables. If SECURITY DEFINER is needed for elevated privileges, document why in a COMMENT. Otherwise, consider removing SECURITY DEFINER if not needed.`,
394
+ code: getCodeSnippet(content, funcStart, 0, 200),
395
+ severity: 'warning',
396
+ fix: 'Add COMMENT ON FUNCTION explaining why SECURITY DEFINER is needed, or remove SECURITY DEFINER if not required.',
397
+ });
398
+ }
399
+ } else if (queriesRLSProtected && !hasComment) {
400
+ // Function queries RLS-protected tables but doesn't document why SECURITY DEFINER is needed
401
+ const hasComment = /COMMENT\s+ON\s+FUNCTION/i.test(content.substring(funcStart, funcStart + 2000));
402
+ if (!hasComment) {
403
+ issues.push({
404
+ type: 'rlsPolicy',
405
+ file: relativePath,
406
+ line: getLineNumber(content, funcStart),
407
+ message: `SECURITY DEFINER function '${funcName}' queries RLS-protected tables but lacks documentation. REQUIRED: Add COMMENT ON FUNCTION explaining why SECURITY DEFINER is needed (to avoid circular RLS dependencies).`,
408
+ code: getCodeSnippet(content, funcStart, 0, 200),
409
+ severity: 'warning',
410
+ fix: 'Add COMMENT ON FUNCTION documenting that SECURITY DEFINER is required to avoid circular RLS dependencies when querying RLS-protected tables.',
411
+ });
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
319
417
  }
320
418
  }
321
419
  } catch (error) {
@@ -14,7 +14,7 @@ This guide defines the standard folder structure and file organization for consu
14
14
  ## AI Agent Instructions
15
15
 
16
16
  **When creating or organizing files, ALWAYS:**
17
- 1. **Organize by feature** - Group components, hooks, and utilities by feature/domain, not by type
17
+ 1. **Organize by feature** - Group components, hooks, and utilities by feature, not by type
18
18
  2. **Colocate tests** - Place test files next to source files (`Component.test.tsx` next to `Component.tsx`)
19
19
  3. **Follow naming conventions** - Components: `PascalCase.tsx`, Hooks: `use*.ts`, Utils: `camelCase.ts`
20
20
  4. **Use absolute imports** - Use `@/` path alias for imports, never relative imports for distant files
@@ -74,7 +74,7 @@ your-app/
74
74
 
75
75
  ## MUST: Organize Components by Feature
76
76
 
77
- **ALWAYS organize components by feature/domain, not by type:**
77
+ **ALWAYS organize components by feature, not by type:**
78
78
 
79
79
  ```
80
80
  src/
@@ -136,30 +136,6 @@ src/
136
136
  - where migrations/RLS policies are managed
137
137
  - whether the app is expected to add migrations in the future
138
138
 
139
- ## SHOULD: Organize by Domain
140
-
141
- **For larger apps, SHOULD organize by domain/feature:**
142
-
143
- ```
144
- src/
145
- ├── domains/
146
- │ ├── events/
147
- │ │ ├── components/
148
- │ │ ├── hooks/
149
- │ │ ├── services/
150
- │ │ └── types.ts
151
- │ └── users/
152
- │ ├── components/
153
- │ ├── hooks/
154
- │ ├── services/
155
- │ └── types.ts
156
- ├── shared/ # Shared across domains
157
- │ ├── components/
158
- │ ├── hooks/
159
- │ └── utils/
160
- └── App.tsx
161
- ```
162
-
163
139
  ## MUST: Keep Root Directory Clean
164
140
 
165
141
  **Root directory SHOULD only contain:**