@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
@@ -7,6 +7,61 @@ rulesVersion: "2025-01-28"
7
7
  ---
8
8
  # Markup Quality Guide
9
9
 
10
+ **📚 Human-Readable Standard**: See [5-styling-standards.md](../../packages/core/docs/standards/5-styling-standards.md) for complete documentation including **CRITICAL CSS configuration requirements**.
11
+
12
+ **⚠️ IMPORTANT**: This rule is ALWAYS APPLIED. The standard includes required CSS setup that MUST be followed for pace-core components to render correctly.
13
+
14
+ ## AI Agent Instructions
15
+
16
+ **When writing or modifying code, ALWAYS:**
17
+ 1. **Use pace-core components** - Never use native HTML elements when pace-core provides components
18
+ 2. **Use semantic HTML** - Always use semantic elements (`<main>`, `<section>`, `<article>`, etc.) instead of `<div>` wrappers
19
+ 3. **Never use inline styles** - Never use `style={{...}}`, always use pace-core components or Tailwind classes
20
+ 4. **Use Grid for layout** - Prefer CSS Grid over Flexbox for centering, two-dimensional layouts, and full-page layouts
21
+ 5. **Minimize elements** - Use the fewest elements possible, prefer React Fragments over wrapper divs
22
+ 6. **Check CSS setup** - Before using pace-core components, verify CSS is configured correctly (see checklist below)
23
+
24
+ **Decision Tree: Markup & Styling**
25
+ ```
26
+ 1. What element should I use?
27
+ ├─ Button → <Button> from pace-core (not <button>)
28
+ ├─ Input → <Input> from pace-core (not <input>)
29
+ ├─ Page wrapper → <main> (not <div>)
30
+ ├─ Section → <section> (not <div>)
31
+ ├─ Article → <article> (not <div>)
32
+ └─ Navigation → <nav> (not <div>)
33
+
34
+ 2. Do I need a wrapper?
35
+ ├─ For React single root → Use Fragment (<>...</>)
36
+ ├─ For styling only → Apply to existing semantic parent
37
+ └─ For layout → Use Grid (grid place-items-center, grid grid-cols-*)
38
+
39
+ 3. How do I center content?
40
+ ├─ Both axes → grid place-items-center
41
+ └─ Single axis → flex (but prefer grid)
42
+
43
+ 4. Am I using inline styles?
44
+ ├─ YES → WRONG - Use pace-core component or Tailwind class
45
+ └─ NO → Continue
46
+ ```
47
+
48
+ ## ⚠️ CRITICAL: CSS Configuration Required
49
+
50
+ **Before using pace-core components, you MUST configure CSS correctly.** Without proper configuration, pace-core components will appear unstyled or with incorrect styling.
51
+
52
+ **MUST read the standard for complete CSS setup instructions**: [5-styling-standards.md](../../packages/core/docs/standards/5-styling-standards.md)
53
+
54
+ **Quick checklist:**
55
+ - [ ] `src/app.css` exists with `@import "tailwindcss";`
56
+ - [ ] `@source` directives configured correctly (relative to CSS file location)
57
+ - [ ] `@import "@jmruthers/pace-core/styles/core.css";` in `app.css`
58
+ - [ ] All three color palettes defined (main, sec, acc) with all shades (50-950)
59
+ - [ ] `app.css` imported in `main.tsx` (NOT `core.css` directly)
60
+
61
+ **See the standard for detailed setup instructions and troubleshooting.**
62
+
63
+ ---
64
+
10
65
  This guide enforces clean markup standards, semantic HTML usage, and proper pace-core component patterns to ensure maintainable, accessible, and consistent code.
11
66
 
12
67
  ## pace-core First
@@ -17,18 +72,29 @@ This guide enforces clean markup standards, semantic HTML usage, and proper pace
17
72
 
