@jmruthers/pace-core 0.6.5 → 0.6.7

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 (473) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/audit-tool/00-dependencies.cjs +394 -0
  4. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  5. package/audit-tool/audits/02-project-structure.cjs +255 -0
  6. package/audit-tool/audits/03-architecture.cjs +196 -0
  7. package/audit-tool/audits/04-code-quality.cjs +149 -0
  8. package/audit-tool/audits/05-styling.cjs +224 -0
  9. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  10. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  11. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  12. package/audit-tool/audits/09-operations.cjs +208 -0
  13. package/audit-tool/index.cjs +291 -0
  14. package/audit-tool/utils/code-utils.cjs +218 -0
  15. package/audit-tool/utils/file-utils.cjs +230 -0
  16. package/audit-tool/utils/report-utils.cjs +241 -0
  17. package/core-usage-manifest.json +93 -0
  18. package/cursor-rules/00-standards-overview.mdc +156 -0
  19. package/cursor-rules/01-pace-core-compliance.mdc +586 -0
  20. package/cursor-rules/02-project-structure.mdc +42 -4
  21. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
  22. package/cursor-rules/04-code-quality.mdc +419 -0
  23. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
  24. package/cursor-rules/06-security-rbac.mdc +518 -0
  25. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  26. package/cursor-rules/08-testing-documentation.mdc +324 -0
  27. package/cursor-rules/09-operations.mdc +365 -0
  28. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  29. package/dist/DataTable-7PMH7XN7.js +15 -0
  30. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  31. package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
  32. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  33. package/dist/api-Y4MQWOFW.js +4 -0
  34. package/dist/audit-MYQXYZFU.js +3 -0
  35. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  36. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  37. package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
  38. package/dist/chunk-6F3IILHI.js +62 -0
  39. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  40. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  41. package/dist/{chunk-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
  42. package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
  43. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  44. package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
  45. package/dist/chunk-C7NSAPTL.js +1 -0
  46. package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
  47. package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
  48. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  49. package/dist/chunk-GHYHJTYV.js +994 -0
  50. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  51. package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
  52. package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
  53. package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
  54. package/dist/chunk-MBADTM7L.js +64 -0
  55. package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
  56. package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
  57. package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
  58. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  59. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  60. package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
  61. package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
  62. package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
  63. package/dist/components.d.ts +7 -5
  64. package/dist/components.js +46 -257
  65. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  66. package/dist/eslint-rules/index.cjs +35 -0
  67. package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
  68. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  69. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  70. package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
  71. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  72. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  73. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  74. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  75. package/dist/hooks.d.ts +6 -6
  76. package/dist/hooks.js +62 -172
  77. package/dist/icons/index.d.ts +1 -0
  78. package/dist/icons/index.js +1 -0
  79. package/dist/index.d.ts +12 -11
  80. package/dist/index.js +67 -660
  81. package/dist/providers.d.ts +2 -2
  82. package/dist/providers.js +8 -35
  83. package/dist/rbac/eslint-rules.d.ts +46 -44
  84. package/dist/rbac/eslint-rules.js +7 -4
  85. package/dist/rbac/index.d.ts +109 -586
  86. package/dist/rbac/index.js +14 -207
  87. package/dist/styles/index.js +2 -12
  88. package/dist/theming/runtime.d.ts +14 -1
  89. package/dist/theming/runtime.js +3 -19
  90. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  91. package/dist/{types-CkbwOr4Y.d.ts → types-DXstZpNI.d.ts} +4 -17
  92. package/dist/types-t9H8qKRw.d.ts +55 -0
  93. package/dist/types.d.ts +1 -1
  94. package/dist/types.js +7 -94
  95. package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
  96. package/dist/utils.d.ts +24 -117
  97. package/dist/utils.js +54 -392
  98. package/docs/README.md +17 -7
  99. package/docs/api/README.md +4 -402
  100. package/docs/api/modules.md +301 -871
  101. package/docs/api-reference/components.md +21 -21
  102. package/docs/api-reference/deprecated.md +31 -6
  103. package/docs/api-reference/hooks.md +80 -80
  104. package/docs/api-reference/rpc-functions.md +78 -3
  105. package/docs/api-reference/types.md +1 -1
  106. package/docs/api-reference/utilities.md +1 -1
  107. package/docs/architecture/README.md +1 -1
  108. package/docs/core-concepts/events.md +3 -3
  109. package/docs/core-concepts/organisations.md +6 -6
  110. package/docs/core-concepts/permissions.md +6 -6
  111. package/docs/documentation-index.md +12 -18
  112. package/docs/getting-started/cursor-rules.md +3 -23
  113. package/docs/getting-started/dependencies.md +650 -0
  114. package/docs/getting-started/documentation-index.md +1 -1
  115. package/docs/getting-started/examples/README.md +4 -4
  116. package/docs/getting-started/examples/full-featured-app.md +1 -1
  117. package/docs/getting-started/faq.md +2 -2
  118. package/docs/getting-started/installation-guide.md +20 -7
  119. package/docs/getting-started/quick-reference.md +4 -4
  120. package/docs/getting-started/quick-start.md +23 -12
  121. package/docs/implementation-guides/authentication.md +15 -15
  122. package/docs/implementation-guides/component-styling.md +1 -1
  123. package/docs/implementation-guides/data-tables.md +126 -33
  124. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  125. package/docs/implementation-guides/dynamic-colors.md +3 -3
  126. package/docs/implementation-guides/file-upload-storage.md +2 -2
  127. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  128. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  129. package/docs/implementation-guides/large-datasets.md +3 -2
  130. package/docs/implementation-guides/organisation-security.md +2 -2
  131. package/docs/implementation-guides/performance.md +2 -2
  132. package/docs/implementation-guides/permission-enforcement.md +5 -1
  133. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  134. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  135. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  136. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  137. package/docs/rbac/README.md +17 -8
  138. package/docs/rbac/advanced-patterns.md +6 -6
  139. package/docs/rbac/api-reference.md +20 -20
  140. package/docs/rbac/edge-functions-guide.md +376 -0
  141. package/docs/rbac/event-based-apps.md +3 -3
  142. package/docs/rbac/examples.md +41 -41
  143. package/docs/rbac/getting-started.md +37 -37
  144. package/docs/rbac/performance.md +1 -1
  145. package/docs/rbac/quick-start.md +52 -52
  146. package/docs/rbac/secure-client-protection.md +1 -35
  147. package/docs/rbac/troubleshooting.md +1 -1
  148. package/docs/security/README.md +5 -5
  149. package/docs/standards/0-standards-overview.md +220 -0
  150. package/docs/standards/1-pace-core-compliance-standards.md +986 -0
  151. package/docs/standards/2-project-structure-standards.md +949 -0
  152. package/docs/standards/3-architecture-standards.md +606 -0
  153. package/docs/standards/4-code-quality-standards.md +728 -0
  154. package/docs/standards/5-styling-standards.md +348 -0
  155. package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
  156. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  157. package/docs/standards/8-testing-documentation-standards.md +401 -0
  158. package/docs/standards/9-operations-standards.md +1102 -0
  159. package/docs/standards/README.md +185 -57
  160. package/docs/troubleshooting/README.md +4 -4
  161. package/docs/troubleshooting/common-issues.md +2 -2
  162. package/docs/troubleshooting/debugging.md +9 -9
  163. package/docs/troubleshooting/migration.md +4 -4
  164. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  165. package/eslint-config-pace-core.cjs +33 -6
  166. package/package.json +35 -23
  167. package/scripts/install-cursor-rules.cjs +25 -6
  168. package/scripts/install-eslint-config.cjs +284 -0
  169. package/src/__tests__/fixtures/supabase.ts +1 -1
  170. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
  171. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  172. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  173. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  174. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
  175. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  176. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  177. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  178. package/src/__tests__/public-recipe-view.test.ts +38 -9
  179. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  180. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  181. package/src/__tests__/templates/component.test.template.tsx +18 -15
  182. package/src/components/Button/Button.tsx +5 -1
  183. package/src/components/Calendar/Calendar.tsx +201 -47
  184. package/src/components/ContextSelector/ContextSelector.tsx +106 -119
  185. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  186. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  187. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  188. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  189. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  190. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  191. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  192. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  193. package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
  194. package/src/components/DataTable/components/EditFields.tsx +23 -3
  195. package/src/components/DataTable/components/EditableRow.tsx +12 -9
  196. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  197. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  198. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  199. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  200. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  201. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  202. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  203. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  204. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  205. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  206. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  207. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  208. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  209. package/src/components/DataTable/components/index.ts +2 -1
  210. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  212. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  213. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  214. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  215. package/src/components/DataTable/types.ts +5 -18
  216. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  217. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  218. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  219. package/src/components/DateTimeField/DateTimeField.tsx +10 -9
  220. package/src/components/Dialog/Dialog.test.tsx +128 -104
  221. package/src/components/Dialog/Dialog.tsx +742 -24
  222. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  223. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
  224. package/src/components/FileDisplay/FileDisplay.tsx +23 -17
  225. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  226. package/src/components/FileUpload/FileUpload.tsx +112 -130
  227. package/src/components/Form/Form.test.tsx +6 -8
  228. package/src/components/Form/Form.tsx +365 -4
  229. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  230. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  231. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  232. package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
  233. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  234. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  235. package/src/components/Progress/Progress.tsx +2 -4
  236. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  237. package/src/components/Select/Select.tsx +109 -98
  238. package/src/components/Select/types.ts +4 -1
  239. package/src/components/UserMenu/UserMenu.tsx +9 -6
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
  242. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  243. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  244. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  245. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  246. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  247. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  248. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  249. package/src/hooks/public/usePublicEvent.ts +67 -195
  250. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  251. package/src/hooks/public/usePublicEventLogo.ts +24 -14
  252. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  253. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  254. package/src/hooks/useAppConfig.ts +28 -26
  255. package/src/hooks/useEventTheme.test.ts +217 -239
  256. package/src/hooks/useEventTheme.ts +16 -28
  257. package/src/hooks/useFileDisplay.ts +2 -2
  258. package/src/hooks/useOrganisationPermissions.ts +5 -7
  259. package/src/hooks/useQueryCache.ts +0 -1
  260. package/src/hooks/useSessionDraft.ts +380 -0
  261. package/src/hooks/useSessionRestoration.ts +3 -1
  262. package/src/icons/index.ts +27 -0
  263. package/src/index.ts +5 -0
  264. package/src/providers/OrganisationProvider.tsx +23 -14
  265. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  266. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  267. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  268. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  269. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  270. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  271. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  272. package/src/providers/services/EventServiceProvider.tsx +1 -24
  273. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  274. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  275. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
  276. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  277. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  278. package/src/rbac/adapters.tsx +7 -295
  279. package/src/rbac/api.test.ts +44 -56
  280. package/src/rbac/api.ts +10 -17
  281. package/src/rbac/cache-invalidation.ts +0 -1
  282. package/src/rbac/compliance/index.ts +10 -0
  283. package/src/rbac/compliance/pattern-detector.ts +553 -0
  284. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  285. package/src/rbac/components/AccessDenied.tsx +150 -0
  286. package/src/rbac/components/NavigationGuard.tsx +12 -20
  287. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  289. package/src/rbac/components/index.ts +3 -41
  290. package/src/rbac/eslint-rules.js +1 -1
  291. package/src/rbac/hooks/index.ts +0 -3
  292. package/src/rbac/hooks/permissions/index.ts +0 -3
  293. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  294. package/src/rbac/hooks/usePermissions.ts +0 -3
  295. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  296. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  297. package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
  298. package/src/rbac/hooks/useResourcePermissions.ts +139 -48
  299. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  300. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  301. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  302. package/src/rbac/index.ts +7 -9
  303. package/src/rbac/utils/contextValidator.ts +9 -7
  304. package/src/services/AuthService.ts +130 -18
  305. package/src/services/EventService.ts +4 -97
  306. package/src/services/InactivityService.ts +16 -0
  307. package/src/services/OrganisationService.ts +7 -44
  308. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  309. package/src/services/base/BaseService.ts +0 -3
  310. package/src/styles/core.css +7 -0
  311. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  312. package/src/theming/parseEventColours.ts +22 -10
  313. package/src/types/database.generated.ts +4733 -3809
  314. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  315. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  316. package/src/utils/context/organisationContext.test.ts +13 -28
  317. package/src/utils/context/organisationContext.ts +21 -52
  318. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  319. package/src/utils/file-reference/index.ts +39 -15
  320. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  321. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  322. package/src/utils/index.ts +4 -1
  323. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  324. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  325. package/src/utils/persistence/keyDerivation.ts +304 -0
  326. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  327. package/src/utils/security/secureStorage.ts +5 -5
  328. package/src/utils/storage/README.md +1 -1
  329. package/src/utils/storage/helpers.ts +3 -3
  330. package/src/utils/supabase/createBaseClient.ts +147 -0
  331. package/src/utils/timezone/timezone.test.ts +1 -2
  332. package/src/utils/timezone/timezone.ts +1 -1
  333. package/src/utils/validation/csrf.ts +4 -4
  334. package/cursor-rules/00-pace-core-compliance.mdc +0 -331
  335. package/cursor-rules/01-standards-compliance.mdc +0 -244
  336. package/cursor-rules/04-testing-standards.mdc +0 -268
  337. package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
  338. package/cursor-rules/06-code-quality.mdc +0 -309
  339. package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
  340. package/cursor-rules/CHANGELOG.md +0 -119
  341. package/cursor-rules/README.md +0 -192
  342. package/dist/DataTable-AOVNCPTX.js +0 -175
  343. package/dist/DataTable-AOVNCPTX.js.map +0 -1
  344. package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
  345. package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
  346. package/dist/api-O6HTBX5Y.js +0 -52
  347. package/dist/api-O6HTBX5Y.js.map +0 -1
  348. package/dist/audit-V53FV5AG.js +0 -17
  349. package/dist/audit-V53FV5AG.js.map +0 -1
  350. package/dist/chunk-5DRSZLL2.js.map +0 -1
  351. package/dist/chunk-63FOKYGO.js.map +0 -1
  352. package/dist/chunk-6COVEUS7.js.map +0 -1
  353. package/dist/chunk-AFVQODI2.js +0 -263
  354. package/dist/chunk-AFVQODI2.js.map +0 -1
  355. package/dist/chunk-DGUM43GV.js.map +0 -1
  356. package/dist/chunk-E66EQZE6.js.map +0 -1
  357. package/dist/chunk-EFN2EIMK.js.map +0 -1
  358. package/dist/chunk-FFQEQTNW.js.map +0 -1
  359. package/dist/chunk-FMUCXFII.js.map +0 -1
  360. package/dist/chunk-G37KK66H.js.map +0 -1
  361. package/dist/chunk-G7QEZTYQ.js +0 -2053
  362. package/dist/chunk-G7QEZTYQ.js.map +0 -1
  363. package/dist/chunk-HU2C6SSC.js.map +0 -1
  364. package/dist/chunk-IHB5DR3H.js.map +0 -1
  365. package/dist/chunk-IVOFDYWT.js.map +0 -1
  366. package/dist/chunk-J36DSWQK.js.map +0 -1
  367. package/dist/chunk-JGRYX5UX.js.map +0 -1
  368. package/dist/chunk-KQCRWDSA.js +0 -1
  369. package/dist/chunk-KQCRWDSA.js.map +0 -1
  370. package/dist/chunk-L4OXEN46.js.map +0 -1
  371. package/dist/chunk-LMC26NLJ.js +0 -84
  372. package/dist/chunk-LMC26NLJ.js.map +0 -1
  373. package/dist/chunk-M43Y4SSO.js.map +0 -1
  374. package/dist/chunk-M7MPQISP.js.map +0 -1
  375. package/dist/chunk-NTM7ZSB6.js.map +0 -1
  376. package/dist/chunk-PWLANIRT.js.map +0 -1
  377. package/dist/chunk-QXHPKYJV.js.map +0 -1
  378. package/dist/chunk-RGAWHO7N.js.map +0 -1
  379. package/dist/chunk-UPPMRMYG.js.map +0 -1
  380. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  381. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  382. package/dist/components.js.map +0 -1
  383. package/dist/contextValidator-5OGXSPKS.js +0 -9
  384. package/dist/contextValidator-5OGXSPKS.js.map +0 -1
  385. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  386. package/dist/hooks.js.map +0 -1
  387. package/dist/index.js.map +0 -1
  388. package/dist/providers.js.map +0 -1
  389. package/dist/rbac/eslint-rules.js.map +0 -1
  390. package/dist/rbac/index.js.map +0 -1
  391. package/dist/styles/index.js.map +0 -1
  392. package/dist/theming/runtime.js.map +0 -1
  393. package/dist/types.js.map +0 -1
  394. package/dist/utils.js.map +0 -1
  395. package/docs/best-practices/README.md +0 -472
  396. package/docs/best-practices/accessibility.md +0 -601
  397. package/docs/best-practices/common-patterns.md +0 -516
  398. package/docs/best-practices/deployment.md +0 -1103
  399. package/docs/best-practices/performance.md +0 -1328
  400. package/docs/best-practices/security.md +0 -940
  401. package/docs/best-practices/testing.md +0 -1034
  402. package/docs/rbac/compliance/compliance-guide.md +0 -544
  403. package/docs/standards/01-architecture-standard.md +0 -44
  404. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  405. package/docs/standards/03-component-standard.md +0 -32
  406. package/docs/standards/04-code-style-standard.md +0 -32
  407. package/docs/standards/05-security-standard.md +0 -44
  408. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  409. package/docs/standards/pace-core-compliance.md +0 -432
  410. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  411. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  412. package/scripts/audit/core/checks/bundle.cjs +0 -142
  413. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  414. package/scripts/audit/core/checks/config.cjs +0 -54
  415. package/scripts/audit/core/checks/coverage.cjs +0 -84
  416. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  417. package/scripts/audit/core/checks/documentation.cjs +0 -268
  418. package/scripts/audit/core/checks/environment.cjs +0 -116
  419. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  420. package/scripts/audit/core/checks/forms.cjs +0 -172
  421. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  422. package/scripts/audit/core/checks/hooks.cjs +0 -334
  423. package/scripts/audit/core/checks/imports.cjs +0 -244
  424. package/scripts/audit/core/checks/performance.cjs +0 -325
  425. package/scripts/audit/core/checks/routes.cjs +0 -117
  426. package/scripts/audit/core/checks/state.cjs +0 -130
  427. package/scripts/audit/core/checks/structure.cjs +0 -65
  428. package/scripts/audit/core/checks/style.cjs +0 -584
  429. package/scripts/audit/core/checks/testing.cjs +0 -122
  430. package/scripts/audit/core/checks/typescript.cjs +0 -61
  431. package/scripts/audit/core/scanner.cjs +0 -199
  432. package/scripts/audit/core/utils.cjs +0 -137
  433. package/scripts/audit/index.cjs +0 -223
  434. package/scripts/audit/reporters/console.cjs +0 -151
  435. package/scripts/audit/reporters/json.cjs +0 -54
  436. package/scripts/audit/reporters/markdown.cjs +0 -124
  437. package/scripts/audit-consuming-app.cjs +0 -86
  438. package/src/components/DataTable/components/DataTableBody.tsx +0 -454
  439. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  440. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  441. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  442. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  443. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  444. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  445. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  446. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  447. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  448. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  449. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  450. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  451. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  452. package/src/components/DataTable/utils/debugTools.ts +0 -514
  453. package/src/eslint-rules/pace-core-compliance.js +0 -638
  454. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  455. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  456. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  457. package/src/rbac/components/NavigationProvider.tsx +0 -345
  458. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  459. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  460. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  461. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  462. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  463. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  464. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  465. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  466. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  467. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  468. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  469. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  470. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  471. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  472. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  473. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -0,0 +1,819 @@
1
+ ---
2
+ lastUpdated: 2025-01-04T00:00:00+00:00
3
+ version: 2.0.0
4
+ reviewedBy: rbac-architecture-review
5
+ ---
6
+
7
+ # RBAC Migration Guide
8
+
9
+ > **🔄 Migrating to RBAC Contract v2.0.0** | [← Back to RBAC Documentation](./README.md) | [RBAC Contract](./RBAC_CONTRACT.md)
10
+
11
+ This guide helps you migrate your consuming application to comply with the RBAC Contract v2.0.0.
12
+
13
+ ## Breaking Changes
14
+
15
+ ### 1. RBAC Package Surface Area Reduction
16
+
17
+ **What Changed:**
18
+ - Removed redundant and overlapping RBAC exports to enforce a single correct pattern
19
+ - Reduced API surface area by ~40-50%
20
+ - All removed functionality has clear migration paths
21
+
22
+ **Impact:**
23
+ - Code using removed components/hooks/APIs will fail to build
24
+ - Must migrate to the minimal, canonical API
25
+
26
+ **Migration:**
27
+
28
+ #### Components Removed
29
+
30
+ **PermissionEnforcer → PagePermissionGuard**
31
+
32
+ ```tsx
33
+ // ❌ OLD
34
+ import { PermissionEnforcer } from '@jmruthers/pace-core/rbac';
35
+
36
+ <PermissionEnforcer permissions={['read:events']} operation="event-management">
37
+ <Content />
38
+ </PermissionEnforcer>
39
+
40
+ // ✅ NEW
41
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
42
+
43
+ <PagePermissionGuard pageName="events" operation="read">
44
+ <Content />
45
+ </PagePermissionGuard>
46
+ ```
47
+
48
+ **PermissionGuard (from adapters) → PagePermissionGuard**
49
+
50
+ ```tsx
51
+ // ❌ OLD
52
+ import { PermissionGuard } from '@jmruthers/pace-core/rbac';
53
+
54
+ <PermissionGuard permission="update:events" scope={{ organisationId: 'org-123' }}>
55
+ <Content />
56
+ </PermissionGuard>
57
+
58
+ // ✅ NEW
59
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
60
+
61
+ <PagePermissionGuard pageName="events" operation="update">
62
+ <Content />
63
+ </PagePermissionGuard>
64
+ ```
65
+
66
+ **AccessLevelGuard → useAccessLevel Hook**
67
+
68
+ ```tsx
69
+ // ❌ OLD
70
+ import { AccessLevelGuard } from '@jmruthers/pace-core/rbac';
71
+
72
+ <AccessLevelGuard minLevel="admin" scope={{ organisationId: 'org-123' }}>
73
+ <AdminPanel />
74
+ </AccessLevelGuard>
75
+
76
+ // ✅ NEW
77
+ import { useAccessLevel } from '@jmruthers/pace-core/rbac';
78
+
79
+ function AdminPanel() {
80
+ const { accessLevel } = useAccessLevel();
81
+
82
+ if (accessLevel !== 'admin' && accessLevel !== 'super') {
83
+ return <AccessDenied />;
84
+ }
85
+
86
+ return <AdminPanelContent />;
87
+ }
88
+ ```
89
+
90
+ **RoleBasedRouter → PagePermissionGuard + React Router**
91
+
92
+ ```tsx
93
+ // ❌ OLD
94
+ import { RoleBasedRouter } from '@jmruthers/pace-core/rbac';
95
+
96
+ <RoleBasedRouter routes={routeConfig}>
97
+ <App />
98
+ </RoleBasedRouter>
99
+
100
+ // ✅ NEW
101
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
102
+ import { Routes, Route } from 'react-router-dom';
103
+
104
+ <Routes>
105
+ <Route path="/dashboard" element={
106
+ <PagePermissionGuard pageName="dashboard" operation="read">
107
+ <Dashboard />
108
+ </PagePermissionGuard>
109
+ } />
110
+ </Routes>
111
+ ```
112
+
113
+ **EnhancedNavigationMenu → NavigationMenu + NavigationGuard**
114
+
115
+ ```tsx
116
+ // ❌ OLD
117
+ import { EnhancedNavigationMenu } from '@jmruthers/pace-core/rbac';
118
+
119
+ <EnhancedNavigationMenu items={items} />
120
+
121
+ // ✅ NEW
122
+ import { NavigationMenu, NavigationGuard } from '@jmruthers/pace-core';
123
+
124
+ <NavigationMenu>
125
+ {items.map(item => (
126
+ <NavigationGuard key={item.id} permission={item.permission}>
127
+ <NavigationItem {...item} />
128
+ </NavigationGuard>
129
+ ))}
130
+ </NavigationMenu>
131
+ ```
132
+
133
+ **Context Providers Removed**
134
+
135
+ All context providers have been removed. Use components/hooks directly:
136
+
137
+ ```tsx
138
+ // ❌ OLD
139
+ import { PagePermissionProvider, SecureDataProvider, NavigationProvider } from '@jmruthers/pace-core/rbac';
140
+
141
+ <PagePermissionProvider>
142
+ <SecureDataProvider>
143
+ <NavigationProvider>
144
+ <App />
145
+ </NavigationProvider>
146
+ </SecureDataProvider>
147
+ </PagePermissionProvider>
148
+
149
+ // ✅ NEW - No providers needed, use components/hooks directly
150
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
151
+ import { useSecureSupabase } from '@jmruthers/pace-core/rbac';
152
+
153
+ // Use PagePermissionGuard in routes
154
+ // Use useSecureSupabase hook in components that need secure client
155
+ ```
156
+
157
+ #### Hooks Removed
158
+
159
+ **useHasAnyPermission → useMultiplePermissions**
160
+
161
+ ```tsx
162
+ // ❌ OLD
163
+ import { useHasAnyPermission } from '@jmruthers/pace-core/rbac';
164
+
165
+ const hasAny = useHasAnyPermission(['read:events', 'read:users']);
166
+
167
+ // ✅ NEW
168
+ import { useMultiplePermissions } from '@jmruthers/pace-core/rbac';
169
+
170
+ const { permissions } = useMultiplePermissions(['read:events', 'read:users']);
171
+ const hasAny = Object.values(permissions).some(Boolean);
172
+ ```
173
+
174
+ **useHasAllPermissions → useMultiplePermissions**
175
+
176
+ ```tsx
177
+ // ❌ OLD
178
+ import { useHasAllPermissions } from '@jmruthers/pace-core/rbac';
179
+
180
+ const hasAll = useHasAllPermissions(['read:events', 'update:events']);
181
+
182
+ // ✅ NEW
183
+ import { useMultiplePermissions } from '@jmruthers/pace-core/rbac';
184
+
185
+ const { permissions } = useMultiplePermissions(['read:events', 'update:events']);
186
+ const hasAll = Object.values(permissions).every(Boolean);
187
+ ```
188
+
189
+ **useCachedPermissions → Automatic Caching**
190
+
191
+ ```tsx
192
+ // ❌ OLD
193
+ import { useCachedPermissions } from '@jmruthers/pace-core/rbac';
194
+
195
+ const cached = useCachedPermissions(['read:events']);
196
+
197
+ // ✅ NEW - Caching is automatic in all hooks
198
+ import { useCan } from '@jmruthers/pace-core/rbac';
199
+
200
+ const can = useCan('read:events'); // Automatically cached
201
+ ```
202
+
203
+ #### API Functions Removed
204
+
205
+ **hasPermission → isPermitted**
206
+
207
+ ```tsx
208
+ // ❌ OLD
209
+ import { hasPermission } from '@jmruthers/pace-core/rbac';
210
+
211
+ const hasAccess = await hasPermission({
212
+ permission: 'read:events',
213
+ pageName: 'events'
214
+ });
215
+
216
+ // ✅ NEW
217
+ import { isPermitted } from '@jmruthers/pace-core/rbac';
218
+
219
+ const hasAccess = await isPermitted({
220
+ permission: 'read:events',
221
+ pageName: 'events'
222
+ });
223
+ ```
224
+
225
+ **Cache-only helpers → Automatic Caching**
226
+
227
+ ```tsx
228
+ // ❌ OLD
229
+ import { hasPermissionCached, hasAnyPermissionCached } from '@jmruthers/pace-core/rbac';
230
+
231
+ const cached = hasPermissionCached(userId, scope, 'read:events');
232
+ const anyCached = hasAnyPermissionCached(userId, scope, ['read:events', 'read:users']);
233
+
234
+ // ✅ NEW - Use hooks or API with automatic caching
235
+ import { useCan, useMultiplePermissions } from '@jmruthers/pace-core/rbac';
236
+ import { isPermittedCached } from '@jmruthers/pace-core/rbac';
237
+
238
+ // In components (automatic caching)
239
+ const can = useCan('read:events');
240
+
241
+ // In API/server code
242
+ const cached = await isPermittedCached({
243
+ permission: 'read:events',
244
+ pageName: 'events'
245
+ });
246
+ ```
247
+
248
+ #### Internal Exports
249
+
250
+ The following exports are now marked as `@internal` and should not be used by consuming apps:
251
+
252
+ - `RBACEngine`, `createRBACEngine` → Use `isPermitted` API instead
253
+ - `RBACCache`, `rbacCache`, `CACHE_PATTERNS` → Caching is automatic
254
+ - `SecureSupabaseClient`, `createSecureClient`, `fromSupabaseClient` → Use `useSecureSupabase` hook instead
255
+
256
+ **Migration Steps:**
257
+
258
+ 1. **Search for removed exports:**
259
+ ```bash
260
+ grep -r "PermissionEnforcer\|PermissionGuard\|AccessLevelGuard\|RoleBasedRouter\|EnhancedNavigationMenu\|PagePermissionProvider\|SecureDataProvider\|NavigationProvider\|useHasAnyPermission\|useHasAllPermissions\|useCachedPermissions\|hasPermission\|hasPermissionCached\|hasAnyPermissionCached" src/
261
+ ```
262
+
263
+ 2. **Replace with canonical alternatives** (see examples above)
264
+
265
+ 3. **Remove internal export usage:**
266
+ ```bash
267
+ grep -r "RBACEngine\|createRBACEngine\|RBACCache\|rbacCache\|CACHE_PATTERNS\|SecureSupabaseClient\|createSecureClient\|fromSupabaseClient" src/
268
+ ```
269
+ Replace with public APIs/hooks
270
+
271
+ 4. **Verify build:**
272
+ ```bash
273
+ npm run build
274
+ ```
275
+
276
+ ### 2. ESLint Rules Now ERROR (Not Warning)
277
+
278
+ **What Changed:**
279
+ - All RBAC compliance ESLint rules are now **ERROR** severity
280
+ - Builds will fail if violations are detected
281
+ - No more warnings - violations must be fixed
282
+
283
+ **Impact:**
284
+ - Existing code with violations will fail to build
285
+ - Must fix all violations before deployment
286
+
287
+ **Migration:**
288
+ 1. Run ESLint to identify violations:
289
+ ```bash
290
+ npm run lint
291
+ ```
292
+ 2. Fix all violations (see sections below)
293
+ 3. Verify build passes:
294
+ ```bash
295
+ npm run build
296
+ ```
297
+
298
+ ### 2. EventPageGuard Wrapper Pattern Removed
299
+
300
+ **What Changed:**
301
+ - `EventPageGuard` wrapper components are **forbidden**
302
+ - Must use `PagePermissionGuard` directly
303
+ - Event context validation should be in page components
304
+
305
+ **Before:**
306
+
307
+ ```tsx
308
+ // ❌ OLD PATTERN - Remove this
309
+ import { EventPageGuard } from '@/components/permissions';
310
+
311
+ function DashboardPage() {
312
+ return (
313
+ <EventPageGuard pageName={PAGE_NAMES.DASHBOARD}>
314
+ <DashboardContent />
315
+ </EventPageGuard>
316
+ );
317
+ }
318
+ ```
319
+
320
+ **After:**
321
+
322
+ ```tsx
323
+ // ✅ NEW PATTERN - Use this
324
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
325
+ import { useEvents } from '@jmruthers/pace-core';
326
+ import { EventSelectionPrompt } from '@/components/permissions/EventSelectionPrompt';
327
+
328
+ function DashboardPage() {
329
+ const { selectedEvent } = useEvents();
330
+
331
+ // Handle event context validation in page
332
+ if (!selectedEvent) {
333
+ return <EventSelectionPrompt />;
334
+ }
335
+
336
+ return (
337
+ <PagePermissionGuard pageName={PAGE_NAMES.DASHBOARD} operation="read">
338
+ <DashboardContent />
339
+ </PagePermissionGuard>
340
+ );
341
+ }
342
+ ```
343
+
344
+ **Migration Steps:**
345
+
346
+ 1. **Remove EventPageGuard component:**
347
+ ```bash
348
+ rm src/components/permissions/EventPageGuard.tsx
349
+ ```
350
+
351
+ 2. **Update all imports:**
352
+ ```tsx
353
+ // Remove
354
+ import { EventPageGuard } from '@/components/permissions';
355
+
356
+ // Add
357
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
358
+ ```
359
+
360
+ 3. **Replace all usages:**
361
+ - Replace `<EventPageGuard pageName="...">` with `<PagePermissionGuard pageName="..." operation="read">`
362
+ - Add event context validation in page components
363
+ - Add `operation` prop (usually `"read"`)
364
+
365
+ 4. **Update index exports:**
366
+ ```tsx
367
+ // src/components/permissions/index.ts
368
+ // Remove EventPageGuard export
369
+ // export { EventPageGuard } from './EventPageGuard';
370
+ ```
371
+
372
+ ### 3. Custom AccessDenied Components No Longer Allowed
373
+
374
+ **What Changed:**
375
+ - Custom access denied components are **forbidden**
376
+ - Must use `AccessDenied` from pace-core
377
+ - Ensures consistent UX across all apps
378
+
379
+ **Before:**
380
+
381
+ ```tsx
382
+ // ❌ OLD PATTERN - Remove this
383
+ function CustomAccessDenied() {
384
+ return (
385
+ <div>
386
+ <h2>Access Denied</h2>
387
+ <p>You don't have permission.</p>
388
+ </div>
389
+ );
390
+ }
391
+
392
+ <PagePermissionGuard
393
+ pageName="dashboard"
394
+ fallback={<CustomAccessDenied />}
395
+ >
396
+ <DashboardContent />
397
+ </PagePermissionGuard>
398
+ ```
399
+
400
+ **After:**
401
+
402
+ ```tsx
403
+ // ✅ NEW PATTERN - Use this
404
+ import { AccessDenied } from '@jmruthers/pace-core/rbac';
405
+
406
+ <PagePermissionGuard
407
+ pageName="dashboard"
408
+ operation="read"
409
+ fallback={<AccessDenied />}
410
+ >
411
+ <DashboardContent />
412
+ </PagePermissionGuard>
413
+ ```
414
+
415
+ **Migration Steps:**
416
+
417
+ 1. **Remove custom access denied components:**
418
+ ```bash
419
+ rm src/components/permissions/CustomAccessDenied.tsx
420
+ rm src/components/permissions/StandardAccessDenied.tsx
421
+ # etc.
422
+ ```
423
+
424
+ 2. **Update imports:**
425
+ ```tsx
426
+ // Remove
427
+ import { CustomAccessDenied } from '@/components/permissions';
428
+
429
+ // Add
430
+ import { AccessDenied } from '@jmruthers/pace-core/rbac';
431
+ ```
432
+
433
+ 3. **Replace all usages:**
434
+ ```tsx
435
+ // Replace
436
+ fallback={<CustomAccessDenied />}
437
+
438
+ // With
439
+ fallback={<AccessDenied />}
440
+ ```
441
+
442
+ 4. **Customize if needed (via props):**
443
+ ```tsx
444
+ <AccessDenied
445
+ message="Custom message"
446
+ onGoBack={() => navigate('/dashboard')}
447
+ showSignOut={true}
448
+ />
449
+ ```
450
+
451
+ ### 4. Direct RBAC Table Queries Now Errors
452
+
453
+ **What Changed:**
454
+ - Direct queries to RBAC tables are **forbidden**
455
+ - Must use `useSecureSupabase` hook
456
+ - ESLint will error on violations
457
+
458
+ **Before:**
459
+
460
+ ```tsx
461
+ // ❌ OLD PATTERN - Remove this
462
+ const { data } = await supabase
463
+ .from('rbac_user_profiles')
464
+ .select('user_id, display_name')
465
+ .in('user_id', userIds);
466
+ ```
467
+
468
+ **After:**
469
+
470
+ ```tsx
471
+ // ✅ NEW PATTERN - Use this
472
+ import { useSecureSupabase } from '@jmruthers/pace-core/rbac';
473
+
474
+ function MyComponent() {
475
+ const secureSupabase = useSecureSupabase(supabase);
476
+
477
+ const { data } = await secureSupabase
478
+ .from('rbac_user_profiles')
479
+ .select('user_id, display_name')
480
+ .in('user_id', userIds);
481
+ }
482
+ ```
483
+
484
+ **Migration Steps:**
485
+
486
+ 1. **Find all direct RBAC table queries:**
487
+ ```bash
488
+ # Search for RBAC table queries
489
+ grep -r "\.from(['\"]rbac_" src/
490
+ ```
491
+
492
+ 2. **Update to use useSecureSupabase:**
493
+ - Import `useSecureSupabase` from `@jmruthers/pace-core/rbac`
494
+ - Call `useSecureSupabase(supabase)` in component
495
+ - Replace `supabase` with `secureSupabase` in queries
496
+
497
+ 3. **Verify queries work:**
498
+ - Test that queries still return expected data
499
+ - Verify security is maintained
500
+
501
+ ### 5. Direct RPC Calls Now Errors
502
+
503
+ **What Changed:**
504
+ - Direct calls to `rbac_check_permission_simplified` are **forbidden**
505
+ - Must use `isPermitted` from pace-core
506
+ - ESLint will error on violations
507
+
508
+ **Before:**
509
+
510
+ ```tsx
511
+ // ❌ OLD PATTERN - Remove this
512
+ const { data, error } = await supabase.rpc('rbac_check_permission_simplified', {
513
+ p_user_id: userId,
514
+ p_permission: 'read:dashboard',
515
+ p_organisation_id: orgId
516
+ });
517
+ ```
518
+
519
+ **After:**
520
+
521
+ ```tsx
522
+ // ✅ NEW PATTERN - Use this
523
+ import { isPermitted } from '@jmruthers/pace-core/rbac';
524
+
525
+ const hasAccess = await isPermitted({
526
+ permission: 'read:dashboard',
527
+ pageName: 'dashboard'
528
+ });
529
+ ```
530
+
531
+ **Migration Steps:**
532
+
533
+ 1. **Find all direct RPC calls:**
534
+ ```bash
535
+ # Search for RPC calls
536
+ grep -r "rbac_check_permission_simplified" src/
537
+ ```
538
+
539
+ 2. **Replace with isPermitted:**
540
+ - Import `isPermitted` from `@jmruthers/pace-core/rbac`
541
+ - Replace RPC call with `isPermitted` call
542
+ - Update permission format if needed
543
+
544
+ 3. **Verify permission checks work:**
545
+ - Test that permission checks return expected results
546
+ - Verify caching behavior is correct
547
+
548
+ ### 6. enforcePermissions Pattern Clarified
549
+
550
+ **What Changed:**
551
+ - `enforcePermissions` usage clarified for event-based apps
552
+ - Must be `false` for event-based apps
553
+ - Must be `true` for organisation-based apps
554
+
555
+ **Before (Event-Based Apps):**
556
+
557
+ ```tsx
558
+ // ❌ OLD PATTERN - May have been true
559
+ <PaceAppLayout
560
+ appName="MyApp"
561
+ enforcePermissions={true} // Wrong for event-based apps
562
+ showEvents={true}
563
+ >
564
+ ```
565
+
566
+ **After (Event-Based Apps):**
567
+
568
+ ```tsx
569
+ // ✅ NEW PATTERN - Must be false
570
+ <PaceAppLayout
571
+ appName="MyApp"
572
+ enforcePermissions={false} // Correct for event-based apps
573
+ showEvents={true}
574
+ >
575
+ ```
576
+
577
+ **Migration Steps:**
578
+
579
+ 1. **Identify app type:**
580
+ - Event-based: Uses events, pages handle checks
581
+ - Organisation-based: Uses organisations, layout handles checks
582
+
583
+ 2. **Update enforcePermissions:**
584
+ - Event-based apps: Set to `false`
585
+ - Organisation-based apps: Set to `true`
586
+
587
+ 3. **Verify behavior:**
588
+ - Test that pages are properly protected
589
+ - Verify no redundant permission checks
590
+
591
+ ## Step-by-Step Migration Checklist
592
+
593
+ ### Phase 1: Preparation
594
+
595
+ - [ ] Review [RBAC Contract](./RBAC_CONTRACT.md)
596
+ - [ ] Run ESLint: `npm run lint`
597
+ - [ ] Document current violations
598
+
599
+ ### Phase 2: Remove Wrapper Components
600
+
601
+ - [ ] Remove `EventPageGuard` component
602
+ - [ ] Update all imports
603
+ - [ ] Replace all `EventPageGuard` usages with `PagePermissionGuard`
604
+ - [ ] Add event context validation in pages
605
+ - [ ] Test all pages load correctly
606
+
607
+ ### Phase 3: Replace Custom Access Denied
608
+
609
+ - [ ] Remove custom access denied components
610
+ - [ ] Update imports to use `AccessDenied` from pace-core
611
+ - [ ] Replace all fallback props
612
+ - [ ] Customize via props if needed
613
+ - [ ] Test access denied scenarios
614
+
615
+ ### Phase 4: Fix Direct Queries
616
+
617
+ - [ ] Find all direct RBAC table queries
618
+ - [ ] Replace with `useSecureSupabase`
619
+ - [ ] Find all direct RPC calls
620
+ - [ ] Replace with `isPermitted`
621
+ - [ ] Test all queries work correctly
622
+
623
+ ### Phase 5: Remove Hardcoded Role Checks
624
+
625
+ - [ ] Find all hardcoded role comparisons (`role === 'admin'`, etc.)
626
+ - [ ] Replace with `useAccessLevel` hook or `getRoleContext` API
627
+ - [ ] Test role-based logic still works correctly
628
+
629
+ **Example Migration:**
630
+
631
+ ```tsx
632
+ // ❌ OLD
633
+ if (user.role === 'admin') {
634
+ // ...
635
+ }
636
+
637
+ // ✅ NEW
638
+ import { useAccessLevel } from '@jmruthers/pace-core/rbac';
639
+ const { accessLevel } = useAccessLevel();
640
+ if (accessLevel === 'admin') {
641
+ // ...
642
+ }
643
+ ```
644
+
645
+ ### Phase 6: Remove Custom Permission Utilities
646
+
647
+ - [ ] Find all custom permission utility functions (`checkPermission`, `hasPermission`, etc.)
648
+ - [ ] Replace with `isPermitted` API or `useCan` hook
649
+ - [ ] Test permission checks still work correctly
650
+
651
+ **Example Migration:**
652
+
653
+ ```tsx
654
+ // ❌ OLD
655
+ function checkPermission(userId, permission) {
656
+ // Custom logic...
657
+ }
658
+
659
+ // ✅ NEW
660
+ import { isPermitted } from '@jmruthers/pace-core/rbac';
661
+ const hasAccess = await isPermitted({ permission: 'read:dashboard' });
662
+ ```
663
+
664
+ ### Phase 7: Enforce Type-Safe Resource Names
665
+
666
+ - [ ] Create `RESOURCE_NAMES` constant object in your config
667
+ - [ ] Replace all `useResourcePermissions('string-literal')` with `RESOURCE_NAMES.CONSTANT`
668
+ - [ ] Update all permission checks to use constants
669
+ - [ ] Test all resource permissions still work
670
+
671
+ **Example Migration:**
672
+
673
+ ```tsx
674
+ // ❌ OLD
675
+ const { canCreate } = useResourcePermissions('journal');
676
+
677
+ // ✅ NEW
678
+ // 1. Create config/resource-names.ts
679
+ export const RESOURCE_NAMES = {
680
+ JOURNAL: 'journal',
681
+ RISKS: 'risks',
682
+ CONTACTS: 'contacts',
683
+ } as const;
684
+
685
+ // 2. Use in components
686
+ import { RESOURCE_NAMES } from '@/config/resource-names';
687
+ const { canCreate } = useResourcePermissions(RESOURCE_NAMES.JOURNAL);
688
+ ```
689
+
690
+ ### Phase 8: Remove Permission Wrapper Functions
691
+
692
+ - [ ] Find all permission wrapper functions (e.g., `canEdit(postId)`, `canDeletePost(postId)`)
693
+ - [ ] Remove wrapper functions from hooks
694
+ - [ ] Update components to use `useResourcePermissions` directly
695
+ - [ ] Test permission checks still work correctly
696
+
697
+ **Example Migration:**
698
+
699
+ ```tsx
700
+ // ❌ OLD - In hook
701
+ const canEdit = useCallback((postId: string) => {
702
+ const hasPermission = canUpdate('journal');
703
+ const post = posts.find(p => p.id === postId);
704
+ return hasPermission && !!post;
705
+ }, [posts, canUpdate]);
706
+
707
+ // ❌ OLD - In component
708
+ <JournalEntry canEdit={canEdit(post.id)} />
709
+
710
+ // ✅ NEW - In component
711
+ import { RESOURCE_NAMES } from '@/config/resource-names';
712
+ const { canUpdate } = useResourcePermissions(RESOURCE_NAMES.JOURNAL);
713
+ <JournalEntry canEdit={canUpdate(RESOURCE_NAMES.JOURNAL)} />
714
+ ```
715
+
716
+ ### Phase 9: Update Configuration
717
+
718
+ - [ ] Update `enforcePermissions` for app type
719
+ - [ ] Verify `PagePermissionGuard` on all pages
720
+ - [ ] Test permission enforcement works
721
+
722
+ ### Phase 10: Verification
723
+
724
+ - [ ] Run ESLint: `npm run lint`
725
+ - [ ] Run build: `npm run build`
726
+ - [ ] Test all pages and permission checks
727
+ - [ ] Verify no console errors
728
+
729
+ ## Common Issues and Solutions
730
+
731
+ ### Issue: "EventPageGuard is not defined"
732
+
733
+ **Solution:**
734
+ - Remove `EventPageGuard` import
735
+ - Use `PagePermissionGuard` from `@jmruthers/pace-core/rbac` instead
736
+
737
+ ### Issue: "AccessDenied is not defined"
738
+
739
+ **Solution:**
740
+ - Import `AccessDenied` from `@jmruthers/pace-core/rbac`
741
+ - Remove custom access denied components
742
+
743
+ ### Issue: "Direct query to RBAC table detected"
744
+
745
+ **Solution:**
746
+ - Use `useSecureSupabase` hook
747
+ - Replace `supabase` with `secureSupabase` in queries
748
+
749
+ ### Issue: "Direct RPC call detected"
750
+
751
+ **Solution:**
752
+ - Use `isPermitted` from `@jmruthers/pace-core/rbac`
753
+ - Replace RPC call with `isPermitted` call
754
+
755
+ ### Issue: "Route found without PagePermissionGuard"
756
+
757
+ **Solution:**
758
+ - Wrap all route components with `PagePermissionGuard`
759
+ - Add `operation` prop (usually `"read"`)
760
+
761
+ ### Issue: "Hardcoded role check detected"
762
+
763
+ **Solution:**
764
+ - Replace `user.role === 'admin'` with `useAccessLevel` hook
765
+ - Use `getRoleContext` API for programmatic checks
766
+
767
+ ### Issue: "Custom permission utility function detected"
768
+
769
+ **Solution:**
770
+ - Remove custom permission functions
771
+ - Use `isPermitted` API or `useCan` hook from pace-core
772
+
773
+ ### Issue: "Resource permission string literal detected"
774
+
775
+ **Solution:**
776
+ - Create `RESOURCE_NAMES` constant object
777
+ - Replace `useResourcePermissions('journal')` with `useResourcePermissions(RESOURCE_NAMES.JOURNAL)`
778
+
779
+ ### Issue: "Permission wrapper function detected"
780
+
781
+ **Solution:**
782
+ - Remove wrapper functions from hooks
783
+ - Use `useResourcePermissions` directly in components
784
+
785
+ ## Timeline
786
+
787
+ **Recommended migration order:**
788
+
789
+ 1. **Week 1**: Remove wrapper components (EventPageGuard)
790
+ 2. **Week 2**: Replace custom access denied components
791
+ 3. **Week 3**: Fix direct queries and RPC calls
792
+ 4. **Week 4**: Remove hardcoded role checks and custom permission utilities
793
+ 5. **Week 5**: Enforce type-safe resource names and remove wrapper functions
794
+ 6. **Week 6**: Update configuration and verify
795
+
796
+ **Total estimated time:** 4-6 weeks depending on codebase size
797
+
798
+ ## Getting Help
799
+
800
+ If you encounter issues during migration:
801
+
802
+ 1. Review [RBAC Contract](./RBAC_CONTRACT.md) for contract details
803
+ 2. Check [Troubleshooting Guide](./troubleshooting.md) for common issues
804
+ 3. Review [Examples](./examples.md) for migration patterns
805
+ 4. Check [API Reference](./api-reference.md) for API details
806
+
807
+ ## Related Documentation
808
+
809
+ - [RBAC Contract](./RBAC_CONTRACT.md) - The definitive contract
810
+ - [RBAC README](./README.md) - Overview and quick start
811
+ - [Quick Start Guide](./quick-start.md) - Step-by-step setup
812
+ - [Event-Based Apps](./event-based-apps.md) - Event-based app patterns
813
+ - [Permission Enforcement](../implementation-guides/permission-enforcement.md) - Detailed enforcement patterns
814
+
815
+ ---
816
+
817
+ **Last Updated**: 2025-01-04
818
+ **Version**: 2.0.0
819
+