@jmruthers/pace-core 0.6.4 → 0.6.6

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 (387) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/core-usage-manifest.json +93 -0
  4. package/cursor-rules/00-pace-core-compliance.mdc +128 -26
  5. package/cursor-rules/01-standards-compliance.mdc +49 -8
  6. package/cursor-rules/02-project-structure.mdc +6 -0
  7. package/cursor-rules/03-solid-principles.mdc +2 -0
  8. package/cursor-rules/04-testing-standards.mdc +2 -0
  9. package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
  10. package/cursor-rules/06-code-quality.mdc +2 -0
  11. package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
  12. package/cursor-rules/08-markup-quality.mdc +52 -27
  13. package/cursor-rules/09-rbac-compliance.mdc +462 -0
  14. package/cursor-rules/10-error-handling-patterns.mdc +179 -0
  15. package/cursor-rules/11-performance-optimization.mdc +169 -0
  16. package/cursor-rules/12-ci-cd-integration.mdc +150 -0
  17. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  18. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
  19. package/dist/DataTable-LRJL4IRV.js +15 -0
  20. package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
  21. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  22. package/dist/api-Y4MQWOFW.js +4 -0
  23. package/dist/audit-MYQXYZFU.js +3 -0
  24. package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
  25. package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
  26. package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
  27. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  28. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  29. package/dist/chunk-4T7OBVTU.js +62 -0
  30. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  31. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  32. package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
  33. package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
  34. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  35. package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
  36. package/dist/chunk-C7NSAPTL.js +1 -0
  37. package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
  38. package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
  39. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  40. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  41. package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
  42. package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
  43. package/dist/chunk-MBADTM7L.js +64 -0
  44. package/dist/chunk-OHIK3MIO.js +994 -0
  45. package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
  46. package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
  47. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  48. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  49. package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
  50. package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
  51. package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
  52. package/dist/components.d.ts +6 -6
  53. package/dist/components.js +57 -267
  54. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  55. package/dist/eslint-rules/index.cjs +22 -0
  56. package/dist/eslint-rules/rules/compliance.cjs +348 -0
  57. package/dist/eslint-rules/rules/components.cjs +113 -0
  58. package/dist/eslint-rules/rules/imports.cjs +102 -0
  59. package/dist/eslint-rules/rules/rbac.cjs +790 -0
  60. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  61. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  62. package/dist/hooks.d.ts +5 -5
  63. package/dist/hooks.js +62 -270
  64. package/dist/icons/index.d.ts +1 -0
  65. package/dist/icons/index.js +1 -0
  66. package/dist/index.d.ts +36 -26
  67. package/dist/index.js +87 -690
  68. package/dist/providers.d.ts +2 -2
  69. package/dist/providers.js +8 -35
  70. package/dist/rbac/eslint-rules.d.ts +46 -44
  71. package/dist/rbac/eslint-rules.js +7 -4
  72. package/dist/rbac/index.d.ts +124 -594
  73. package/dist/rbac/index.js +14 -207
  74. package/dist/styles/index.js +2 -12
  75. package/dist/theming/runtime.js +3 -19
  76. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  77. package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
  78. package/dist/types-t9H8qKRw.d.ts +55 -0
  79. package/dist/types.d.ts +1 -1
  80. package/dist/types.js +7 -94
  81. package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
  82. package/dist/utils.d.ts +24 -117
  83. package/dist/utils.js +54 -392
  84. package/docs/README.md +16 -6
  85. package/docs/api/README.md +4 -402
  86. package/docs/api/modules.md +454 -930
  87. package/docs/api-reference/components.md +3 -1
  88. package/docs/api-reference/deprecated.md +31 -6
  89. package/docs/api-reference/rpc-functions.md +78 -3
  90. package/docs/best-practices/accessibility.md +6 -3
  91. package/docs/getting-started/cursor-rules.md +3 -23
  92. package/docs/getting-started/dependencies.md +650 -0
  93. package/docs/getting-started/installation-guide.md +20 -7
  94. package/docs/getting-started/quick-start.md +23 -12
  95. package/docs/implementation-guides/permission-enforcement.md +4 -0
  96. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  97. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  98. package/docs/rbac/README.md +12 -3
  99. package/docs/rbac/edge-functions-guide.md +376 -0
  100. package/docs/rbac/secure-client-protection.md +0 -34
  101. package/docs/standards/00-pace-core-compliance.md +967 -0
  102. package/docs/standards/01-standards-compliance.md +188 -0
  103. package/docs/standards/02-project-structure.md +985 -0
  104. package/docs/standards/03-solid-principles.md +39 -0
  105. package/docs/standards/04-testing-standards.md +36 -0
  106. package/docs/standards/05-bug-reports-and-features.md +27 -0
  107. package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
  108. package/docs/standards/07-tech-stack-compliance.md +30 -0
  109. package/docs/standards/08-markup-quality.md +345 -0
  110. package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
  111. package/docs/standards/10-error-handling-patterns.md +401 -0
  112. package/docs/standards/11-performance-optimization.md +348 -0
  113. package/docs/standards/12-ci-cd-integration.md +370 -0
  114. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
  115. package/docs/standards/README.md +62 -33
  116. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  117. package/eslint-config-pace-core.cjs +20 -4
  118. package/package.json +31 -21
  119. package/scripts/audit/audit-compliance.cjs +1295 -0
  120. package/scripts/audit/audit-components.cjs +260 -0
  121. package/scripts/audit/audit-dependencies.cjs +395 -0
  122. package/scripts/audit/audit-rbac.cjs +954 -0
  123. package/scripts/audit/audit-standards.cjs +1268 -0
  124. package/scripts/audit/index.cjs +1898 -194
  125. package/scripts/install-cursor-rules.cjs +259 -8
  126. package/scripts/validate-master.js +1 -1
  127. package/src/__tests__/fixtures/supabase.ts +1 -1
  128. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
  129. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  130. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  131. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
  132. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  133. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  134. package/src/__tests__/public-recipe-view.test.ts +38 -9
  135. package/src/components/Button/Button.tsx +5 -1
  136. package/src/components/ContextSelector/ContextSelector.tsx +42 -39
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
  138. package/src/components/DataTable/components/DataTableBody.tsx +55 -31
  139. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  140. package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
  141. package/src/components/DataTable/components/EditFields.tsx +23 -3
  142. package/src/components/DataTable/components/EditableRow.tsx +7 -2
  143. package/src/components/DataTable/components/ImportModal.tsx +4 -6
  144. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  145. package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
  146. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
  147. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
  148. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  149. package/src/components/DataTable/core/DataTableContext.tsx +1 -1
  150. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  151. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  152. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  153. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  154. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  155. package/src/components/DataTable/types.ts +5 -0
  156. package/src/components/DateTimeField/DateTimeField.tsx +20 -20
  157. package/src/components/DateTimeField/README.md +5 -2
  158. package/src/components/Dialog/Dialog.test.tsx +361 -318
  159. package/src/components/Dialog/Dialog.tsx +1154 -323
  160. package/src/components/Dialog/index.ts +3 -3
  161. package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
  162. package/src/components/FileDisplay/FileDisplay.tsx +28 -22
  163. package/src/components/Form/Form.test.tsx +9 -10
  164. package/src/components/Form/Form.tsx +369 -9
  165. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
  166. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
  167. package/src/components/LoginForm/LoginForm.tsx +2 -2
  168. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  169. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  170. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  171. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  172. package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
  173. package/src/components/PaceAppLayout/README.md +10 -9
  174. package/src/components/PaceAppLayout/test-setup.tsx +40 -31
  175. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  176. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  177. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
  178. package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
  179. package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
  180. package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
  181. package/src/components/Select/Select.tsx +23 -21
  182. package/src/components/Select/types.ts +1 -1
  183. package/src/components/UserMenu/UserMenu.test.tsx +38 -6
  184. package/src/components/UserMenu/UserMenu.tsx +39 -34
  185. package/src/components/index.ts +3 -4
  186. package/src/eslint-rules/index.cjs +22 -0
  187. package/src/eslint-rules/rules/compliance.cjs +348 -0
  188. package/src/eslint-rules/rules/components.cjs +113 -0
  189. package/src/eslint-rules/rules/imports.cjs +102 -0
  190. package/src/eslint-rules/rules/rbac.cjs +790 -0
  191. package/src/eslint-rules/utils/helpers.cjs +42 -0
  192. package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
  193. package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
  194. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  195. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  196. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  197. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  198. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  199. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  200. package/src/hooks/public/usePublicEvent.ts +62 -190
  201. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  202. package/src/hooks/public/usePublicEventLogo.ts +19 -9
  203. package/src/hooks/useAppConfig.ts +26 -24
  204. package/src/hooks/useEventTheme.test.ts +211 -233
  205. package/src/hooks/useEventTheme.ts +19 -28
  206. package/src/hooks/useEvents.ts +11 -7
  207. package/src/hooks/useKeyboardShortcuts.ts +1 -1
  208. package/src/hooks/useOrganisationPermissions.ts +9 -11
  209. package/src/hooks/useOrganisations.ts +13 -7
  210. package/src/hooks/useQueryCache.ts +0 -1
  211. package/src/hooks/useSessionDraft.ts +380 -0
  212. package/src/hooks/useSessionRestoration.ts +3 -1
  213. package/src/icons/index.ts +27 -0
  214. package/src/index.ts +16 -1
  215. package/src/providers/OrganisationProvider.tsx +23 -14
  216. package/src/providers/services/EventServiceProvider.tsx +1 -24
  217. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  218. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
  219. package/src/rbac/README.md +20 -20
  220. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  221. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  222. package/src/rbac/adapters.tsx +7 -295
  223. package/src/rbac/api.test.ts +44 -56
  224. package/src/rbac/api.ts +10 -17
  225. package/src/rbac/cache-invalidation.ts +0 -1
  226. package/src/rbac/compliance/index.ts +10 -0
  227. package/src/rbac/compliance/pattern-detector.ts +553 -0
  228. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  229. package/src/rbac/components/AccessDenied.tsx +150 -0
  230. package/src/rbac/components/NavigationGuard.tsx +12 -20
  231. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  232. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  233. package/src/rbac/components/index.ts +3 -41
  234. package/src/rbac/eslint-rules.js +1 -1
  235. package/src/rbac/hooks/index.ts +0 -3
  236. package/src/rbac/hooks/permissions/index.ts +0 -3
  237. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  238. package/src/rbac/hooks/usePermissions.ts +0 -3
  239. package/src/rbac/hooks/useRBAC.test.ts +21 -3
  240. package/src/rbac/hooks/useRBAC.ts +4 -3
  241. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  242. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  243. package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
  244. package/src/rbac/hooks/useResourcePermissions.ts +182 -63
  245. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  246. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  247. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  248. package/src/rbac/index.ts +7 -9
  249. package/src/rbac/permissions.ts +17 -17
  250. package/src/rbac/utils/contextValidator.ts +45 -7
  251. package/src/services/AuthService.ts +132 -23
  252. package/src/services/EventService.ts +4 -97
  253. package/src/services/InactivityService.ts +155 -58
  254. package/src/services/OrganisationService.ts +7 -44
  255. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  256. package/src/services/base/BaseService.ts +0 -3
  257. package/src/styles/core.css +4 -0
  258. package/src/types/database.generated.ts +4733 -3809
  259. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  260. package/src/utils/context/organisationContext.test.ts +13 -28
  261. package/src/utils/context/organisationContext.ts +21 -52
  262. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  263. package/src/utils/file-reference/index.ts +39 -15
  264. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  265. package/src/utils/formatting/formatTime.test.ts +3 -2
  266. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  267. package/src/utils/index.ts +4 -1
  268. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  269. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  270. package/src/utils/persistence/keyDerivation.ts +304 -0
  271. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  272. package/src/utils/security/secureStorage.ts +5 -5
  273. package/src/utils/storage/helpers.ts +3 -3
  274. package/src/utils/supabase/createBaseClient.ts +147 -0
  275. package/src/utils/timezone/timezone.test.ts +1 -2
  276. package/src/utils/timezone/timezone.ts +1 -1
  277. package/src/utils/validation/csrf.ts +4 -4
  278. package/cursor-rules/CHANGELOG.md +0 -119
  279. package/cursor-rules/README.md +0 -192
  280. package/dist/DataTable-E7YQZD7D.js +0 -175
  281. package/dist/DataTable-E7YQZD7D.js.map +0 -1
  282. package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
  283. package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
  284. package/dist/api-6LVZTHDS.js +0 -52
  285. package/dist/api-6LVZTHDS.js.map +0 -1
  286. package/dist/audit-V53FV5AG.js +0 -17
  287. package/dist/audit-V53FV5AG.js.map +0 -1
  288. package/dist/chunk-36LVWXB2.js +0 -227
  289. package/dist/chunk-36LVWXB2.js.map +0 -1
  290. package/dist/chunk-3LPHPB62.js.map +0 -1
  291. package/dist/chunk-5DRSZLL2.js.map +0 -1
  292. package/dist/chunk-5EC5MEWX.js.map +0 -1
  293. package/dist/chunk-63FOKYGO.js.map +0 -1
  294. package/dist/chunk-6SOIHG6Z.js.map +0 -1
  295. package/dist/chunk-7JPAB3T5.js.map +0 -1
  296. package/dist/chunk-ATKZM7RX.js +0 -2053
  297. package/dist/chunk-ATKZM7RX.js.map +0 -1
  298. package/dist/chunk-AVMLPIM7.js.map +0 -1
  299. package/dist/chunk-DGUM43GV.js.map +0 -1
  300. package/dist/chunk-E66EQZE6.js.map +0 -1
  301. package/dist/chunk-FFQEQTNW.js.map +0 -1
  302. package/dist/chunk-FMUCXFII.js.map +0 -1
  303. package/dist/chunk-G37KK66H.js.map +0 -1
  304. package/dist/chunk-I6DAQMWX.js.map +0 -1
  305. package/dist/chunk-J36DSWQK.js.map +0 -1
  306. package/dist/chunk-KQCRWDSA.js +0 -1
  307. package/dist/chunk-KQCRWDSA.js.map +0 -1
  308. package/dist/chunk-L4OXEN46.js.map +0 -1
  309. package/dist/chunk-LMC26NLJ.js +0 -84
  310. package/dist/chunk-LMC26NLJ.js.map +0 -1
  311. package/dist/chunk-M43Y4SSO.js.map +0 -1
  312. package/dist/chunk-M7MPQISP.js.map +0 -1
  313. package/dist/chunk-NN6WWZ5U.js.map +0 -1
  314. package/dist/chunk-OEWDTMG7.js.map +0 -1
  315. package/dist/chunk-PWLANIRT.js.map +0 -1
  316. package/dist/chunk-QXHPKYJV.js.map +0 -1
  317. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  318. package/dist/chunk-YKRAFF5K.js.map +0 -1
  319. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  320. package/dist/components.js.map +0 -1
  321. package/dist/contextValidator-OOPCLPZW.js +0 -9
  322. package/dist/contextValidator-OOPCLPZW.js.map +0 -1
  323. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  324. package/dist/hooks.js.map +0 -1
  325. package/dist/index.js.map +0 -1
  326. package/dist/providers.js.map +0 -1
  327. package/dist/rbac/eslint-rules.js.map +0 -1
  328. package/dist/rbac/index.js.map +0 -1
  329. package/dist/styles/index.js.map +0 -1
  330. package/dist/theming/runtime.js.map +0 -1
  331. package/dist/types.js.map +0 -1
  332. package/dist/utils.js.map +0 -1
  333. package/docs/standards/01-architecture-standard.md +0 -44
  334. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  335. package/docs/standards/03-component-standard.md +0 -32
  336. package/docs/standards/05-security-standard.md +0 -44
  337. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  338. package/docs/standards/pace-core-compliance.md +0 -432
  339. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  340. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  341. package/scripts/audit/core/checks/bundle.cjs +0 -142
  342. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  343. package/scripts/audit/core/checks/config.cjs +0 -54
  344. package/scripts/audit/core/checks/coverage.cjs +0 -84
  345. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  346. package/scripts/audit/core/checks/documentation.cjs +0 -268
  347. package/scripts/audit/core/checks/environment.cjs +0 -116
  348. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  349. package/scripts/audit/core/checks/forms.cjs +0 -172
  350. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  351. package/scripts/audit/core/checks/hooks.cjs +0 -334
  352. package/scripts/audit/core/checks/imports.cjs +0 -244
  353. package/scripts/audit/core/checks/performance.cjs +0 -325
  354. package/scripts/audit/core/checks/routes.cjs +0 -117
  355. package/scripts/audit/core/checks/state.cjs +0 -130
  356. package/scripts/audit/core/checks/structure.cjs +0 -65
  357. package/scripts/audit/core/checks/style.cjs +0 -584
  358. package/scripts/audit/core/checks/testing.cjs +0 -122
  359. package/scripts/audit/core/checks/typescript.cjs +0 -61
  360. package/scripts/audit/core/scanner.cjs +0 -199
  361. package/scripts/audit/core/utils.cjs +0 -137
  362. package/scripts/audit/reporters/console.cjs +0 -151
  363. package/scripts/audit/reporters/json.cjs +0 -54
  364. package/scripts/audit/reporters/markdown.cjs +0 -124
  365. package/scripts/audit-consuming-app.cjs +0 -86
  366. package/src/eslint-rules/pace-core-compliance.cjs +0 -510
  367. package/src/eslint-rules/pace-core-compliance.js +0 -638
  368. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  369. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  370. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  371. package/src/rbac/components/NavigationProvider.tsx +0 -345
  372. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  373. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  374. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  375. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  376. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  377. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  378. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  379. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  380. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  381. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  382. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  383. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  384. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  385. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  386. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  387. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -1,510 +0,0 @@