18
73
  ```tsx
19
74
  // ❌ WRONG: Custom button or native HTML element
20
- <button className="btn-primary">Click me</button>
21
- <input type="text" className="form-input" />
75
+ <button className="btn-primary" onClick={handleClick}>
76
+ Click me
77
+ </button>
78
+ <input
79
+ type="text"
80
+ className="form-input"
81
+ value={value}
82
+ onChange={handleChange}
83
+ />
22
84
 
23
85
  // ✅ CORRECT: Use pace-core components
24
86
  import { Button, Input } from '@jmruthers/pace-core';
25
- <Button>Click me</Button>
26
- <Input type="text" />
87
+ <Button onClick={handleClick}>Click me</Button>
88
+ <Input
89
+ type="text"
90
+ value={value}
91
+ onChange={handleChange}
92
+ />
27
93
  ```
28
94
 
29
95
  ### MUST NOT: Add Custom Styles to pace-core Components
30
96
 
31
- **MUST NOT add custom styles when pace-core components already provide styling:**
97
+ **NEVER add custom styles when pace-core components already provide styling. Use component variants/props instead.**
32
98
 
33
99
  ```tsx
34
100
  // ❌ WRONG: Overriding pace-core component styles
@@ -88,41 +154,45 @@ import { Button, Input } from '@jmruthers/pace-core';
88
154
  <footer>Footer</footer>
89
155
  ```
90
156
 
91
- ### MUST NOT: Use `<div>` Elements
157
+ ### MUST: Prefer Semantic HTML (Limit `<div>`)
158
+
159
+ **ALWAYS prefer semantic HTML elements** (`<main>`, `<section>`, `<article>`, `<header>`, `<footer>`, `<nav>`, lists, etc.).
160
+ Using semantic elements improves accessibility, maintainability, and consistency.
92
161
 
93
- **MUST NOT use `<div>` elements (except for the first child of `<body>` in `index.html`, React portals, or when required by third-party libraries that mandate specific DOM structure):**
162
+ #### `<div>` usage policy
163
+
164
+ - **MUST NOT** use `<div>` when a clear semantic element exists.
165
+ - `<div>` is **allowed only** for:
166
+ - purely presentational layout wrappers (flex/grid grouping) when no semantic element fits, OR
167
+ - React portal roots / app shell roots, OR
168
+ - third-party libraries that require specific DOM structure (document the reason in a short comment).
169
+
170
+ #### Severity guidance (for audits)
171
+
172
+ - **HIGH/BLOCKER**: `<div>` used in place of landmark/semantic structure (e.g., main page wrapper that should be `<main>`, navigation that should be `<nav>`, lists that should be `<ul>/<ol>`).
173
+ - **MEDIUM**: `<div>` used as a generic wrapper inside semantic structure where it could be a fragment or semantic element.
174
+ - **LOW**: `<div>` used for unavoidable third-party structure with a comment justifying it.
175
+
176
+ **Examples:**
94
177
 
95
178
  ```tsx
96
- // ❌ WRONG: Using div elements
97
- <div className="container">
98
- <div className="content">Content</div>
179
+ // ❌ WRONG: Non-semantic page structure
180
+ <div className="page">
181
+ <div className="nav">...</div>
182
+ <div className="content">...</div>
99
183
  </div>
100
184
 
101
- // ✅ CORRECT: Use semantic elements or React Fragments
185
+ // ✅ CORRECT: Semantic structure
102
186
  <main>
103
- <section>Content</section>
187
+ <nav>...</nav>
188
+ <section>...</section>
104
189
  </main>
105
- // Or for grouping without semantic meaning:
106
- <>
107
- <Component1 />
108
- <Component2 />
109
- </>
110
- ```
111
-
112
- ### MUST: Choose Most Semantic Element
113
190
 
