@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,377 @@
1
+ ---
2
+ description: Enforce tech stack compliance, API/RPC naming conventions, and Vite configuration patterns
3
+ globs: ["src/**/*.{ts,tsx,js,jsx,css}", "*.config.{ts,js}", "supabase/migrations/**/*.sql"]
4
+ alwaysApply: false
5
+ paceCoreVersion: "0.6.x"
6
+ rulesVersion: "2025-01-28"
7
+ ---
8
+ # API & Tech Stack Standards Guide
9
+
10
+ **📚 Human-Readable Standard**: See [7-api-tech-stack-standards.md](../../packages/core/docs/standards/7-api-tech-stack-standards.md) for complete documentation.
11
+
12
+ This guide ensures consuming apps use the correct versions and patterns for all technologies in the PACE stack, and follow API/RPC naming conventions.
13
+
14
+ ## AI Agent Instructions
15
+
16
+ **When writing or modifying code, ALWAYS:**
17
+ 1. **Use Tailwind v4 CSS-first** - Use `@import 'tailwindcss'` and `@theme`, never `@tailwind` directives
18
+ 2. **Use theme variables** - Never use bracket syntax like `bg-[oklch(...)]`, always use theme variables (`bg-main-500`)
19
+ 3. **Use custom color namespaces** - Always use `main-*`, `sec-*`, `acc-*`, never standard Tailwind colors
20
+ 4. **Follow RPC naming** - Read operations: `data_*`, write operations: `app_*`, verbs: `create`, `read`, `update`, `delete`, `list`, `get`
21
+ 5. **Return ApiResult** - All RPCs must return ApiResult shape with proper error handling
22
+ 6. **Use TanStack Query** - Always use TanStack Query for server state, never `useState + useEffect`
23
+ 7. **Use React Hook Form + Zod** - Always use `useZodForm` from pace-core for forms
24
+
25
+ **Decision Tree: RPC Naming**
26
+ ```
27
+ 1. What operation is this?
28
+ ├─ Read (SELECT) → data_<domain>_<verb>
29
+ ├─ Write (INSERT/UPDATE/DELETE) → app_<domain>_<verb>
30
+ └─ Bulk operation → app_<domain>_<verb>_bulk
31
+
32
+ 2. What verb should I use?
33
+ ├─ Get single item → get
34
+ ├─ Get multiple items → list
35
+ ├─ Create → create
36
+ ├─ Update → update
37
+ ├─ Delete → delete
38
+ └─ Read (generic) → read
39
+ ```
40
+
41
+ **Decision Tree: Styling**
42
+ ```
43
+ 1. What am I styling?
44
+ ├─ Component → Use pace-core component (already styled)
45
+ ├─ Layout → Use Tailwind utilities (grid, flex, gap)
46
+ └─ Custom → Use theme variables (main-*, sec-*, acc-*)
47
+
48
+ 2. Do I need a color?
49
+ ├─ YES → Use theme variable (bg-main-500, text-sec-700)
50
+ └─ NO → Use semantic class (bg-background, text-foreground)
51
+
52
+ 3. Am I using bracket syntax?
53
+ ├─ YES → WRONG - Use theme variable instead
54
+ └─ NO → Continue
55
+ ```
56
+
57
+ ## Tailwind CSS v4
58
+
59
+ ### MUST: Use Tailwind v4 CSS-First Approach
60
+
61
+ **MUST use Tailwind v4 CSS-first syntax, NOT v3 patterns:**
62
+
63
+ ```css
64
+ /* ✅ CORRECT: Tailwind v4 CSS-first (@import 'tailwindcss'; @theme { ... }) */
65
+ /* ❌ WRONG: Tailwind v3 (@tailwind base/components/utilities directives) */
66
+ ```
67
+
68
+ ### MUST NOT: Use Bracket Syntax
69
+
70
+ **MUST NOT use bracket syntax like `bg-[oklch(...)]`. Map everything through theme variables:**
71
+
72
+ ```tsx
73
+ // ❌ WRONG: Bracket syntax (bg-[oklch(...)])
74
+ // ✅ CORRECT: Theme variable (bg-main-500)
75
+ ```
76
+
77
+ ### MUST: Use Custom Color Namespaces
78
+
79
+ **MUST use custom color namespaces:**
80
+ - `main-*` for primary colors (green, emerald, teal, cyan, sky, blue)
81
+ - `sec-*` for secondary colors (indigo, violet, purple, fuchsia, slate, gray, zinc, neutral, stone)
82
+ - `acc-*` for accent colors (red, orange, amber, yellow, lime, pink, rose)
83
+
84
+ ```tsx
85
+ // ✅ CORRECT: Custom namespaces (main-*, sec-*, acc-*)
86
+ // ❌ WRONG: Standard Tailwind colors (blue-*, gray-*, red-*)
87
+ ```
88
+
89
+ ### MUST: Use Semantic Classes
90
+
91
+ **MUST use semantic classes mapped in index.css:**
92
+
93
+ ```tsx
94
+ // ✅ CORRECT - Semantic classes
95
+ <div className="bg-background text-foreground">
96
+
97
+ // ❌ WRONG - Direct color classes (unless necessary)
98
+ <div className="bg-main-50 text-main-950">
99
+ ```
100
+
101
+ ## React 19+
102
+
103
+ ### MUST: Use React 19+ Features
104
+
105
+ **MUST use React 19+ patterns:**
106
+
107
+ ```tsx
108
+ // ✅ CORRECT: React 19+ features (Suspense, useTransition, etc.)
109
+ import { Suspense, useTransition } from 'react';
110
+ function App() {
111
+ const [isPending, startTransition] = useTransition();
112
+ return <Suspense fallback={<Loading />}><Component /></Suspense>;
113
+ }
114
+ ```
115
+
116
+ ### MUST: Use Functional Components
117
+
118
+ **MUST use functional components with hooks exclusively:**
119
+
120
+ ```tsx
121
+ // ✅ CORRECT: Functional components with hooks
122
+ function MyComponent() { const [state, setState] = useState(); return <div>...</div>; }
123
+
124
+ // ❌ WRONG: Class components
125
+ ```
126
+
127
+ ## Supabase
128
+
129
+ ### MUST: Use Secure Supabase Client
130
+
131
+ **MUST use `useSecureSupabase()` for all database operations:**
132
+
133
+ ```tsx
134
+ // ✅ CORRECT: useSecureSupabase() from '@jmruthers/pace-core/rbac'
135
+ // ❌ WRONG: createClient() from '@supabase/supabase-js' (base client)
136
+ ```
137
+
138
+ ### MUST: Enforce RLS
139
+
140
+ **MUST ensure RLS is enabled on all tables. Never bypass RLS.**
141
+
142
+ ### SHOULD: Use RPC Functions
143
+
144
+ **SHOULD use RPC functions for complex queries:**
145
+
146
+ ```tsx
147
+ // ✅ CORRECT: RPC functions for complex queries
148
+ const { data } = await secureSupabase.rpc('data_events_list', { organisation_id: orgId });
149
+
150
+ // ❌ AVOID: Complex client-side queries with many joins
151
+ ```
152
+
153
+ ## TanStack Query
154
+
155
+ ### MUST: Use TanStack Query for Server State
156
+
157
+ **MUST use TanStack Query for all server state management:**
158
+
159
+ ```tsx
160
+ // ✅ CORRECT: TanStack Query for server state
161
+ import { useQuery, useMutation } from '@tanstack/react-query';
162
+ const { data, isLoading } = useQuery({ queryKey: ['events', orgId], queryFn: () => fetchEvents(orgId) });
163
+
164
+ // ❌ WRONG: useState + useEffect for server state
165
+ ```
166
+
167
+ ### SHOULD: Configure Query Client
168
+
169
+ **SHOULD configure QueryClient with appropriate defaults:**
170
+
171
+ ```tsx
172
+ // ✅ CORRECT: Configure QueryClient with appropriate defaults (staleTime, cacheTime, retry)
173
+ const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, cacheTime: 10 * 60 * 1000, retry: 1 } } });
174
+ ```
175
+
176
+ ## React Hook Form + Zod
177
+
178
+ ### MUST: Use React Hook Form with Zod
179
+
180
+ **MUST use React Hook Form with Zod for all forms:**
181
+
182
+ ```tsx
183
+ // ✅ CORRECT: React Hook Form + Zod (useZodForm from pace-core)
184
+ import { useZodForm } from '@jmruthers/pace-core';
185
+ const schema = z.object({ email: z.string().email(), name: z.string().min(1) });
186
+ const form = useZodForm(schema);
187
+
188
+ // ❌ WRONG: Manual form handling (useState for form state)
189
+ ```
190
+
191
+ ## Vite Configuration
192
+
193
+ ### MUST: Use Vite for Build Tooling
194
+
195
+ **MUST use Vite for all build tooling:**
196
+
197
+ ```typescript
198
+ // ✅ CORRECT: Vite for build tooling
199
+ import { defineConfig } from 'vite';
200
+ import react from '@vitejs/plugin-react';
201
+ export default defineConfig({ plugins: [react()] });
202
+ ```
203
+
204
+ ### MUST: Configure Vite for pace-core
205
+
206
+ **⚠️ CRITICAL: Vite configuration prevents React context mismatches!**
207
+
208
+ **MUST** configure Vite to exclude `@jmruthers/pace-core` and `react-router-dom` from pre-bundling:
209
+
210
+ ```typescript
211
+ // vite.config.ts
212
+ import { defineConfig } from 'vite';
213
+ import react from '@vitejs/plugin-react';
214
+ import path from 'path';
215
+
216
+ export default defineConfig({
217
+ plugins: [react()],
218
+ resolve: {
219
+ alias: {
220
+ '@': path.resolve(__dirname, './src'),
221
+ },
222
+ // CRITICAL: Dedupe React dependencies
223
+ dedupe: ['react', 'react-dom', 'react-router-dom'],
224
+ },
225
+ optimizeDeps: {
226
+ include: [
227
+ 'react',
228
+ 'react-dom',
229
+ 'react/jsx-runtime',
230
+ ],
231
+ // CRITICAL: Exclude pace-core to prevent React context mismatches
232
+ exclude: ['@jmruthers/pace-core', 'react-router-dom'],
233
+ },
234
+ });
235
+ ```
236
+
237
+ **Why this matters:**
238
+ - Pre-bundling `@jmruthers/pace-core` creates separate React instances
239
+ - This causes "useUnifiedAuth must be used within a UnifiedAuthProvider" errors
240
+ - Excluding it ensures pace-core uses the same React instance as your app
241
+ - `react-router-dom` must also be excluded and deduped to prevent Router context errors
242
+
243
+ ### MUST: Use Environment Variables Correctly
244
+
245
+ **MUST use `import.meta.env` for environment variables:**
246
+
247
+ ```tsx
248
+ // ✅ CORRECT: import.meta.env.VITE_API_URL (Vite env vars)
249
+ // ❌ WRONG: process.env.VITE_API_URL (Node.js env vars)
250
+ ```
251
+
252
+ ## API & RPC Patterns
253
+
254
+ ### MUST: Follow RPC Naming Convention
255
+
256
+ **RPCs MUST follow pattern: `<family>_<domain>_<verb>`**
257
+
258
+ - `data_*` prefix for read operations: `data_events_list`, `data_file_reference_list`
259
+ - `app_*` prefix for write operations: `app_event_create`, `app_event_update`
260
+ - CRUD verbs only: `create`, `read`, `update`, `delete`, `list`, `get`
261
+ - Bulk operations: `_bulk` suffix (e.g., `app_event_create_bulk`)
262
+
263
+ ```sql
264
+ -- ✅ CORRECT: data_events_list, app_event_create, app_event_create_bulk
265
+ -- ❌ WRONG: getEvents, create_event (wrong naming pattern)
266
+ ```
267
+
268
+ ### MUST: Use ApiResult Shape
269
+
270
+ **All RPCs MUST return ApiResult shape:**
271
+
272
+ ```typescript
273
+ type ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError };
274
+ type ApiError = { code: string; message: string; details?: object };
275
+ ```
276
+
277
+ ```tsx
278
+ // ✅ CORRECT: Handle ApiResult
279
+ const result = await supabase.rpc('app_events_create', { name, date });
280
+ if (!result.ok) {
281
+ // Handle error
282
+ return { ok: false, error: result.error };
283
+ }
284
+ return { ok: true, data: result.data };
285
+ ```
286
+
287
+ ### MUST: Enforce RLS in RPCs
288
+
289
+ **RPCs MUST enforce RLS and tenant boundaries.** Never bypass RLS.
290
+
291
+ ### SHOULD: Make Write RPCs Idempotent
292
+
293
+ **Write RPCs SHOULD be idempotent when possible:**
294
+
295
+ ```sql
296
+ -- ✅ CORRECT: Idempotent create (ON CONFLICT DO NOTHING)
297
+ INSERT INTO events (id, name, date)
298
+ VALUES (p_event_id, p_name, p_date)
299
+ ON CONFLICT (id) DO NOTHING;
300
+ ```
301
+
302
+ ## TypeScript
303
+
304
+ **Note**: TypeScript configuration details are handled by ESLint and the standards. See [7-api-tech-stack-standards.md](../../packages/core/docs/standards/7-api-tech-stack-standards.md) for complete TypeScript setup.
305
+
306
+ **MUST:**
307
+ - Use TypeScript 5+ with strict mode
308
+ - Follow TypeScript patterns from [4-code-quality-standards.md](../../packages/core/docs/standards/4-code-quality-standards.md)
309
+
310
+ ## Version Requirements
311
+
312
+ ### MUST: Use Required Versions
313
+
314
+ **MUST use compatible versions:**
315
+
316
+ - React: `^19.0.0`
317
+ - TypeScript: `^5.0.0`
318
+ - Tailwind CSS: `^4.0.0`
319
+ - Vite: `^6.0.0`
320
+ - Supabase: `^2.49.0+`
321
+
322
+ **Check `package.json` for exact versions required by pace-core.**
323
+
324
+ ## Common Mistakes to Avoid
325
+
326
+ **When writing code, NEVER:**
327
+ 1. **Use Tailwind v3 patterns** - Always use v4 CSS-first syntax
328
+ ```css
329
+ /* ❌ WRONG */
330
+ @tailwind base;
331
+ @tailwind components;
332
+ @tailwind utilities;
333
+
334
+ /* ✅ CORRECT */
335
+ @import "tailwindcss";
336
+ @theme { /* ... */ }
337
+ ```
338
+
339
+ 2. **Use bracket syntax for colors** - Always use theme variables
340
+ ```tsx
341
+ // ❌ WRONG
342
+ <div className="bg-[oklch(0.5 0.2 250)]">
343
+
344
+ // ✅ CORRECT
345
+ <div className="bg-main-500">
346
+ ```
347
+
348
+ 3. **Use standard Tailwind colors** - Always use custom namespaces (main-*, sec-*, acc-*)
349
+ 4. **Use useState + useEffect for server state** - Always use TanStack Query
350
+ 5. **Create RPCs without ApiResult** - Always return ApiResult shape
351
+ 6. **Use wrong RPC naming** - Always follow `data_*` or `app_*` pattern
352
+
353
+ ## Tech Stack Checklist
354
+
355
+ Before committing, verify:
356
+ - [ ] Tailwind v4 CSS-first syntax (no @tailwind directives)
357
+ - [ ] No bracket syntax for colors (use theme variables)
358
+ - [ ] Custom color namespaces (main-*, sec-*, acc-*)
359
+ - [ ] React 19+ functional components
360
+ - [ ] Secure Supabase client (useSecureSupabase)
361
+ - [ ] TanStack Query for server state
362
+ - [ ] React Hook Form + Zod for forms
363
+ - [ ] Vite configured correctly (optimizeDeps.exclude, resolve.dedupe)
364
+ - [ ] TypeScript 5+ with strict mode
365
+ - [ ] All versions compatible with pace-core
366
+ - [ ] RPCs follow naming convention (data_* or app_*)
367
+ - [ ] RPCs return ApiResult shape
368
+ - [ ] RPCs enforce RLS
369
+
370
+ ## Reference
371
+
372
+ - Tailwind v4: https://tailwindcss.com/blog/tailwindcss-v4
373
+ - React 19: https://react.dev/blog/2024/04/25/react-19-upgrade-guide
374
+ - Supabase: https://supabase.com/docs
375
+ - TanStack Query: https://tanstack.com/query
376
+ - React Hook Form: https://react-hook-form.com
377
+ - Vite: https://vitejs.dev
@@ -0,0 +1,324 @@
1
+ ---
2
+ description: Enforce testing standards, documentation requirements, and issue reporting templates
3
+ globs: ["**/*.{test,spec}.{ts,tsx}", "**/*.md", "**/*.mdx"]
4
+ alwaysApply: false
5
+ paceCoreVersion: "0.6.x"
6
+ rulesVersion: "2025-01-28"
7
+ ---
8
+ # Testing & Documentation Standards Guide
9
+
10
+ **📚 Human-Readable Standard**: See [8-testing-documentation-standards.md](../../packages/core/docs/standards/8-testing-documentation-standards.md) for complete documentation including coverage requirements, test timeouts, and documentation templates.
11
+
12
+ This guide ensures consistent, high-quality testing and documentation across consuming apps in the PACE suite.
13
+
14
+ ## AI Agent Instructions
15
+
16
+ **When writing or modifying tests, ALWAYS:**
17
+ 1. **Use React Testing Library** - Always use `@testing-library/react` and `userEvent`, never Enzyme or other libraries
18
+ 2. **Test user behavior** - Test what users see and do, not implementation details
19
+ 3. **Use accessible queries** - Prefer `getByRole`, `getByLabelText` over `getByTestId`
20
+ 4. **Include timeouts** - Always include timeout parameters to prevent tests from hanging
21
+ 5. **Colocate tests** - Place test files next to source files (`Component.test.tsx` next to `Component.tsx`)
22
+ 6. **Use descriptive names** - Test names should clearly describe the behavior being tested
23
+ 7. **Group related tests** - Use `describe` blocks to organize related tests
24
+
25
+ **Decision Tree: Writing Tests**
26
+ ```
27
+ 1. What am I testing?
28
+ ├─ Component → Use React Testing Library + userEvent
29
+ ├─ Hook → Test hook in isolation with renderHook
30
+ ├─ Utility → Test pure function directly
31
+ └─ Integration → Test user workflows end-to-end
32
+
33
+ 2. How do I query elements?
34
+ ├─ Interactive element → getByRole (preferred)
35
+ ├─ Form field → getByLabelText (preferred)
36
+ ├─ Text content → getByText
37
+ └─ Last resort → getByTestId (avoid if possible)
38
+
39
+ 3. Is this async?
40
+ ├─ YES → Use waitFor with timeout
41
+ └─ NO → Direct assertions
42
+ ```
43
+
44
+ ## Testing Patterns
45
+
46
+ ### MUST: Use React Testing Library
47
+
48
+ **MUST use React Testing Library + userEvent for all component tests:**
49
+
50
+ ```tsx
51
+ // ✅ CORRECT: React Testing Library + userEvent
52
+ import { render, screen } from '@testing-library/react';
53
+ import userEvent from '@testing-library/user-event';
54
+
55
+ test('button clicks work', async () => {
56
+ const user = userEvent.setup();
57
+ const handleClick = vi.fn();
58
+ render(<Button onClick={handleClick}>Click me</Button>);
59
+ await user.click(screen.getByRole('button', { name: /click me/i }));
60
+ expect(handleClick).toHaveBeenCalledTimes(1);
61
+ });
62
+ ```
63
+
64
+ ### MUST: Colocate Tests
65
+
66
+ **Tests MUST be colocated with source files:**
67
+
68
+ ```
69
+ src/
70
+ ├── components/
71
+ │ └── EventCard/
72
+ │ ├── EventCard.tsx
73
+ │ └── EventCard.test.tsx
74
+ ├── hooks/
75
+ │ ├── useEventData.ts
76
+ │ └── useEventData.test.ts
77
+ └── utils/
78
+ ├── formatEvent.ts
79
+ └── formatEvent.test.ts
80
+ ```
81
+
82
+ ### MUST: Test User Behavior, Not Implementation
83
+
84
+ **Tests MUST focus on what users see and do:**
85
+
86
+ ```tsx
87
+ // ❌ WRONG: Testing implementation
88
+ test('calls setState', () => {
89
+ const component = render(<Counter />);
90
+ expect(component.state.count).toBe(0);
91
+ });
92
+
93
+ // ✅ CORRECT: Testing user behavior
94
+ test('displays count and increments on button click', async () => {
95
+ const user = userEvent.setup();
96
+ render(<Counter />);
97
+ expect(screen.getByText('Count: 0')).toBeInTheDocument();
98
+ await user.click(screen.getByRole('button', { name: /increment/i }));
99
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
100
+ });
101
+ ```
102
+
103
+ ### MUST: Use Accessible Queries
104
+
105
+ **MUST prefer accessible queries (byRole, byLabelText, etc.):**
106
+
107
+ ```tsx
108
+ // ✅ CORRECT: Accessible queries
109
+ screen.getByRole('button', { name: /submit/i });
110
+ screen.getByLabelText(/email address/i);
111
+
112
+ // ❌ AVOID: Non-accessible queries (use as last resort)
113
+ screen.getByTestId('submit-button');
114
+ ```
115
+
116
+ ### MUST: Include Timeout Parameters
117
+
118
+ **Tests MUST include timeout parameters to prevent hanging:**
119
+
120
+ ```tsx
121
+ // ✅ CORRECT: Include timeout parameters
122
+ test('async operation completes', async () => {
123
+ await waitFor(
124
+ () => expect(screen.getByText('Loaded')).toBeInTheDocument(),
125
+ { timeout: 5000 }
126
+ );
127
+ }, { timeout: 10000 });
128
+ ```
129
+
130
+ **Configure timeouts in `vitest.config.ts`:**
131
+
132
+ ```typescript
133
+ export default defineConfig({
134
+ test: {
135
+ testTimeout: 10000, // Default 10 seconds for all tests
136
+ hookTimeout: 10000,
137
+ },
138
+ });
139
+ ```
140
+
141
+ ### SHOULD: Test Critical Paths
142
+
143
+ **SHOULD test:**
144
+ - User workflows and interactions
145
+ - Error handling and edge cases
146
+ - Form validation
147
+ - Permission checks (RBAC)
148
+ - Data loading states
149
+ - Error states
150
+
151
+ ### SHOULD: Use Descriptive Test Names
152
+
153
+ **Test names SHOULD describe behavior:**
154
+
155
+ ```tsx
156
+ // ❌ WRONG - Vague
157
+ test('button works', () => { ... });
158
+
159
+ // ✅ CORRECT - Descriptive
160
+ test('increments counter when increment button is clicked', () => { ... });
161
+ test('displays error message when API call fails', () => { ... });
162
+ ```
163
+
164
+ ### SHOULD: Group Related Tests
165
+
166
+ **SHOULD use `describe` blocks to group related tests:**
167
+
168
+ ```tsx
169
+ describe('EventCard', () => {
170
+ describe('rendering', () => {
171
+ test('displays event title', () => { ... });
172
+ test('displays event date', () => { ... });
173
+ });
174
+
175
+ describe('interactions', () => {
176
+ test('calls onEdit when edit button clicked', () => { ... });
177
+ });
178
+ });
179
+ ```
180
+
181
+ ## Coverage Requirements
182
+
183
+ **Note**: Coverage threshold enforcement is handled by CI/ESLint. See [8-testing-documentation-standards.md](../../packages/core/docs/standards/8-testing-documentation-standards.md) for complete coverage requirements.
184
+
185
+ **MUST achieve:**
186
+ - ≥90% coverage for utils & hooks
187
+ - ≥70% coverage for components
188
+
189
+ **MUST configure test runner to enforce thresholds:**
190
+
191
+ ```typescript
192
+ // vitest.config.ts
193
+ export default defineConfig({
194
+ test: {
195
+ coverage: {
196
+ thresholds: {
197
+ lines: 80,
198
+ functions: 80,
199
+ branches: 80,
200
+ statements: 80,
201
+ },
202
+ },
203
+ },
204
+ });
205
+ ```
206
+
207
+ ## Documentation Requirements
208
+
209
+ ### MUST: Document Public APIs
210
+
211
+ **MUST document all public functions, components, and hooks:**
212
+
213
+ ```tsx
214
+ /**
215
+ * Fetches event data for a given event ID.
216
+ *
217
+ * @param eventId - The unique identifier for the event
218
+ * @returns Event data or null if not found
219
+ * @throws {Error} If eventId is invalid
220
+ */
221
+ export async function fetchEvent(eventId: string): Promise<Event | null> {
222
+ // Implementation
223
+ }
224
+ ```
225
+
226
+ ### MUST: Include Usage Examples
227
+
228
+ **MUST include usage examples in documentation:**
229
+
230
+ ```tsx
231
+ /**
232
+ * Example usage:
233
+ * ```tsx
234
+ * const { event, isLoading } = useEventData('event-123');
235
+ * if (isLoading) return <Loading />;
236
+ * return <EventCard event={event} />;
237
+ * ```
238
+ */
239
+ ```
240
+
241
+ ### SHOULD: Document Complex Logic
242
+
243
+ **SHOULD document complex logic and business rules:**
244
+
245
+ ```tsx
246
+ // Calculate event duration, accounting for timezone differences
247
+ // Events can span multiple days, so we need to handle day boundaries
248
+ function calculateDuration(start: Date, end: Date): number {
249
+ // Implementation
250
+ }
251
+ ```
252
+
253
+ ## Bug Reports & Feature Requests
254
+
255
+ **Note**: Complete templates are in [8-testing-documentation-standards.md](../../packages/core/docs/standards/8-testing-documentation-standards.md). Use these patterns when creating issues.
256
+
257
+ ### Bug Report Checklist
258
+
259
+ Before filing a bug report:
260
+ - [ ] Issue hasn't been reported already
261
+ - [ ] Using latest pace-core version
262
+ - [ ] Issue is in pace-core (not your app)
263
+ - [ ] Checked documentation
264
+ - [ ] Have minimal reproduction
265
+ - [ ] Included all required information
266
+
267
+ ### Feature Request Checklist
268
+
269
+ Before filing a feature request:
270
+ - [ ] Feature doesn't already exist
271
+ - [ ] Checked if workaround exists
272
+ - [ ] Clear problem statement
273
+ - [ ] Proposed solution described
274
+ - [ ] Real-world use case provided
275
+ - [ ] Alternatives considered
276
+
277
+ ## Common Mistakes to Avoid
278
+
279
+ **When writing tests, NEVER:**
280
+ 1. **Test implementation details** - Always test user behavior
281
+ ```tsx
282
+ // ❌ WRONG
283
+ test('calls setState', () => {
284
+ const component = render(<Counter />);
285
+ expect(component.state.count).toBe(0);
286
+ });
287
+
288
+ // ✅ CORRECT
289
+ test('displays count and increments on button click', async () => {
290
+ const user = userEvent.setup();
291
+ render(<Counter />);
292
+ expect(screen.getByText('Count: 0')).toBeInTheDocument();
293
+ await user.click(screen.getByRole('button', { name: /increment/i }));
294
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
295
+ });
296
+ ```
297
+
298
+ 2. **Use getByTestId as first choice** - Always prefer accessible queries (getByRole, getByLabelText)
299
+ 3. **Skip timeouts** - Always include timeout parameters to prevent hanging
300
+ 4. **Place tests in separate directory** - Always colocate tests with source files
301
+ 5. **Use vague test names** - Always use descriptive names that explain behavior
302
+
303
+ ## Testing Checklist
304
+
305
+ Before committing tests, verify:
306
+ - [ ] Coverage meets requirements (≥90% utils, ≥70% components)
307
+ - [ ] Using React Testing Library + userEvent
308
+ - [ ] Tests are colocated with source files
309
+ - [ ] Testing user behavior, not implementation
310
+ - [ ] Using accessible queries (byRole, byLabelText)
311
+ - [ ] Test names are descriptive
312
+ - [ ] Related tests grouped with describe
313
+ - [ ] No unnecessary mocks
314
+ - [ ] Async code tested properly
315
+ - [ ] Cleanup after tests
316
+ - [ ] Timeout parameters included
317
+
318
+ ## Reference
319
+
320
+ **Note**: Coverage threshold enforcement and detailed test configuration are handled by CI/ESLint. See [8-testing-documentation-standards.md](../../packages/core/docs/standards/8-testing-documentation-standards.md) for complete enforcement details.
321
+
322
+ - React Testing Library: https://testing-library.com/react
323
+ - Vitest: https://vitest.dev
324
+ - Complete templates: [8-testing-documentation-standards.md](../../packages/core/docs/standards/8-testing-documentation-standards.md)