1
- /**
2
- * ESLint Rules for pace-core Compliance Enforcement
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/pace-core-compliance
5
- * @since 1.0.0
6
- *
7
- * This module provides ESLint rules to enforce pace-core usage patterns
8
- * and prevent consuming apps from creating local alternatives.
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- // Load manifest data
15
- let manifestData = null;
16
- try {
17
- const manifestPath = path.join(__dirname, '../../core-usage-manifest.json');
18
- if (fs.existsSync(manifestPath)) {
19
- manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
20
- }
21
- } catch (error) {
22
- // If manifest can't be loaded, rules will use hardcoded defaults
23
- console.warn('Warning: Could not load core-usage-manifest.json, using defaults');
24
- }
25
-
26
- // Get restricted imports from manifest or use defaults
27
- const getRestrictedImports = () => {
28
- if (manifestData && manifestData.restrictedImports) {
29
- return manifestData.restrictedImports;
30
- }
31
- // Fallback defaults
32
- return [
33
- { module: '@radix-ui/react-avatar', reason: 'Use Avatar component from pace-core instead' },
34
- { module: '@radix-ui/react-checkbox', reason: 'Use Checkbox component from pace-core instead' },
35
- { module: '@radix-ui/react-dialog', reason: 'Use Dialog component from pace-core instead' },
36
- { module: '@radix-ui/react-label', reason: 'Use Label component from pace-core instead' },
37
- { module: '@radix-ui/react-slot', reason: 'Use Button component from pace-core which handles slot composition' },
38
- { module: '@radix-ui/react-switch', reason: 'Use Switch component from pace-core instead' },
39
- { module: '@radix-ui/react-tabs', reason: 'Use Tabs component from pace-core instead' },
40
- { module: '@radix-ui/react-toast', reason: 'Use Toast component and useToast hook from pace-core instead' },
41
- { module: '@radix-ui/react-tooltip', reason: 'Use Tooltip component from pace-core instead' },
42
- { module: 'react-day-picker', reason: 'Use Calendar component from pace-core instead' },
43
- { module: '@tanstack/react-table', reason: 'Use DataTable component and related hooks from pace-core instead. DataTable wraps and standardizes table functionality' },
44
- { module: 'react-hook-form', reason: 'Use Form component and useZodForm hook from pace-core instead' },
45
- { module: 'zod', reason: 'Use validation utilities and schemas from pace-core instead. pace-core provides standardized validation helpers' }
46
- ];
47
- };
48
-
49
- // Get pace-core components from manifest or use defaults
50
- const getPaceCoreComponents = () => {
51
- if (manifestData && manifestData.components) {
52
- return manifestData.components;
53
- }
54
- return ['Button', 'Card', 'Dialog', 'Input', 'Form', 'Select', 'Alert', 'Badge', 'Checkbox', 'Switch', 'Textarea', 'Label', 'Table', 'DataTable', 'Toast', 'Tooltip', 'Tabs', 'Calendar', 'Avatar', 'Progress'];
55
- };
56
-
57
- // Get pace-core hooks from manifest or use defaults
58
- const getPaceCoreHooks = () => {
59
- if (manifestData && manifestData.hooks) {
60
- return manifestData.hooks;
61
- }
62
- return ['useToast', 'useDebounce', 'useUnifiedAuth', 'useEvents', 'useOrganisations', 'useFileReference', 'useStorage', 'useZodForm', 'useRBAC', 'usePermissions'];
63
- };
64
-
65
- // Get pace-core utils from manifest or use defaults
66
- const getPaceCoreUtils = () => {
67
- if (manifestData && manifestData.utils) {
68
- return manifestData.utils;
69
- }
70
- return ['formatDate', 'formatCurrency', 'formatNumber', 'formatTime', 'formatDateTime', 'cn', 'validateUserInput', 'sanitizeUserInput', 'hasPermission', 'getAppConfig'];
71
- };
72
-
73
- module.exports = {
74
- rules: {
75
- /**
76
- * Block direct imports of libraries wrapped by pace-core
77
- */
78
- 'no-restricted-imports': {
79
- meta: {
80
- type: 'problem',
81
- docs: {
82
- description: 'Disallow direct imports of libraries that pace-core wraps',
83
- category: 'Best Practices',
84
- recommended: true
85
- },
86
- fixable: 'code',
87
- hasSuggestions: true,
88
- messages: {
89
- restrictedImport: '{{message}} Import from {{alternative}} instead.',
90
- restrictedImportWithReason: '{{message}} {{reason}}'
91
- }
92
- },
93
- create(context) {
94
- const restrictedImports = getRestrictedImports();
95
- const restrictedModules = restrictedImports.map(imp => imp.module);
96
-
97
- // Also catch @radix-ui/* patterns
98
- const radixPattern = /^@radix-ui\//;
99
-
100
- return {
101
- ImportDeclaration(node) {
102
- const importSource = node.source.value;
103
-
104
- // Check exact matches
105
- const restricted = restrictedImports.find(imp => imp.module === importSource);
106
- if (restricted) {
107
- context.report({
108
- node: node.source,
109
- messageId: 'restrictedImportWithReason',
110
- data: {
111
- message: `Direct import of '${importSource}' is not allowed.`,
112
- reason: restricted.reason
113
- },
114
- suggest: [{
115
- desc: `Use pace-core alternative: ${restricted.reason}`,
116
- fix(fixer) {
117
- // Suggest importing from pace-core instead
118
- const paceCoreAlternative = getPaceCoreAlternative(importSource);
119
- if (paceCoreAlternative) {
120
- return fixer.replaceText(
121
- node.source,
122
- `'@jmruthers/pace-core${paceCoreAlternative}'`
123
- );
124
- }
125
- return null;
126
- }
127
- }]
128
- });
129
- return;
130
- }
131
-
132
- // Check @radix-ui/* pattern
133
- if (radixPattern.test(importSource) && !restrictedModules.includes(importSource)) {
134
- context.report({
135
- node: node.source,
136
- messageId: 'restrictedImport',
137
- data: {
138
- message: `Direct import of '${importSource}' is not allowed.`,
139
- alternative: '@jmruthers/pace-core'
140
- },
141
- suggest: [{
142
- desc: 'Use pace-core component instead',
143
- fix(fixer) {
144
- return fixer.replaceText(
145
- node.source,
146
- "'@jmruthers/pace-core'"
147
- );
148
- }
149
- }]
150
- });
151
- }
152
- }
153
- };
154
- }
155
- },
156
-
157
- /**
158
- * Prefer pace-core components over native HTML elements or custom implementations
159
- */
160
- 'prefer-pace-core-components': {
161
- meta: {
162
- type: 'suggestion',
163
- docs: {
164
- description: 'Suggest using pace-core components instead of native HTML elements',
165
- category: 'Best Practices',
166
- recommended: true
167
- },
168
- hasSuggestions: true,
169
- messages: {
170
- preferButton: "Use 'Button' component from '@jmruthers/pace-core' instead of <button>",
171
- preferInput: "Use 'Input' component from '@jmruthers/pace-core' instead of <input>",
172
- preferTextarea: "Use 'Textarea' component from '@jmruthers/pace-core' instead of <textarea>",
173
- preferLabel: "Use 'Label' component from '@jmruthers/pace-core' instead of <label>",
174
- preferForm: "Use 'Form' component from '@jmruthers/pace-core' instead of custom form implementation"
175
- }
176
- },
177
- create(context) {
178
- const paceCoreComponents = getPaceCoreComponents();
179
-
180
- return {
181
- JSXOpeningElement(node) {
182
- const elementName = node.name.name;
183
-
184
- if (!elementName) return;
185
-
186
- // Check for native HTML elements that have pace-core alternatives
187
- const nativeToPaceCore = {
188
- 'button': 'Button',
189
- 'input': 'Input',
190
- 'textarea': 'Textarea',
191
- 'label': 'Label'
192
- };
193
-
194
- if (nativeToPaceCore[elementName.toLowerCase()]) {
195
- const paceCoreComponent = nativeToPaceCore[elementName.toLowerCase()];
196
- if (paceCoreComponents.includes(paceCoreComponent)) {
197
- context.report({
198
- node,
199
- messageId: `prefer${paceCoreComponent}`,
200
- suggest: [{
201
- desc: `Import and use ${paceCoreComponent} from pace-core`,
202
- fix(fixer) {
203
- // This is a complex fix, so we'll just report
204
- return null;
205
- }
206
- }]
207
- });
208
- }
209
- }
210
- }
211
- };
212
- }
213
- },
214
-
215
- /**
216
- * Detect custom hooks that duplicate pace-core functionality
217
- */
218
- 'prefer-pace-core-hooks': {
219
- meta: {
220
- type: 'suggestion',
221
- docs: {
222
- description: 'Suggest using pace-core hooks instead of custom implementations',
223
- category: 'Best Practices',
224
- recommended: true
225
- },
226
- messages: {
227
- preferPaceCoreHook: "Consider using '{{hook}}' from '@jmruthers/pace-core' instead of custom hook '{{customHook}}'"
228
- }
229
- },
230
- create(context) {
231
- const paceCoreHooks = getPaceCoreHooks();
232
- const hookPatterns = {
233
- 'useToast': ['useToast', 'useNotification', 'useSnackbar'],
234
- 'useDebounce': ['useDebounce', 'useDebounced'],
235
- 'useAuth': ['useAuth', 'useAuthentication', 'useUser'],
236
- 'useFile': ['useFile', 'useFileUpload', 'useFileReference'],
237
- 'useForm': ['useForm', 'useZodForm'],
238
- 'useTable': ['useTable', 'useDataTable']
239
- };
240
-
241
- return {
242
- FunctionDeclaration(node) {
243
- const functionName = node.id?.name;
244
- if (!functionName || !functionName.startsWith('use')) return;
245
-
246
- // Check if this looks like a hook that pace-core provides
247
- for (const [paceCoreHook, patterns] of Object.entries(hookPatterns)) {
248
- if (paceCoreHooks.includes(paceCoreHook)) {
249
- for (const pattern of patterns) {
250
- if (functionName.toLowerCase().includes(pattern.toLowerCase().replace('use', ''))) {
251
- context.report({
252
- node: node.id,
253
- messageId: 'preferPaceCoreHook',
254
- data: {
255
- hook: paceCoreHook,
256
- customHook: functionName
257
- }
258
- });
259
- return;
260
- }
261
- }
262
- }
263
- }
264
- }
265
- };
266
- }
267
- },
268
-
269
- /**
270
- * Detect utility functions that duplicate pace-core functionality
271
- */
272
- 'prefer-pace-core-utils': {
273
- meta: {
274
- type: 'suggestion',
275
- docs: {
276
- description: 'Suggest using pace-core utilities instead of custom implementations',
277
- category: 'Best Practices',
278
- recommended: true
279
- },
280
- messages: {
281
- preferPaceCoreUtil: "Consider using '{{util}}' from '@jmruthers/pace-core' instead of custom function '{{customUtil}}'"
282
- }
283
- },
284
- create(context) {
285
- const paceCoreUtils = getPaceCoreUtils();
286
- const utilPatterns = {
287
- 'formatDate': ['formatDate', 'formatDateTime', 'dateFormat'],
288
- 'formatCurrency': ['formatCurrency', 'formatMoney', 'currencyFormat'],
289
- 'formatNumber': ['formatNumber', 'numberFormat'],
290
- 'cn': ['cn', 'classNames', 'clsx', 'mergeClasses'],
291
- 'validateUserInput': ['validate', 'validateInput', 'validateUser'],
292
- 'sanitizeUserInput': ['sanitize', 'sanitizeInput', 'sanitizeUser']
293
- };
294
-
295
- return {
296
- FunctionDeclaration(node) {
297
- const functionName = node.id?.name;
298
- if (!functionName) return;
299
-
300
- // Check if this looks like a util that pace-core provides
301
- for (const [paceCoreUtil, patterns] of Object.entries(utilPatterns)) {
302
- if (paceCoreUtils.includes(paceCoreUtil)) {
303
- for (const pattern of patterns) {
304
- if (functionName.toLowerCase().includes(pattern.toLowerCase())) {
305
- context.report({
306
- node: node.id,
307
- messageId: 'preferPaceCoreUtil',
308
- data: {
309
- util: paceCoreUtil,
310
- customUtil: functionName
311
- }
312
- });
313
- return;
314
- }
315
- }
316
- }
317
- }
318
- }
319
- };
320
- }
321
- },
322
-
323
- /**
324
- * Detect component files with names matching pace-core components
325
- */
326
- 'no-local-component-duplication': {
327
- meta: {
328
- type: 'problem',
329
- docs: {
330
- description: 'Disallow local components with names matching pace-core components',
331
- category: 'Best Practices',
332
- recommended: true
333
- },
334
- messages: {
335
- duplicateComponent: "Component '{{componentName}}' conflicts with pace-core component. Use '@jmruthers/pace-core' instead of creating a local version."
336
- }
337
- },
338
- create(context) {
339
- const paceCoreComponents = getPaceCoreComponents();
340
- const filename = context.getFilename();
341
-
342
- // Only check component files (components/, src/components/, etc.)
343
- if (!filename.match(/(components|Components)\//)) {
344
- return {};
345
- }
346
-
347
- // Extract component name from filename
348
- const basename = path.basename(filename, path.extname(filename));
349
- const componentName = basename.replace(/\.(test|spec)$/, '');
350
-
351
- return {
352
- Program(node) {
353
- // Check if this file exports a component with a name matching pace-core
354
- if (paceCoreComponents.includes(componentName)) {
355
- // Check if file exports this component
356
- const hasExport = node.body.some(stmt => {
357
- if (stmt.type === 'ExportNamedDeclaration') {
358
- return stmt.declaration?.id?.name === componentName ||
359
- stmt.specifiers?.some(spec => spec.exported.name === componentName);
360
- }
361
- if (stmt.type === 'ExportDefaultDeclaration') {
362
- return stmt.declaration?.id?.name === componentName ||
363
- stmt.declaration?.name === componentName;
364
- }
365
- return false;
366
- });
367
-
368
- if (hasExport) {
369
- context.report({
370
- node,
371
- messageId: 'duplicateComponent',
372
- data: {
373
- componentName
374
- }
375
- });
376
- }
377
- }
378
- }
379
- };
380
- }
381
- },
382
-
383
- /**
384
- * Disallow direct Supabase client creation - must use useSecureSupabase
385
- */
386
- 'no-direct-supabase-client': {
387
- meta: {
388
- type: 'problem',
389
- docs: {
390
- description: 'Disallow direct createClient calls from @supabase/supabase-js. Use useSecureSupabase() from pace-core instead to ensure organisation context and RLS policies are enforced.',
391
- category: 'Security',
392
- recommended: true
393
- },
394
- messages: {
395
- directClientCreation: "Direct Supabase client creation detected. You MUST use useSecureSupabase() from '@jmruthers/pace-core/rbac' instead to ensure organisation context and RLS policies are enforced. This prevents cross-organisation data access.",
396
- directClientImport: "Direct import of createClient from @supabase/supabase-js is not allowed. Use useSecureSupabase() from '@jmruthers/pace-core/rbac' instead."
397
- },
398
- hasSuggestions: true
399
- },
400
- create(context) {
401
- let hasSupabaseImport = false;
402
- let createClientImported = false;
403
- const filename = context.getFilename();
404
-
405
- // Allow createClient in specific config files (supabaseClient.ts/js, etc.)
406
- const isConfigFile = /(supabase|client)\.(ts|js|tsx|jsx)$/i.test(filename) &&
407
- (filename.includes('supabase') || filename.includes('client'));
408
-
409
- return {
410
- ImportDeclaration(node) {
411
- const importSource = node.source.value;
412
-
413
- // Check for @supabase/supabase-js import
414
- if (importSource === '@supabase/supabase-js') {
415
- hasSupabaseImport = true;
416
-
417
- // Check if createClient is imported
418
- const hasCreateClient = node.specifiers.some(spec => {
419
- if (spec.type === 'ImportSpecifier') {
420
- return spec.imported.name === 'createClient';
421
- }
422
- if (spec.type === 'ImportNamespaceSpecifier') {
423
- return true; // import * as supabase
424
- }
425
- return false;
426
- });
427
-
428
- if (hasCreateClient) {
429
- createClientImported = true;
430
-
431
- // Only report if not in a config file
432
- if (!isConfigFile) {
433
- context.report({
434
- node: node.source,
435
- messageId: 'directClientImport',
436
- suggest: [{
437
- desc: 'Replace with useSecureSupabase hook',
438
- fix(fixer) {
439
- // Remove the import
440
- return fixer.remove(node);
441
- }
442
- }]
443
- });
444
- }
445
- }
446
- }
447
- },
448
-
449
- CallExpression(node) {
450
- // Check for createClient() calls
451
- if (node.callee.type === 'Identifier' && node.callee.name === 'createClient') {
452
- // Only report if not in a config file
453
- if (!isConfigFile) {
454
- context.report({
455
- node,
456
- messageId: 'directClientCreation',
457
- suggest: [{
458
- desc: 'Use useSecureSupabase() hook instead',
459
- fix(fixer) {
460
- // This is complex to auto-fix, so we'll just report
461
- return null;
462
- }
463
- }]
464
- });
465
- }
466
- }
467
-
468
- // Check for supabase.createClient() or similar patterns
469
- if (node.callee.type === 'MemberExpression' &&
470
- node.callee.property?.name === 'createClient') {
471
- if (!isConfigFile) {
472
- context.report({
473
- node,
474
- messageId: 'directClientCreation',
475
- suggest: [{
476
- desc: 'Use useSecureSupabase() hook instead',
477
- fix(fixer) {
478
- return null;
479
- }
480
- }]
481
- });
482
- }
483
- }
484
- }
485
- };
486
- }
487
- }
488
- }
489
- };
490
-
491
- // Helper function to get pace-core alternative for restricted imports
492
- function getPaceCoreAlternative(importSource) {
493
- const alternatives = {
494
- '@radix-ui/react-avatar': '/components',
495
- '@radix-ui/react-checkbox': '/components',
496
- '@radix-ui/react-dialog': '/components',
497
- '@radix-ui/react-label': '/components',
498
- '@radix-ui/react-switch': '/components',
499
- '@radix-ui/react-tabs': '/components',
500
- '@radix-ui/react-toast': '/components',
501
- '@radix-ui/react-tooltip': '/components',
502
- 'react-day-picker': '/components',
503
- '@tanstack/react-table': '/components',
504
- 'react-hook-form': '/components',
505
- 'zod': '/utils'
506
- };
507
-
508
- return alternatives[importSource] || '';
509
- }
510
-