114
- **MUST choose the most semantically accurate element for the content:**
115
-
116
- ```tsx
117
- // CORRECT: Choose appropriate semantic elements
118
- <main>Main content</main>
119
- <section>Section of content</section>
120
- <article>Article content</article>
121
- <header>Header content</header>
122
- <footer>Footer content</footer>
123
- <nav>Navigation</nav>
124
- <ul><li>List items</li></ul>
125
- <p>Paragraph text</p>
191
+ // ACCEPTABLE: Layout-only wrapper (no semantic fit)
192
+ // (Prefer fragments where possible)
193
+ <section>
194
+ <div className="flex gap-2">...</div>
195
+ </section>
126
196
  ```
127
197
 
128
198
  ## Typography & Styling
@@ -445,8 +515,8 @@ Before committing code, verify:
445
515
 
446
516
  ## Reference
447
517
 
448
- - **pace-core Components**: See `00-pace-core-compliance.mdc` for component usage
518
+ - **pace-core Components**: See [01-pace-core-compliance.mdc](./01-pace-core-compliance.mdc) for component usage
449
519
  - **Semantic HTML**: https://developer.mozilla.org/en-US/docs/Glossary/Semantics
450
520
  - **React Fragments**: https://react.dev/reference/react/Fragment
451
- - **Accessibility**: See `06-code-quality.mdc` for accessibility requirements
521
+ - **Accessibility**: See [04-code-quality.mdc](./04-code-quality.mdc) for accessibility requirements
452
522
  - **When in doubt**: Remove the element, remove the style, and rely on pace-core or semantic HTML
