@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
@@ -12,6 +12,8 @@ The PACE Core RBAC (Role-Based Access Control) system provides comprehensive per
12
12
 
13
13
  ## 🚨 Critical Rules (Follow These or It Won't Work)
14
14
 
15
+ > **📋 IMPORTANT**: See [RBAC Contract](./RBAC_CONTRACT.md) for the complete, enforceable contract. This section provides a quick overview.
16
+
15
17
  **MANDATORY Setup Steps (in order):**
16
18
 
17
19
  1. **Call `setupRBAC(supabase)` FIRST** - Must be called before any RBAC components or hooks
@@ -42,6 +44,8 @@ The PACE Core RBAC (Role-Based Access Control) system provides comprehensive per
42
44
  6. **App name must match exactly** - Environment variable must match `rbac_apps.name` (case-sensitive)
43
45
  7. **Never query RBAC tables directly** - Always use `PagePermissionGuard` or RBAC API functions
44
46
 
47
+ **⚠️ Contract Compliance**: All consuming apps must comply with the [RBAC Contract](./RBAC_CONTRACT.md). Violations will result in build errors.
48
+
45
49
  ## 🚀 Quick Start
46
50
 
47
51
  ```tsx
@@ -62,6 +66,8 @@ function MyComponent() {
62
66
 
63
67
  ## 📖 Core Concepts
64
68
 
69
+ - **[RBAC Contract](./RBAC_CONTRACT.md)** - ⚠️ **START HERE** - The definitive, enforceable contract (MUST read)
70
+ - **[Migration Guide](./MIGRATION_GUIDE.md)** - Migrating to RBAC Contract v2.0.0
65
71
  - **[Quick Start](./quick-start.md)** - Get up and running in 10 minutes (foolproof guide for organisation-based apps)
66
72
  - **[Event-Based Apps](./event-based-apps.md)** - Get up and running in 10 minutes (foolproof guide for event-based apps)
67
73
  - **[API Reference](./api-reference.md)** - Complete API documentation
@@ -138,11 +144,14 @@ graph TD
138
144
  - `useCan` - Check individual permissions
139
145
  - `usePermissions` - Get all permissions for a scope
140
146
  - `useAccessLevel` - Get user's access level
141
- - `useMultiplePermissions` - Check multiple permissions efficiently
147
+ - `useMultiplePermissions` - Check multiple permissions efficiently (covers any/all logic)
148
+ - `useResourcePermissions` - Resource CRUD permissions
149
+ - `useSecureSupabase` - Secure Supabase client access
142
150
 
143
151
  ### Components
144
- - `PermissionGuard` - Conditional rendering based on permissions
145
- - `AccessLevelGuard` - Conditional rendering based on access level
152
+ - `PagePermissionGuard` - Page-level permission protection (single canonical component)
153
+ - `NavigationGuard` - Navigation item protection
154
+ - `AccessDenied` - Standard access denied component
146
155
 
147
156
  ### Utilities
148
157
  - `isPermitted` - Server-side permission checking
@@ -0,0 +1,376 @@
1
+ ---
2
+ lastUpdated: 2025-01-28T00:00:00+11:00
3
+ version: 0.6.0
4
+ reviewedBy: rbac-compliance-audit
5
+ ---
6
+
7
+ # Edge Functions RBAC Guide
8
+
9
+ **📚 Related**: [RBAC Compliance Guide](../standards/09-rbac-compliance.md) | [RBAC API Reference](./api-reference.md)
10
+
11
+ This guide explains how to use pace-core RBAC APIs in Edge Functions (Deno serverless functions). **There are NO exceptions** - Edge Functions MUST use pace-core APIs, not custom RBAC helpers.
12
+
13
+ ## Why No Exceptions?
14
+
15
+ Edge Functions cannot use React hooks (they're Deno-based serverless functions), but pace-core provides programmatic APIs that work outside React:
16
+
17
+ - ✅ `isPermitted()` - Programmatic permission checking API
18
+ - ✅ `setupRBAC()` - Initialize RBAC engine with Supabase client
19
+ - ✅ `getAccessLevel()` - Get user access level
20
+ - ✅ `getRoleContext()` - Get user role context
21
+
22
+ **Custom RBAC helpers are FORBIDDEN** because they:
23
+ - Bypass security validation
24
+ - Skip audit logging
25
+ - Miss caching optimizations
26
+ - Duplicate functionality that pace-core already provides
27
+
28
+ ## Correct Pattern
29
+
30
+ ### Step 1: Create Supabase Client
31
+
32
+ ```typescript
33
+ import { createClient } from 'jsr:@supabase/supabase-js@2';
34
+
35
+ Deno.serve(async (req: Request) => {
36
+ // Extract auth token from request
37
+ const authHeader = req.headers.get('Authorization');
38
+ if (!authHeader) {
39
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
40
+ }
41
+
42
+ // Create Supabase client with auth header
43
+ const supabase = createClient(
44
+ Deno.env.get('SUPABASE_URL') ?? '',
45
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
46
+ {
47
+ global: {
48
+ headers: { Authorization: authHeader },
49
+ },
50
+ }
51
+ );
52
+ ```
53
+
54
+ ### Step 2: Get User from Session
55
+
56
+ ```typescript
57
+ // Get authenticated user
58
+ const { data: { user }, error: authError } = await supabase.auth.getUser();
59
+ if (authError || !user) {
60
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
61
+ }
62
+ ```
63
+
64
+ ### Step 3: Setup RBAC
65
+
66
+ ```typescript
67
+ // Import pace-core RBAC functions
68
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
69
+
70
+ // Setup RBAC (MUST be called before using isPermitted)
71
+ setupRBAC(supabase);
72
+ ```
73
+
74
+ ### Step 4: Extract Organisation Context
75
+
76
+ ```typescript
77
+ // Extract organisation context from request
78
+ // Option 1: From headers
79
+ const organisationId = req.headers.get('x-organisation-id');
80
+
81
+ // Option 2: From request body
82
+ if (!organisationId) {
83
+ const body = await req.json();
84
+ organisationId = body.organisationId;
85
+ }
86
+
87
+ // Option 3: From query parameters
88
+ if (!organisationId) {
89
+ const url = new URL(req.url);
90
+ organisationId = url.searchParams.get('organisationId');
91
+ }
92
+
93
+ if (!organisationId) {
94
+ return new Response(
95
+ JSON.stringify({ error: 'Organisation context required' }),
96
+ { status: 400 }
97
+ );
98
+ }
99
+ ```
100
+
101
+ ### Step 5: Check Permission
102
+
103
+ ```typescript
104
+ // Check permission using pace-core API
105
+ const hasPermission = await isPermitted({
106
+ userId: user.id,
107
+ scope: {
108
+ organisationId,
109
+ eventId: req.headers.get('x-event-id'), // Optional
110
+ appId: req.headers.get('x-app-id'), // Optional
111
+ },
112
+ permission: 'read:dashboard',
113
+ pageId: 'dashboard' // Optional, but recommended
114
+ });
115
+
116
+ if (!hasPermission) {
117
+ return new Response(
118
+ JSON.stringify({ error: 'Permission denied' }),
119
+ { status: 403 }
120
+ );
121
+ }
122
+
123
+ // Proceed with function logic
124
+ return new Response(JSON.stringify({ success: true }));
125
+ });
126
+ ```
127
+
128
+ ## Complete Example
129
+
130
+ ```typescript
131
+ // supabase/functions/protected-endpoint/index.ts
132
+ import { createClient } from 'jsr:@supabase/supabase-js@2';
133
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
134
+
135
+ Deno.serve(async (req: Request) => {
136
+ try {
137
+ // 1. Extract auth token
138
+ const authHeader = req.headers.get('Authorization');
139
+ if (!authHeader) {
140
+ return new Response(
141
+ JSON.stringify({ error: 'Unauthorized' }),
142
+ { status: 401, headers: { 'Content-Type': 'application/json' } }
143
+ );
144
+ }
145
+
146
+ // 2. Create Supabase client
147
+ const supabase = createClient(
148
+ Deno.env.get('SUPABASE_URL') ?? '',
149
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
150
+ {
151
+ global: {
152
+ headers: { Authorization: authHeader },
153
+ },
154
+ }
155
+ );
156
+
157
+ // 3. Get authenticated user
158
+ const { data: { user }, error: authError } = await supabase.auth.getUser();
159
+ if (authError || !user) {
160
+ return new Response(
161
+ JSON.stringify({ error: 'Unauthorized' }),
162
+ { status: 401, headers: { 'Content-Type': 'application/json' } }
163
+ );
164
+ }
165
+
166
+ // 4. Setup RBAC
167
+ setupRBAC(supabase);
168
+
169
+ // 5. Extract organisation context
170
+ const organisationId = req.headers.get('x-organisation-id') ||
171
+ (await req.json().catch(() => ({}))).organisationId;
172
+
173
+ if (!organisationId) {
174
+ return new Response(
175
+ JSON.stringify({ error: 'Organisation context required' }),
176
+ { status: 400, headers: { 'Content-Type': 'application/json' } }
177
+ );
178
+ }
179
+
180
+ // 6. Check permission
181
+ const hasPermission = await isPermitted({
182
+ userId: user.id,
183
+ scope: { organisationId },
184
+ permission: 'read:dashboard',
185
+ pageId: 'dashboard'
186
+ });
187
+
188
+ if (!hasPermission) {
189
+ return new Response(
190
+ JSON.stringify({ error: 'Permission denied' }),
191
+ { status: 403, headers: { 'Content-Type': 'application/json' } }
192
+ );
193
+ }
194
+
195
+ // 7. Execute function logic
196
+ const result = {
197
+ message: 'Access granted',
198
+ userId: user.id,
199
+ organisationId
200
+ };
201
+
202
+ return new Response(
203
+ JSON.stringify(result),
204
+ {
205
+ status: 200,
206
+ headers: { 'Content-Type': 'application/json' }
207
+ }
208
+ );
209
+ } catch (error) {
210
+ console.error('Edge Function error:', error);
211
+ return new Response(
212
+ JSON.stringify({ error: 'Internal server error' }),
213
+ { status: 500, headers: { 'Content-Type': 'application/json' } }
214
+ );
215
+ }
216
+ });
217
+ ```
218
+
219
+ ## Migration Guide: Removing Custom RBAC Helpers
220
+
221
+ If you have existing Edge Functions with custom RBAC helpers, follow these steps:
222
+
223
+ ### Step 1: Identify Custom Helpers
224
+
225
+ Search for custom RBAC helpers:
226
+ ```bash
227
+ # Find files with custom RBAC helpers
228
+ grep -r "rbac_check_permission_simplified" supabase/functions/
229
+ grep -r "function.*checkPermission" supabase/functions/
230
+ grep -r "pace-core-compliance-exception" supabase/functions/
231
+ ```
232
+
233
+ ### Step 2: Replace Custom Helper with pace-core API
234
+
235
+ **Before (❌ FORBIDDEN):**
236
+ ```typescript
237
+ // supabase/functions/_shared/rbac.ts
238
+ export async function checkPermission(
239
+ supabase: SupabaseClient,
240
+ userId: string,
241
+ permission: string,
242
+ organisationId: string
243
+ ): Promise<boolean> {
244
+ const { data, error } = await supabase.rpc('rbac_check_permission_simplified', {
245
+ p_user_id: userId,
246
+ p_permission: permission,
247
+ p_organisation_id: organisationId
248
+ });
249
+ return data === true;
250
+ }
251
+
252
+ // supabase/functions/my-function/index.ts
253
+ import { checkPermission } from '../_shared/rbac.ts';
254
+
255
+ const hasPermission = await checkPermission(supabase, user.id, 'read:dashboard', orgId);
256
+ ```
257
+
258
+ **After (✅ CORRECT):**
259
+ ```typescript
260
+ // supabase/functions/my-function/index.ts
261
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
262
+
263
+ // Setup RBAC once
264
+ setupRBAC(supabase);
265
+
266
+ // Use pace-core API directly
267
+ const hasPermission = await isPermitted({
268
+ userId: user.id,
269
+ scope: { organisationId: orgId },
270
+ permission: 'read:dashboard',
271
+ pageId: 'dashboard'
272
+ });
273
+ ```
274
+
275
+ ### Step 3: Remove Custom Helper Files
276
+
277
+ After migrating all Edge Functions:
278
+ ```bash
279
+ # Remove custom RBAC helper file
280
+ rm supabase/functions/_shared/rbac.ts
281
+ ```
282
+
283
+ ### Step 4: Update All Edge Functions
284
+
285
+ Update each Edge Function to:
286
+ 1. Import `setupRBAC` and `isPermitted` from pace-core
287
+ 2. Call `setupRBAC(supabase)` before permission checks
288
+ 3. Use `isPermitted()` with complete `PermissionCheck` input
289
+ 4. Remove imports of custom RBAC helpers
290
+
291
+ ## Common Mistakes
292
+
293
+ ### ❌ Mistake 1: Calling RPC Directly
294
+
295
+ ```typescript
296
+ // ❌ FORBIDDEN
297
+ const { data } = await supabase.rpc('rbac_check_permission_simplified', {
298
+ p_user_id: userId,
299
+ p_permission: 'read:dashboard'
300
+ });
301
+ ```
302
+
303
+ **Fix:**
304
+ ```typescript
305
+ // ✅ CORRECT
306
+ setupRBAC(supabase);
307
+ const hasPermission = await isPermitted({
308
+ userId,
309
+ scope: { organisationId },
310
+ permission: 'read:dashboard'
311
+ });
312
+ ```
313
+
314
+ ### ❌ Mistake 2: Forgetting to Setup RBAC
315
+
316
+ ```typescript
317
+ // ❌ FORBIDDEN - Missing setupRBAC
318
+ import { isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
319
+
320
+ const hasPermission = await isPermitted({ ... }); // Will fail!
321
+ ```
322
+
323
+ **Fix:**
324
+ ```typescript
325
+ // ✅ CORRECT
326
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
327
+
328
+ setupRBAC(supabase); // MUST be called first
329
+ const hasPermission = await isPermitted({ ... });
330
+ ```
331
+
332
+ ### ❌ Mistake 3: Missing Organisation Context
333
+
334
+ ```typescript
335
+ // ❌ FORBIDDEN - Missing organisationId
336
+ const hasPermission = await isPermitted({
337
+ userId: user.id,
338
+ scope: {}, // Missing organisationId
339
+ permission: 'read:dashboard'
340
+ });
341
+ ```
342
+
343
+ **Fix:**
344
+ ```typescript
345
+ // ✅ CORRECT
346
+ const organisationId = req.headers.get('x-organisation-id');
347
+ if (!organisationId) {
348
+ return new Response(JSON.stringify({ error: 'Organisation context required' }), { status: 400 });
349
+ }
350
+
351
+ const hasPermission = await isPermitted({
352
+ userId: user.id,
353
+ scope: { organisationId },
354
+ permission: 'read:dashboard'
355
+ });
356
+ ```
357
+
358
+ ## Verification Checklist
359
+
360
+ Before deploying Edge Functions, verify:
361
+
362
+ - [ ] `setupRBAC(supabase)` is called before any permission checks
363
+ - [ ] `isPermitted()` is used instead of custom helpers
364
+ - [ ] No direct calls to `rbac_check_permission_simplified` RPC
365
+ - [ ] Organisation context is extracted from request
366
+ - [ ] User authentication is verified before permission checks
367
+ - [ ] Error handling for missing auth/context
368
+ - [ ] No custom RBAC helper files exist
369
+ - [ ] All Edge Functions follow the correct pattern
370
+
371
+ ## Related Documentation
372
+
373
+ - [RBAC Compliance Guide](../standards/09-rbac-compliance.md) - Complete compliance rules
374
+ - [RBAC API Reference](./api-reference.md) - Complete API documentation
375
+ - [RBAC Quick Start](./quick-start.md) - Getting started guide
376
+
@@ -229,38 +229,6 @@ function MyComponent() {
229
229
  }
230
230
  ```
231
231
 
232
- ## Audit Script Detection
233
-
234
- The pace-core audit script comprehensively detects insecure client usage:
235
-
236
- ```bash
237
- npm run audit
238
- ```
239
-
240
- The audit will report violations including:
241
- - ✅ Direct `createClient` imports from `@supabase/supabase-js`
242
- - ✅ Direct `createClient()` function calls
243
- - ✅ Usage of non-secure clients for database queries (`.from()` calls)
244
- - ✅ Files that import `createClient` but don't use `useSecureSupabase()`
245
- - ✅ Variables created with `createClient()` that are used for queries
246
-
247
- **Example audit output**:
248
- ```
249
- ❌ Direct Supabase client usage detected
250
- File: src/components/UserList.tsx
251
- Line: 15
252
- Variable: supabase
253
- Table: users
254
- Reason: Direct Supabase client usage detected. Variable 'supabase' is created with createClient() and used for database queries. You MUST use useSecureSupabase() instead to ensure RLS policies and organisation context are enforced.
255
- Recommendation: Replace with: import { useSecureSupabase } from '@jmruthers/pace-core/rbac'; const supabase = useSecureSupabase();
256
- ```
257
-
258
- The audit tool provides the same level of detection as the ESLint rule, making it useful for:
259
- - Pre-commit checks
260
- - CI/CD pipelines
261
- - Code reviews
262
- - Migration validation
263
-
264
232
  ## Best Practices
265
233
 
266
234
  1. **Always use `useSecureSupabase()`** in React components
@@ -268,7 +236,6 @@ The audit tool provides the same level of detection as the ESLint rule, making i
268
236
  3. **Never import `createClient`** from `@supabase/supabase-js` in component files
269
237
  4. **Verify client security** in critical code paths (optional but recommended)
270
238
  5. **Run ESLint** regularly to catch violations early
271
- 6. **Run audit script** before deploying to catch any missed violations
272
239
 
273
240
  ## Troubleshooting
274
241
 
@@ -324,7 +291,6 @@ The protection system provides:
324
291
  - ✅ **Runtime warnings** to alert developers in development mode
325
292
  - ✅ **Type safety** to verify client security
326
293
  - ✅ **Automatic marking** of secure clients
327
- - ✅ **Audit scripts** to catch violations before deployment
328
294
 
329
295
  By following these guidelines, you ensure that all database operations respect organisation context and RLS policies, preventing security vulnerabilities and data leakage.
330
296