@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,440 +0,0 @@
1
- /**
2
- * @file Role Based Router Component
3
- * @package @jmruthers/pace-core
4
- * @module RBAC/Components/RoleBasedRouter
5
- * @since 2.0.0
6
- *
7
- * A component that provides centralized routing control and prevents apps from
8
- * implementing custom routing that bypasses permission checks. This is a critical
9
- * security component that ensures all routes are properly protected.
10
- *
11
- * Features:
12
- * - Centralized routing control
13
- * - Role-based route protection
14
- * - Permission-based route filtering
15
- * - Strict mode to prevent bypassing
16
- * - Automatic audit logging
17
- * - Integration with existing RBAC system
18
- * - Clear error messages for unauthorized routes
19
- *
20
- * @example
21
- * ```tsx
22
- * // Basic role-based routing
23
- * <RoleBasedRouter
24
- * routes={routeConfig}
25
- * fallbackRoute="/unauthorized"
26
- * strictMode={true}
27
- * >
28
- * <App />
29
- * </RoleBasedRouter>
30
- *
31
- * // With custom configuration
32
- * <RoleBasedRouter
33
- * routes={routeConfig}
34
- * fallbackRoute="/unauthorized"
35
- * strictMode={true}
36
- * auditLog={true}
37
- * onRouteAccess={(route, allowed) => {
38
- * console.log(`Route access: ${route} - ${allowed ? 'allowed' : 'denied'}`);
39
- * }}
40
- * >
41
- * <App />
42
- * </RoleBasedRouter>
43
- * ```
44
- *
45
- * @security
46
- * - Enforces route-level permissions
47
- * - Prevents apps from bypassing route protection
48
- * - Automatic audit logging for all route access attempts
49
- * - Integration with existing RBAC system
50
- * - Clear error messages for unauthorized routes
51
- *
52
- * @performance
53
- * - Optimized with useMemo and useCallback
54
- * - Cached permission checks
55
- * - Minimal re-renders
56
- * - Efficient route matching
57
- *
58
- * @dependencies
59
- * - React 19+ - Component framework
60
- * - React Router - Routing functionality
61
- * - useCan hook - Permission checking
62
- * - useUnifiedAuth - Authentication context
63
- * - RBAC types - Type definitions
64
- */
65
-
66
- import React, { useMemo, useCallback, useEffect, useState, createContext, useContext } from 'react';
67
- import { useLocation, useNavigate, Outlet } from 'react-router-dom';
68
- import { useCan } from '../hooks';
69
- import { useResolvedScope } from '../hooks/useResolvedScope';
70
- import { useUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
71
- import { UUID, Permission, Scope, AccessLevel } from '../types';
72
- import { getRBACLogger } from '../config';
73
-
74
- export interface RouteConfig {
75
- /** Route path */
76
- path: string;
77
-
78
- /** React component to render */
79
- component: React.ComponentType;
80
-
81
- /** Permissions required for this route */
82
- permissions: Permission[];
83
-
84
- /** If true, this route is public and doesn't require permission checks */
85
- public?: boolean;
86
-
87
- /** Roles that can access this route */
88
- roles?: string[];
89
-
90
- /** Minimum access level required */
91
- accessLevel?: AccessLevel;
92
-
93
- /** Page ID for permission checking */
94
- pageId?: string;
95
-
96
- /** Enable strict mode for this route */
97
- strictMode?: boolean;
98
-
99
- /** Route metadata */
100
- meta?: {
101
- title?: string;
102
- description?: string;
103
- requiresAuth?: boolean;
104
- hidden?: boolean;
105
- };
106
- }
107
-
108
- export interface RouteAccessRecord {
109
- route: string;
110
- permissions: Permission[];
111
- userId: UUID;
112
- scope: Scope;
113
- allowed: boolean;
114
- timestamp: string;
115
- pageId?: string;
116
- roles?: string[];
117
- accessLevel?: AccessLevel;
118
- }
119
-
120
- export interface RoleBasedRouterContextType {
121
- /** Get all accessible routes for current user */
122
- getAccessibleRoutes: () => RouteConfig[];
123
-
124
- /** Check if user can access a specific route */
125
- canAccessRoute: (path: string) => boolean;
126
-
127
- /** Get route configuration for a path */
128
- getRouteConfig: (path: string) => RouteConfig | null;
129
-
130
- /** Get route access history */
131
- getRouteAccessHistory: () => RouteAccessRecord[];
132
-
133
- /** Clear route access history */
134
- clearRouteAccessHistory: () => void;
135
-
136
- /** Check if strict mode is enabled */
137
- isStrictMode: boolean;
138
-
139
- /** Check if audit logging is enabled */
140
- isAuditLogEnabled: boolean;
141
- }
142
-
143
- export interface RoleBasedRouterProps {
144
- /** Route configuration */
145
- routes: RouteConfig[];
146
-
147
- /** Fallback route for unauthorized access */
148
- fallbackRoute?: string;
149
-
150
- /** Child components */
151
- children: React.ReactNode;
152
-
153
- /** Enable strict mode to prevent bypassing (default: true) */
154
- strictMode?: boolean;
155
-
156
- /** Enable audit logging (default: true) */
157
- auditLog?: boolean;
158
-
159
- /** Callback when route access is attempted */
160
- onRouteAccess?: (route: string, allowed: boolean, record: RouteAccessRecord) => void;
161
-
162
- /** Callback when strict mode violation occurs */
163
- onStrictModeViolation?: (route: string, record: RouteAccessRecord) => void;
164
-
165
- /** Maximum number of access records to keep in history */
166
- maxHistorySize?: number;
167
-
168
- /** Custom unauthorized component */
169
- unauthorizedComponent?: React.ComponentType<{ route: string; reason: string }>;
170
- }
171
-
172
- const RoleBasedRouterContext = createContext<RoleBasedRouterContextType | null>(null);
173
-
174
- /**
175
- * RoleBasedRouter - Centralized routing control with role-based protection
176
- *
177
- * This component ensures that all routes are properly protected and provides
178
- * centralized routing control to prevent apps from bypassing route protection.
179
- *
180
- * @param props - Router props
181
- * @returns React element with role-based routing
182
- */
183
- export function RoleBasedRouter({
184
- routes,
185
- fallbackRoute = '/unauthorized',
186
- children,
187
- strictMode = true,
188
- auditLog = true,
189
- onRouteAccess,
190
- onStrictModeViolation,
191
- maxHistorySize = 1000,
192
- unauthorizedComponent: UnauthorizedComponent = DefaultUnauthorizedComponent
193
- }: RoleBasedRouterProps) {
194
- const { user, selectedOrganisation, selectedEvent, supabase } = useUnifiedAuth();
195
- const location = useLocation();
196
- const navigate = useNavigate();
197
- const [routeAccessHistory, setRouteAccessHistory] = useState<RouteAccessRecord[]>([]);
198
- const [currentRoute, setCurrentRoute] = useState<string>('');
199
-
200
- // Use useResolvedScope to get proper scope (org derived from event if needed)
201
- const { resolvedScope } = useResolvedScope({
202
- supabase,
203
- selectedOrganisationId: selectedOrganisation?.id || null,
204
- selectedEventId: selectedEvent?.event_id || null
205
- });
206
-
207
- // Get current scope from resolved scope
208
- // For event-required apps: org is derived from event
209
- // For org-required apps: org comes from selectedOrganisation
210
- const currentScope = resolvedScope;
211
-
212
- // Get route configuration for current path
213
- const currentRouteConfig = useMemo((): RouteConfig | null => {
214
- const currentPath = location.pathname;
215
- return routes.find(route => route.path === currentPath) || null;
216
- }, [routes, location.pathname]);
217
-
218
- // Check if user can access a specific route
219
- const canAccessRoute = useCallback((path: string): boolean => {
220
- if (!user?.id || !currentScope) return false;
221
-
222
- const routeConfig = routes.find(route => route.path === path);
223
- if (!routeConfig) return false;
224
-
225
- // Use the existing RBAC system to check route permissions
226
- // This is a synchronous check for the context - actual permission checking
227
- // happens in the individual route components using useCan hook
228
- // For now, we'll return true and let the individual route components
229
- // handle the actual permission checking asynchronously
230
- return true;
231
- }, [user?.id, currentScope, routes]);
232
-
233
- // Use useCan hook for actual permission checking
234
- // Pass null for super admin status (not checked yet - hook will check if needed)
235
- const { can: canAccessCurrentRoute, isLoading: permissionLoading } = useCan(
236
- user?.id || '',
237
- currentScope || { organisationId: '', eventId: undefined, appId: undefined },
238
- currentRouteConfig?.permissions?.[0] || 'read:page',
239
- currentRouteConfig?.pageId,
240
- true, // useCache
241
- null, // precomputedSuperAdmin - not checked yet
242
- undefined // appName
243
- );
244
-
245
- // Check if route is public
246
- const isPublicRoute = currentRouteConfig?.public === true;
247
-
248
- // If route has no permissions and is not public, deny access (secure by default)
249
- const hasPermissions = currentRouteConfig?.permissions && currentRouteConfig.permissions.length > 0;
250
- const finalCanAccess = isPublicRoute ? true : (hasPermissions ? canAccessCurrentRoute : false);
251
- const finalLoading = isPublicRoute ? false : (hasPermissions ? permissionLoading : false);
252
-
253
- // Get all accessible routes for current user
254
- const getAccessibleRoutes = useCallback((): RouteConfig[] => {
255
- if (!user?.id || !currentScope) return [];
256
-
257
- return routes.filter(route => canAccessRoute(route.path));
258
- }, [user?.id, currentScope, routes, canAccessRoute]);
259
-
260
- // Get route configuration for a path
261
- const getRouteConfig = useCallback((path: string): RouteConfig | null => {
262
- return routes.find(route => route.path === path) || null;
263
- }, [routes]);
264
-
265
- // Get route access history
266
- const getRouteAccessHistory = useCallback((): RouteAccessRecord[] => {
267
- return [...routeAccessHistory];
268
- }, [routeAccessHistory]);
269
-
270
- // Clear route access history
271
- const clearRouteAccessHistory = useCallback(() => {
272
- setRouteAccessHistory([]);
273
- }, []);
274
-
275
- // Record route access attempt
276
- const recordRouteAccess = useCallback((
277
- route: string,
278
- allowed: boolean,
279
- routeConfig: RouteConfig
280
- ) => {
281
- if (!auditLog || !user?.id || !currentScope) return;
282
-
283
- const record: RouteAccessRecord = {
284
- route,
285
- permissions: routeConfig.permissions,
286
- userId: user.id,
287
- scope: currentScope,
288
- allowed,
289
- timestamp: new Date().toISOString(),
290
- pageId: routeConfig.pageId,
291
- roles: routeConfig.roles,
292
- accessLevel: routeConfig.accessLevel
293
- };
294
-
295
- setRouteAccessHistory(prev => {
296
- const newHistory = [record, ...prev];
297
- return newHistory.slice(0, maxHistorySize);
298
- });
299
-
300
- if (onRouteAccess) {
301
- onRouteAccess(route, allowed, record);
302
- }
303
-
304
- if (strictMode && !allowed && onStrictModeViolation) {
305
- onStrictModeViolation(route, record);
306
- }
307
- }, [auditLog, user?.id, currentScope, maxHistorySize, onRouteAccess, onStrictModeViolation, strictMode]);
308
-
309
- // Check route access on location change
310
- useEffect(() => {
311
- const currentPath = location.pathname;
312
- setCurrentRoute(currentPath);
313
-
314
- if (!currentRouteConfig) {
315
- // Route not found in configuration
316
- if (strictMode) {
317
- const logger = getRBACLogger();
318
- logger.error(`STRICT MODE VIOLATION: Route not found in configuration`, {
319
- route: currentPath,
320
- userId: user?.id,
321
- timestamp: new Date().toISOString()
322
- });
323
-
324
- if (onStrictModeViolation) {
325
- onStrictModeViolation(currentPath, {
326
- route: currentPath,
327
- permissions: [],
328
- userId: user?.id || '',
329
- scope: currentScope || { organisationId: '' },
330
- allowed: false,
331
- timestamp: new Date().toISOString()
332
- });
333
- }
334
- }
335
- return;
336
- }
337
-
338
- // Use the actual permission check result
339
- const allowed = finalCanAccess;
340
- // Log route access (including public routes for audit monitoring)
341
- recordRouteAccess(currentPath, allowed, currentRouteConfig);
342
-
343
- if (!allowed && !isPublicRoute) {
344
- // Redirect to fallback route (skip for public routes)
345
- navigate(fallbackRoute, { replace: true });
346
- }
347
- }, [location.pathname, currentRouteConfig, canAccessCurrentRoute, recordRouteAccess, strictMode, user?.id, currentScope, onStrictModeViolation, navigate, fallbackRoute, isPublicRoute]);
348
-
349
- // Context value
350
- const contextValue = useMemo((): RoleBasedRouterContextType => ({
351
- getAccessibleRoutes,
352
- canAccessRoute,
353
- getRouteConfig,
354
- getRouteAccessHistory,
355
- clearRouteAccessHistory,
356
- isStrictMode: strictMode,
357
- isAuditLogEnabled: auditLog
358
- }), [
359
- getAccessibleRoutes,
360
- canAccessRoute,
361
- getRouteConfig,
362
- getRouteAccessHistory,
363
- clearRouteAccessHistory,
364
- strictMode,
365
- auditLog
366
- ]);
367
-
368
- // Show loading state while checking permissions (skip for public routes)
369
- if (finalLoading && !isPublicRoute) {
370
- return (
371
- <div className="flex items-center justify-center min-h-screen">
372
- <div className="text-center">
373
- <div className="animate-spin rounded-full size-8 border-b-2 border-main-600 mx-auto mb-4"></div>
374
- <p className="text-sec-600">Checking permissions...</p>
375
- </div>
376
- </div>
377
- );
378
- }
379
-
380
- // Show unauthorized component if user can't access current route
381
- if (currentRouteConfig && !finalCanAccess && !isPublicRoute) {
382
- return (
383
- <UnauthorizedComponent
384
- route={currentRoute}
385
- reason="Insufficient permissions"
386
- />
387
- );
388
- }
389
- return (
390
- <RoleBasedRouterContext.Provider value={contextValue}>
391
- {children}
392
- <Outlet />
393
- </RoleBasedRouterContext.Provider>
394
- );
395
- }
396
-
397
- /**
398
- * Hook to use role-based router context
399
- *
400
- * @returns Role-based router context
401
- * @throws Error if used outside of RoleBasedRouter
402
- */
403
- export function useRoleBasedRouter(): RoleBasedRouterContextType {
404
- const context = useContext(RoleBasedRouterContext);
405
-
406
- if (!context) {
407
- throw new Error('useRoleBasedRouter must be used within a RoleBasedRouter');
408
- }
409
-
410
- return context;
411
- }
412
-
413
- /**
414
- * Default unauthorized component
415
- */
416
- function DefaultUnauthorizedComponent({ route, reason }: { route: string; reason: string }) {
417
- return (
418
- <div className="flex flex-col items-center justify-center min-h-screen p-8 text-center">
419
- <div className="mb-4">
420
- <svg className="w-16 h-16 text-acc-500 mx-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
421
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
422
- </svg>
423
- </div>
424
- <h2 className="text-xl font-semibold text-sec-900 mb-2">Access Denied</h2>
425
- <p className="text-sec-600 mb-4">
426
- You don't have permission to access <code className="bg-sec-100 px-2 py-1 rounded">{route}</code>
427
- </p>
428
- <p className="text-sm text-sec-500 mb-4">Reason: {reason}</p>
429
- <button
430
- onClick={() => window.history.back()}
431
- className="px-4 py-2 bg-main-600 text-main-50 rounded-md hover:bg-main-700 transition-colors"
432
- >
433
- Go Back
434
- </button>
435
- </div>
436
- );
437
- }
438
-
439
- export default RoleBasedRouter;
440
-