@@ -0,0 +1,518 @@
1
+ ---
2
+ description: Enforce RBAC contract compliance, RLS policy patterns, and security requirements
3
+ globs: ["src/**/*.{ts,tsx,js,jsx}", "supabase/migrations/**/*.sql"]
4
+ alwaysApply: false
5
+ paceCoreVersion: "0.6.x"
6
+ rulesVersion: "2025-01-28"
7
+ ---
8
+ # Security & RBAC Standards Guide
9
+
10
+ **📚 Human-Readable Standard**: See [6-security-rbac-standards.md](../../packages/core/docs/standards/6-security-rbac-standards.md) for complete documentation including RLS policy patterns, helper functions, and security requirements.
11
+
12
+ This guide enforces the **mandatory RBAC contract** and security patterns between pace-core and consuming apps.
13
+
14
+ **⚠️ CRITICAL**: This contract is **non-negotiable**. See [RBAC Contract](../../packages/core/docs/rbac/RBAC_CONTRACT.md) for complete documentation.
15
+
16
+ ## AI Agent Instructions
17
+
18
+ **When writing or modifying code, ALWAYS:**
19
+ 1. **Protect all pages** - Wrap every protected page with `PagePermissionGuard` (no exceptions)
20
+ 2. **Use pace-core hooks directly** - Never create wrapper functions around `useCan` or `useResourcePermissions`
21
+ 3. **Use RESOURCE_NAMES constants** - Never use string literals in `useResourcePermissions` calls
22
+ 4. **Validate all inputs** - Always validate user input with Zod schemas before processing
23
+ 5. **Never expose internals** - Never show SQL errors, stack traces, or internal details to users
24
+ 6. **Use helper functions in RLS** - Always use STABLE SECURITY DEFINER helper functions, never subqueries
25
+ 7. **Sanitize logs** - Never log passwords, tokens, or sensitive data
26
+
27
+ **Decision Tree: Security & Permissions**
28
+ ```
29
+ 1. Is this a protected page?
30
+ ├─ YES → Wrap with PagePermissionGuard (no exceptions)
31
+ └─ NO → Continue
32
+
33
+ 2. Do I need to check permissions?
34
+ ├─ YES → Use pace-core hooks directly (useCan, useResourcePermissions)
35
+ └─ NO → Continue
36
+
37
+ 3. Am I handling user input?
38
+ ├─ YES → Validate with Zod schema
39
+ └─ NO → Continue
40
+
41
+ 4. Am I logging or showing errors?
42
+ ├─ YES → Never expose internals, sanitize sensitive data
43
+ └─ NO → Continue
44
+ ```
45
+
46
+ ## MUST: Use PagePermissionGuard for All Protected Pages
47
+
48
+ **MUST wrap all protected pages with `PagePermissionGuard`:**
49
+
50
+ ```tsx
51
+ // ✅ CORRECT
52
+ import { PagePermissionGuard } from '@jmruthers/pace-core/rbac';
53
+
54
+ function DashboardPage() {
55
+ return (
56
+ <PagePermissionGuard pageName="dashboard" operation="read">
57
+ <DashboardContent />
58
+ </PagePermissionGuard>
59
+ );
60
+ }
61
+ ```
62
+
63
+ **MUST NOT:**
64
+ - Render protected content without `PagePermissionGuard`
65
+ - Create wrapper components around `PagePermissionGuard`
66
+ - Bypass page-level permission checks
67
+
68
+ ```tsx
69
+ // ❌ FORBIDDEN - No guard
70
+ function DashboardPage() {
71
+ return <DashboardContent />; // ERROR: Unprotected page
72
+ }
73
+
74
+ // ❌ FORBIDDEN - Wrapper component
75
+ function EventPageGuard({ pageName, children }) {
76
+ return <PagePermissionGuard pageName={pageName}>{children}</PagePermissionGuard>;
77
+ }
78
+ ```
79
+
80
+ ## MUST: Use pace-core Permission Hooks Directly
81
+
82
+ **MUST use pace-core hooks directly without wrappers:**
83
+
84
+ ```tsx
85
+ // ✅ CORRECT
86
+ import { useCan, useResourcePermissions } from '@jmruthers/pace-core/rbac';
87
+ import { RESOURCE_NAMES } from '@/config/resource-names';
88
+
89
+ function MyComponent() {
90
+ const { canUpdate, canDelete } = useResourcePermissions(RESOURCE_NAMES.JOURNAL);
91
+ const canEdit = useCan(userId, scope, 'update:users');
92
+ // Use canUpdate, canDelete, canEdit directly
93
+ }
94
+ ```
95
+
96
+ **MUST NOT:**
97
+ - Create wrapper functions around permission hooks
98
+ - Create custom permission utility functions
99
+ - Use string literals in `useResourcePermissions` calls
100
+
101
+ ```tsx
102
+ // ❌ FORBIDDEN - Wrapper function
103
+ const canEdit = (postId: string) => {
104
+ const hasPermission = canUpdate('journal');
105
+ const post = posts.find(p => p.id === postId);
106
+ return hasPermission && !!post;
107
+ };
108
+
109
+ // ❌ FORBIDDEN - Custom utility
110
+ function checkPermission(permission: string) {
111
+ // Custom logic...
112
+ }
113
+
114
+ // ❌ FORBIDDEN - String literal
115
+ const { canUpdate } = useResourcePermissions('journal');
116
+ ```
117
+
118
+ ## MUST: Use RESOURCE_NAMES Constants
119
+
120
+ **MUST use `RESOURCE_NAMES` constant object for all resource permission checks:**
121
+
122
+ ```tsx
123
+ // ✅ CORRECT
124
+ import { RESOURCE_NAMES } from '@/config/resource-names';
125
+ const { canCreate, canUpdate, canDelete } = useResourcePermissions(RESOURCE_NAMES.JOURNAL);
126
+ ```
127
+
128
+ **MUST NOT:**
129
+ - Use string literals in `useResourcePermissions` calls
130
+ - Hardcode resource names
131
+
132
+ ```tsx
133
+ // ❌ FORBIDDEN - String literal
134
+ const { canUpdate } = useResourcePermissions('journal');
135
+ ```
136
+
137
+ ## MUST: Use Standard AccessDenied Component
138
+
139
+ **MUST use `AccessDenied` from pace-core for all access denied scenarios:**
140
+
141
+ ```tsx
142
+ // ✅ CORRECT
143
+ import { AccessDenied } from '@jmruthers/pace-core/rbac';
144
+
145
+ <PagePermissionGuard
146
+ pageName="dashboard"
147
+ operation="read"
148
+ fallback={<AccessDenied />}
149
+ >
150
+ <DashboardContent />
151
+ </PagePermissionGuard>
152
+ ```
153
+
154
+ **MUST NOT:**
155
+ - Create custom access denied components
156
+ - Use custom permission denied components
157
+
158
+ ```tsx
159
+ // ❌ FORBIDDEN - Custom component
160
+ function CustomAccessDenied() {
161
+ return <div>Access Denied</div>;
162
+ }
163
+ ```
164
+
165
+ ## MUST: Use pace-core API for Permission Checks
166
+
167
+ **MUST use pace-core API functions for programmatic permission checks:**
168
+
169
+ ```tsx
170
+ // ✅ CORRECT
171
+ import { isPermitted, isPermittedCached } from '@jmruthers/pace-core/rbac';
172
+
173
+ const hasAccess = await isPermitted({
174
+ userId: 'user-123',
175
+ scope: { organisationId: 'org-456' },
176
+ permission: 'read:dashboard',
177
+ pageId: 'dashboard'
178
+ });
179
+ ```
180
+
181
+ **MUST NOT:**
182
+ - Call RBAC RPC functions directly
183
+ - Query RBAC tables directly (without `useSecureSupabase`)
184
+ - Create custom RBAC helper functions
185
+
186
+ ```tsx
187
+ // ❌ FORBIDDEN - Direct RPC call
188
+ const { data } = await supabase.rpc('rbac_check_permission_simplified', {
189
+ p_user_id: userId,
190
+ p_permission: 'read:dashboard'
191
+ });
192
+
193
+ // ❌ FORBIDDEN - Direct table query
194
+ const { data } = await supabase
195
+ .from('rbac_user_profiles')
196
+ .select('*');
197
+
198
+ // ❌ FORBIDDEN - Custom RBAC helper
199
+ function checkPermission(userId: string, permission: string) {
200
+ // Custom logic that bypasses pace-core
201
+ }
202
+ ```
203
+
204
+ ## MUST: Use pace-core API in Edge Functions (No Exceptions)
205
+
206
+ **Edge Functions (Deno serverless functions) MUST use pace-core's `isPermitted()` API function.** Edge Functions cannot use React hooks, but pace-core provides programmatic APIs that work outside React.
207
+
208
+ **✅ CORRECT - Edge Function Pattern:**
209
+
210
+ ```typescript
211
+ // supabase/functions/my-function/index.ts
212
+ import { createClient } from 'jsr:@supabase/supabase-js@2';
213
+ import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
214
+
215
+ Deno.serve(async (req: Request) => {
216
+ // 1. Create Supabase client from request headers
217
+ const authHeader = req.headers.get('Authorization');
218
+ if (!authHeader) {
219
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
220
+ }
221
+
222
+ const supabase = createClient(
223
+ Deno.env.get('SUPABASE_URL') ?? '',
224
+ Deno.env.get('SUPABASE_ANON_KEY') ?? '',
225
+ {
226
+ global: {
227
+ headers: { Authorization: authHeader },
228
+ },
229
+ }
230
+ );
231
+
232
+ // 2. Get user from session
233
+ const { data: { user } } = await supabase.auth.getUser();
234
+ if (!user) {
235
+ return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
236
+ }
237
+
238
+ // 3. Setup RBAC (required before using isPermitted)
239
+ setupRBAC(supabase);
240
+
241
+ // 4. Extract organisation context from request (headers, body, or query params)
242
+ const organisationId = req.headers.get('x-organisation-id') ||
243
+ (await req.json()).organisationId;
244
+
245
+ if (!organisationId) {
246
+ return new Response(JSON.stringify({ error: 'Organisation context required' }), { status: 400 });
247
+ }
248
+
249
+ // 5. Check permission using pace-core API
250
+ const hasPermission = await isPermitted({
251
+ userId: user.id,
252
+ scope: { organisationId },
253
+ permission: 'read:dashboard',
254
+ pageId: 'dashboard'
255
+ });
256
+
257
+ if (!hasPermission) {
258
+ return new Response(JSON.stringify({ error: 'Permission denied' }), { status: 403 });
259
+ }
260
+
261
+ // 6. Proceed with function logic
262
+ return new Response(JSON.stringify({ success: true }));
263
+ });
264
+ ```
265
+
266
+ **❌ FORBIDDEN - Custom RBAC Helper in Edge Functions:**
267
+
268
+ ```typescript
269
+ // ❌ FORBIDDEN - Creating custom RBAC helper
270
+ // supabase/functions/_shared/rbac.ts
271
+ export async function checkPermission(userId: string, permission: string) {
272
+ // Custom logic that bypasses pace-core
273
+ const { data } = await supabase.rpc('rbac_check_permission_simplified', {
274
+ p_user_id: userId,
275
+ p_permission: permission
276
+ });
277
+ return data;
278
+ }
279
+ ```
280
+
281
+ **Why No Exceptions:**
282
+ - pace-core provides `isPermitted()` API that works outside React
283
+ - `setupRBAC()` initializes the engine with a Supabase client
284
+ - No custom helpers needed - use pace-core APIs directly
285
+ - Custom helpers bypass security validation, caching, and audit logging
286
+
287
+ **Edge Function Requirements:**
288
+ 1. **MUST** call `setupRBAC(supabase)` before using `isPermitted()`
289
+ 2. **MUST** extract `userId` from Supabase auth session
290
+ 3. **MUST** extract `organisationId` from request (headers, body, or query params)
291
+ 4. **MUST** use `isPermitted()` with complete `PermissionCheck` input
292
+ 5. **MUST NOT** create custom RBAC helper functions
293
+ 6. **MUST NOT** call `rbac_check_permission_simplified` RPC directly
294
+
295
+ ## MUST: Use useSecureSupabase for RBAC Table Queries
296
+
297
+ **If you must query RBAC tables (rare), MUST use `useSecureSupabase`:**
298
+
299
+ ```tsx
300
+ // ✅ CORRECT
301
+ import { useSecureSupabase } from '@jmruthers/pace-core/rbac';
302
+
303
+ function MyComponent() {
304
+ const secureSupabase = useSecureSupabase();
305
+ // If your hook signature requires a client argument, pass ONLY the pace-core-provided client (never a local createClient()).
306
+ const { data } = await secureSupabase
307
+ .from('rbac_user_profiles') // Allowed through secure client
308
+ .select('*');
309
+ }
310
+ ```
311
+
312
+ **MUST NOT query these tables directly:**
313
+ - `rbac_organisation_roles`
314
+ - `rbac_event_app_roles`
315
+ - `rbac_global_roles`
316
+ - `rbac_apps`
317
+ - `rbac_app_pages`
318
+ - `rbac_page_permissions`
319
+ - `rbac_user_profiles`
320
+
321
+ ## MUST NOT: Use Hardcoded Role Checks
322
+
323
+ **MUST NOT compare roles directly:**
324
+
325
+ ```tsx
326
+ // ❌ FORBIDDEN - Hardcoded role check
327
+ if (user.role === 'admin') {
328
+ // ...
329
+ }
330
+ ```
331
+
332
+ **MUST use pace-core APIs:**
333
+
334
+ ```tsx
335
+ // ✅ CORRECT
336
+ import { useAccessLevel, getRoleContext } from '@jmruthers/pace-core/rbac';
337
+
338
+ const { accessLevel } = useAccessLevel(userId, scope);
339
+ const roleContext = await getRoleContext({ userId, scope });
340
+ ```
341
+
342
+ ## MUST: Configure enforcePermissions Correctly
343
+
344
+ **For event-based apps (where pages handle their own checks):**
345
+
346
+ ```tsx
347
+ // ✅ CORRECT - Event-based app pattern
348
+ <PaceAppLayout
349
+ appName="MyApp"
350
+ enforcePermissions={false} // Pages handle checks via PagePermissionGuard
351
+ // ...
352
+ >
353
+ ```
354
+
355
+ **For organisation-based apps (where layout handles checks):**
356
+
357
+ ```tsx
358
+ // ✅ CORRECT - Organisation-based app pattern
359
+ <PaceAppLayout
360
+ appName="MyApp"
361
+ enforcePermissions={true} // Layout handles checks
362
+ defaultPermission="read"
363
+ // ...
364
+ >
365
+ ```
366
+
367
+ ## MUST: Setup RBAC Before Use
368
+
369
+ **MUST call `setupRBAC()` before any RBAC usage:**
370
+
371
+ ```tsx
372
+ // main.tsx - MUST be first
373
+ import { setupRBAC } from '@jmruthers/pace-core/rbac';
374
+ setupRBAC(supabase);
375
+ // Then render app
376
+ ```
377
+
378
+ ## Enforcement
379
+
380
+ These rules are enforced by ESLint rules (all ERROR severity):
381
+
382
+ 1. **`no-direct-rbac-rpc`** - Detects direct calls to `rbac_check_permission_simplified`
383
+ 2. **`no-direct-rbac-tables`** - Detects direct queries to RBAC tables
384
+ 3. **`no-bypass-page-guard`** - Detects routes without `PagePermissionGuard`
385
+ 4. **`no-custom-access-denied`** - Detects custom access denied components
386
+ 5. **`no-hardcoded-role-checks`** - Detects hardcoded role comparisons
387
+ 6. **`no-custom-permission-utilities`** - Detects custom permission utility functions
388
+ 7. **`no-resource-permission-string-literals`** - Detects string literals in `useResourcePermissions` calls
389
+ 8. **`no-permission-wrapper-functions`** - Detects wrapper functions around pace-core permission hooks
390
+
391
+ ## Common Mistakes to Avoid
392
+
393
+ **When writing code, NEVER:**
394
+ 1. **Skip PagePermissionGuard** - Every protected page must be wrapped
395
+ ```tsx
396
+ // ❌ WRONG
397
+ function DashboardPage() {
398
+ return <DashboardContent />;
399
+ }
400
+
401
+ // ✅ CORRECT
402
+ function DashboardPage() {
403
+ return (
404
+ <PagePermissionGuard pageName="dashboard" operation="read">
405
+ <DashboardContent />
406
+ </PagePermissionGuard>
407
+ );
408
+ }
409
+ ```
410
+
411
+ 2. **Create wrapper functions around permission hooks** - Use hooks directly
412
+ 3. **Use string literals in useResourcePermissions** - Always use RESOURCE_NAMES constants
413
+ 4. **Bypass input validation** - Always validate with Zod schemas
414
+ 5. **Expose internal errors** - Never show SQL, stack traces, or file paths to users
415
+ 6. **Log sensitive data** - Never log passwords, tokens, or PII
416
+
417
+ ## Compliance Checklist
418
+
419
+ Before committing RBAC-related code, verify:
420
+
421
+ - [ ] All protected pages use `PagePermissionGuard`
422
+ - [ ] No wrapper components around `PagePermissionGuard`
423
+ - [ ] No wrapper functions around permission hooks
424
+ - [ ] All `useResourcePermissions` calls use `RESOURCE_NAMES` constants
425
+ - [ ] No direct RPC calls to `rbac_check_permission_simplified`
426
+ - [ ] No direct queries to RBAC tables (use `useSecureSupabase` if needed)
427
+ - [ ] No hardcoded role checks (use `useAccessLevel` or `getRoleContext`)
428
+ - [ ] No custom permission utility functions
429
+ - [ ] All access denied scenarios use `AccessDenied` from pace-core
430
+ - [ ] `enforcePermissions` configured correctly for app type
431
+ - [ ] `setupRBAC()` called before any RBAC usage
432
+ - [ ] Edge Functions use `isPermitted()` API (no custom RBAC helpers)
433
+ - [ ] All RLS policies for authenticated users include super-admin checks
434
+ - [ ] All `is_super_admin()` calls use explicit parameter (`safe_get_user_id_for_rls()`)
435
+ - [ ] No security-critical functions use fallback strategies
436
+ - [ ] ESLint rules pass without errors
437
+
438
+ ## MUST: Include Super-Admin Checks in RLS Policies
439
+
440
+ **MUST include super-admin bypass in all RLS policies for authenticated users:**
441
+
442
+ ```sql
443
+ -- ✅ CORRECT: Super-admin check included
444
+ CREATE POLICY "rbac_select_table_name" ON table_name
445
+ FOR SELECT TO authenticated
446
+ USING (
447
+ organisation_id IS NOT NULL
448
+ AND (
449
+ is_super_admin(safe_get_user_id_for_rls())
450
+ OR check_user_organisation_access(organisation_id)
451
+ )
452
+ );
453
+ ```
454
+
455
+ **MUST NOT:**
456
+ - Create RLS policies without super-admin checks (except for public/anonymous policies)
457
+ - Use `is_super_admin()` without a parameter (relies on fallback strategies)
458
+ - Create security-critical functions with fallback strategies
459
+
460
+ ```sql
461
+ -- ❌ FORBIDDEN: Missing super-admin check
462
+ CREATE POLICY "rbac_select_table_name" ON table_name
463
+ FOR SELECT TO authenticated
464
+ USING (
465
+ check_user_organisation_access(organisation_id)
466
+ );
467
+
468
+ -- ❌ FORBIDDEN: is_super_admin() without parameter
469
+ CREATE POLICY "rbac_select_table_name" ON table_name
470
+ FOR SELECT TO authenticated
471
+ USING (
472
+ is_super_admin() -- Missing parameter, uses fallback strategies
473
+ OR check_user_organisation_access(organisation_id)
474
+ );
475
+ ```
476
+
477
+ **MUST use explicit parameter passing:**
478
+
479
+ ```sql
480
+ -- ✅ CORRECT: Explicit user ID parameter
481
+ is_super_admin(safe_get_user_id_for_rls())
482
+ ```
483
+
484
+ **MUST NOT create security-critical functions with fallback strategies:**
485
+
486
+ ```sql
487
+ -- ❌ FORBIDDEN: Multiple fallback strategies
488
+ CREATE FUNCTION is_super_admin(p_user_id UUID DEFAULT NULL)
489
+ RETURNS boolean AS $$
490
+ BEGIN
491
+ IF p_user_id IS NOT NULL THEN
492
+ v_user_id := p_user_id;
493
+ ELSE
494
+ v_user_id := auth.uid(); -- Fallback 1
495
+ END IF;
496
+ -- More fallbacks...
497
+ END;
498
+ $$;
499
+
500
+ -- ✅ CORRECT: Required parameter, no fallbacks
501
+ CREATE FUNCTION is_super_admin(p_user_id UUID)
502
+ RETURNS boolean AS $$
503
+ BEGIN
504
+ IF p_user_id IS NULL THEN
505
+ RETURN false; -- Fail secure
506
+ END IF;
507
+ -- Check super-admin status
508
+ END;
509
+ $$;
510
+ ```
511
+
512
+ ## Reference
513
+
514
+ - **RBAC Contract**: `packages/core/docs/rbac/RBAC_CONTRACT.md` - Complete contract documentation
515
+ - **Migration Guide**: `packages/core/docs/rbac/MIGRATION_GUIDE.md` - Migrating to RBAC Contract v2.0.0
516
+ - **Quick Start**: `packages/core/docs/rbac/quick-start.md` - Getting started guide
517
+ - **API Reference**: `packages/core/docs/rbac/api-reference.md` - Complete API documentation
518
+ - **RLS Standards**: [6-security-rbac-standards.md](../../packages/core/docs/standards/6-security-rbac-standards.md) - RLS policy patterns and super-admin requirements