@jmruthers/pace-core 0.6.6 → 0.6.8

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 (292) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +240 -0
  4. package/audit-tool/audits/03-architecture.cjs +224 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +554 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +355 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +295 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +380 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-6RMSCQJ6.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
  28. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  29. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  30. package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
  31. package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
  32. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  33. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  34. package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
  35. package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
  36. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  37. package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
  38. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  39. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  40. package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
  41. package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
  42. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  43. package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
  44. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  45. package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
  46. package/dist/components.d.ts +5 -4
  47. package/dist/components.js +29 -34
  48. package/dist/eslint-rules/index.cjs +22 -9
  49. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  50. package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
  51. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  52. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
  53. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
  54. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  55. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  56. package/dist/hooks.d.ts +5 -5
  57. package/dist/hooks.js +8 -8
  58. package/dist/index.d.ts +7 -7
  59. package/dist/index.js +21 -20
  60. package/dist/providers.js +2 -2
  61. package/dist/rbac/index.d.ts +1 -1
  62. package/dist/rbac/index.js +8 -8
  63. package/dist/theming/runtime.d.ts +61 -1
  64. package/dist/theming/runtime.js +1 -1
  65. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  66. package/dist/types.d.ts +2 -2
  67. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  68. package/dist/utils.d.ts +2 -2
  69. package/dist/utils.js +8 -8
  70. package/docs/README.md +1 -1
  71. package/docs/api/modules.md +106 -41
  72. package/docs/api-reference/components.md +18 -20
  73. package/docs/api-reference/hooks.md +80 -80
  74. package/docs/api-reference/types.md +1 -1
  75. package/docs/api-reference/utilities.md +1 -1
  76. package/docs/architecture/README.md +1 -1
  77. package/docs/core-concepts/events.md +3 -3
  78. package/docs/core-concepts/organisations.md +6 -6
  79. package/docs/core-concepts/permissions.md +6 -6
  80. package/docs/documentation-index.md +12 -18
  81. package/docs/getting-started/dependencies.md +23 -0
  82. package/docs/getting-started/documentation-index.md +1 -1
  83. package/docs/getting-started/examples/README.md +4 -4
  84. package/docs/getting-started/examples/full-featured-app.md +1 -1
  85. package/docs/getting-started/faq.md +2 -2
  86. package/docs/getting-started/quick-reference.md +4 -4
  87. package/docs/implementation-guides/app-layout.md +1 -1
  88. package/docs/implementation-guides/authentication.md +15 -15
  89. package/docs/implementation-guides/component-styling.md +1 -1
  90. package/docs/implementation-guides/data-tables.md +127 -34
  91. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  92. package/docs/implementation-guides/dynamic-colors.md +3 -3
  93. package/docs/implementation-guides/file-upload-storage.md +2 -2
  94. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  95. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  96. package/docs/implementation-guides/large-datasets.md +3 -2
  97. package/docs/implementation-guides/organisation-security.md +2 -2
  98. package/docs/implementation-guides/performance.md +2 -2
  99. package/docs/implementation-guides/permission-enforcement.md +1 -1
  100. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  101. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  102. package/docs/rbac/README.md +5 -5
  103. package/docs/rbac/advanced-patterns.md +6 -6
  104. package/docs/rbac/api-reference.md +20 -20
  105. package/docs/rbac/event-based-apps.md +3 -3
  106. package/docs/rbac/examples.md +41 -41
  107. package/docs/rbac/getting-started.md +37 -37
  108. package/docs/rbac/performance.md +1 -1
  109. package/docs/rbac/quick-start.md +52 -52
  110. package/docs/rbac/secure-client-protection.md +1 -1
  111. package/docs/rbac/troubleshooting.md +1 -1
  112. package/docs/security/README.md +5 -5
  113. package/docs/standards/0-standards-overview.md +220 -0
  114. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
  115. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  116. package/docs/standards/3-architecture-standards.md +606 -0
  117. package/docs/standards/4-code-quality-standards.md +728 -0
  118. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  119. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  120. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  121. package/docs/standards/8-testing-documentation-standards.md +401 -0
  122. package/docs/standards/9-operations-standards.md +1102 -0
  123. package/docs/standards/README.md +203 -104
  124. package/docs/troubleshooting/README.md +4 -4
  125. package/docs/troubleshooting/common-issues.md +2 -2
  126. package/docs/troubleshooting/debugging.md +9 -9
  127. package/docs/troubleshooting/migration.md +4 -4
  128. package/eslint-config-pace-core.cjs +50 -20
  129. package/package.json +50 -19
  130. package/scripts/eslint-audit.cjs +123 -0
  131. package/scripts/install-cursor-rules.cjs +11 -243
  132. package/scripts/install-eslint-config.cjs +349 -0
  133. package/scripts/validate-dependencies.cjs +248 -0
  134. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  135. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  136. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
  137. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  138. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  139. package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
  140. package/src/__tests__/templates/component.test.template.tsx +18 -15
  141. package/src/components/AddressField/AddressField.tsx +26 -1
  142. package/src/components/Alert/Alert.test.tsx +86 -22
  143. package/src/components/Alert/Alert.tsx +19 -11
  144. package/src/components/Badge/Badge.tsx +1 -1
  145. package/src/components/Calendar/Calendar.tsx +201 -47
  146. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  147. package/src/components/ContextSelector/ContextSelector.tsx +108 -126
  148. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  149. package/src/components/DataTable/DataTable.tsx +1 -19
  150. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
  151. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
  152. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  153. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  154. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  155. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  156. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  157. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  158. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  159. package/src/components/DataTable/components/EmptyState.tsx +11 -10
  160. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  161. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  162. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  163. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  164. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  165. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  166. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  167. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  168. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  169. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +45 -27
  170. package/src/components/DataTable/components/index.ts +2 -1
  171. package/src/components/DataTable/types.ts +0 -18
  172. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  173. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
  174. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  175. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  176. package/src/components/Dialog/Dialog.test.tsx +1 -0
  177. package/src/components/Dialog/Dialog.tsx +25 -8
  178. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  179. package/src/components/FileUpload/FileUpload.test.tsx +45 -16
  180. package/src/components/FileUpload/FileUpload.tsx +141 -130
  181. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  182. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  183. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  184. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  185. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  186. package/src/components/Progress/Progress.tsx +2 -4
  187. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  188. package/src/components/Select/Select.tsx +86 -77
  189. package/src/components/Select/types.ts +3 -0
  190. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  191. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  192. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  193. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  194. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
  195. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  196. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  197. package/src/hooks/public/usePublicEvent.ts +5 -5
  198. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  199. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  200. package/src/hooks/public/usePublicRouteParams.ts +13 -9
  201. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  202. package/src/hooks/useAppConfig.ts +2 -2
  203. package/src/hooks/useEventTheme.test.ts +7 -7
  204. package/src/hooks/useEventTheme.ts +2 -1
  205. package/src/hooks/useFileDisplay.ts +2 -2
  206. package/src/hooks/useFileUrl.ts +52 -8
  207. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  208. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  209. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  210. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  211. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  212. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  213. package/src/providers/__tests__/ProviderLifecycle.test.tsx +38 -38
  214. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  215. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  216. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  217. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  218. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  219. package/src/rbac/api.test.ts +104 -0
  220. package/src/rbac/engine.ts +1 -1
  221. package/src/rbac/hooks/useCan.test.ts +2 -2
  222. package/src/rbac/secureClient.ts +1 -1
  223. package/src/rbac/types/functions.ts +1 -1
  224. package/src/styles/core.css +7 -0
  225. package/src/theming/__tests__/parseEventColours.test.ts +118 -3
  226. package/src/theming/parseEventColours.ts +77 -11
  227. package/src/types/supabase.ts +2 -3
  228. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  229. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  230. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  231. package/src/utils/formatting/formatDate.test.ts +3 -2
  232. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  233. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  234. package/src/utils/storage/README.md +1 -1
  235. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  236. package/src/utils/storage/helpers.test.ts +69 -3
  237. package/cursor-rules/01-standards-compliance.mdc +0 -285
  238. package/cursor-rules/04-testing-standards.mdc +0 -270
  239. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  240. package/cursor-rules/06-code-quality.mdc +0 -311
  241. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  242. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  243. package/cursor-rules/11-performance-optimization.mdc +0 -169
  244. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  245. package/dist/DataTable-LRJL4IRV.js +0 -15
  246. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  247. package/dist/eslint-rules/rules/components.cjs +0 -113
  248. package/dist/eslint-rules/rules/imports.cjs +0 -102
  249. package/docs/best-practices/README.md +0 -472
  250. package/docs/best-practices/accessibility.md +0 -604
  251. package/docs/best-practices/common-patterns.md +0 -516
  252. package/docs/best-practices/deployment.md +0 -1103
  253. package/docs/best-practices/performance.md +0 -1328
  254. package/docs/best-practices/security.md +0 -940
  255. package/docs/best-practices/testing.md +0 -1034
  256. package/docs/rbac/compliance/compliance-guide.md +0 -544
  257. package/docs/standards/01-standards-compliance.md +0 -188
  258. package/docs/standards/03-solid-principles.md +0 -39
  259. package/docs/standards/04-testing-standards.md +0 -36
  260. package/docs/standards/05-bug-reports-and-features.md +0 -27
  261. package/docs/standards/06-code-quality.md +0 -34
  262. package/docs/standards/07-tech-stack-compliance.md +0 -30
  263. package/docs/standards/10-error-handling-patterns.md +0 -401
  264. package/docs/standards/11-performance-optimization.md +0 -348
  265. package/docs/standards/12-ci-cd-integration.md +0 -370
  266. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  267. package/scripts/audit/audit-compliance.cjs +0 -1295
  268. package/scripts/audit/audit-components.cjs +0 -260
  269. package/scripts/audit/audit-rbac.cjs +0 -954
  270. package/scripts/audit/audit-standards.cjs +0 -1268
  271. package/scripts/audit/index.cjs +0 -1927
  272. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  273. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  274. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  275. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  276. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  277. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  278. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  279. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  280. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  281. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  282. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  283. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  284. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  285. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  286. package/src/components/DataTable/utils/debugTools.ts +0 -514
  287. package/src/eslint-rules/index.cjs +0 -22
  288. package/src/eslint-rules/rules/components.cjs +0 -113
  289. package/src/eslint-rules/rules/imports.cjs +0 -102
  290. package/src/eslint-rules/rules/rbac.cjs +0 -790
  291. package/src/eslint-rules/utils/helpers.cjs +0 -42
  292. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -1,285 +0,0 @@
1
- ---
2
- description: Enforce compliance with all pace-core standards across architecture, API, components, code style, security, testing, and RBAC/RLS
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
- # Standards Compliance Guide
9
-
10
- This guide ensures consuming apps comply with all pace-core standards. Follow these standards to maintain quality, security, and consistency.
11
-
12
- ## MUST: Include Complete Cursor Ruleset
13
-
14
- Consuming apps **MUST** include the complete pace-core ruleset in the repository so audits are deterministic and repeatable.
15
-
16
- - **MUST** include these files under `.cursor/rules/` (exact filenames):
17
- - `00-pace-core-compliance.mdc`
18
- - `01-standards-compliance.mdc`
19
- - `02-project-structure.mdc`
20
- - `03-solid-principles.mdc`
21
- - `06-code-quality.mdc`
22
- - `07-tech-stack-compliance.mdc`
23
- - `08-markup-quality.mdc`
24
- - `09-rbac-compliance.mdc`
25
- - `10-error-handling-patterns.mdc`
26
- - `11-performance-optimization.mdc`
27
- - **MUST NOT** rename or partially copy rules files.
28
- - If a rule does not apply to a given app, document the exception and the reason, but keep the rule file present.
29
-
30
-
31
- ## Architecture Standard
32
-
33
- ### MUST: Follow Architecture Principles
34
-
35
- **MUST adhere to:**
36
- - Composition over complexity
37
- - Separation of concerns
38
- - Domain-agnostic design
39
- - Extensible, stable APIs
40
- - Secure by default
41
- - Performance-conscious
42
-
43
- ### MUST: Use Helper Functions in RLS Policies
44
-
45
- **RLS policies MUST use helper functions, NEVER subqueries.**
46
-
47
- ```sql
48
- -- ❌ WRONG: Subquery in RLS policy (causes N+1 queries)
49
- CREATE POLICY rbac_select_users ON users FOR SELECT USING (
50
- organisation_id IN (SELECT organisation_id FROM organisation_memberships WHERE user_id = auth.uid())
51
- );
52
-
53
- -- ✅ CORRECT: Helper function with STABLE SECURITY DEFINER
54
- CREATE OR REPLACE FUNCTION get_user_organisation_ids() RETURNS uuid[] LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path TO public AS $$
55
- BEGIN RETURN ARRAY(SELECT organisation_id FROM organisation_memberships WHERE user_id = get_effective_user_id()); END;
56
- $$;
57
- CREATE POLICY rbac_select_users ON users FOR SELECT USING (organisation_id = ANY(get_user_organisation_ids()));
58
- ```
59
-
60
- ### MUST: Test Database Migrations
61
-
62
- **MUST verify migrations don't cause query timeouts or performance degradation.**
63
-
64
- ## API & RPC Standard
65
-
66
- ### MUST: Follow RPC Naming Convention
67
-
68
- **RPCs MUST follow pattern: `<family>_<domain>_<verb>`**
69
-
70
- - `data_*` prefix for read operations: `data_cake_dishes_list`, `data_file_reference_list`
71
- - `app_*` prefix for write operations: `app_cake_dish_create`, `app_cake_dish_update`
72
- - CRUD verbs only: `create`, `read`, `update`, `delete`, `list`, `get`
73
- - Bulk operations: `_bulk` suffix (e.g., `app_cake_dish_create_bulk`)
74
-
75
- ```sql
76
- -- ✅ CORRECT: data_cake_dishes_list, app_cake_dish_create, app_cake_dish_create_bulk
77
- -- ❌ WRONG: getDishes, create_dish (wrong naming pattern)
78
- ```
79
-
80
- ### MUST: Use ApiResult Shape
81
-
82
- **All RPCs MUST return ApiResult shape:**
83
-
84
- ```typescript
85
- type ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError };
86
- type ApiError = { code: string; message: string; details?: object };
87
- ```
88
-
89
- ### MUST: Enforce RLS in RPCs
90
-
91
- **RPCs MUST enforce RLS and tenant boundaries.** Never bypass RLS.
92
-
93
- ### SHOULD: Make Write RPCs Idempotent
94
-
95
- **Write RPCs SHOULD be idempotent when possible.**
96
-
97
- ## Component Standard
98
-
99
- ### MUST: Follow Component Principles
100
-
101
- **Components MUST:**
102
- - Be stateless when possible
103
- - Use composable structure
104
- - Be accessible by default
105
- - Be fully typed
106
- - Have small surface area
107
-
108
- ### MUST NOT: Add Domain Logic to Components
109
-
110
- **Components MUST NOT:**
111
- - Include domain-specific logic
112
- - Fetch data directly (use hooks/services)
113
- - Include business workflows
114
-
115
- ### MUST: Ensure Accessibility
116
-
117
- **Components MUST:**
118
- - Be keyboard operable
119
- - Have correct ARIA roles
120
- - Have visible focus states
121
- - Avoid inaccessible interactions
122
-
123
- ## Code Style Standard
124
-
125
- ### MUST: Follow TypeScript Rules
126
-
127
- **MUST:**
128
- - Use strict mode (`strict: true` in tsconfig)
129
- - Prefer discriminated unions
130
- - Use ReadonlyArray where possible
131
- - Avoid boolean mode flags (use unions instead)
132
-
133
- **MUST NOT:**
134
- - Use `any` (use `unknown` if type is truly unknown)
135
- - Use implicit any
136
- - Use unnecessary type assertions
137
-
138
- ### MUST: Follow Naming Conventions
139
-
140
- - Hooks: `useSomething`
141
- - Providers: `SomethingProvider`
142
- - Utilities: `camelCase`
143
- - Components: `PascalCase`
144
-
145
- ### SHOULD: Use Preferred Patterns
146
-
147
- **SHOULD:**
148
- - Use pure functions
149
- - Prefer composition over inheritance
150
- - Use early returns
151
- - Extract large functions into small helpers
152
-
153
- ## Security Standard
154
-
155
- ### MUST: Never Bypass RLS
156
-
157
- **MUST enforce RLS on all tables.** Never bypass RLS policies.
158
-
159
- ### MUST: Validate All Inputs
160
-
161
- **MUST validate all inputs using Zod schemas or similar.**
162
-
163
- ### MUST: Sanitize Logs
164
-
165
- **MUST NOT log:**
166
- - Passwords
167
- - Tokens
168
- - Sensitive data (PII)
169
-
170
- **MAY log:**
171
- - IDs
172
- - Non-PII metadata
173
-
174
- ### MUST: Use Safe Error Messaging
175
-
176
- **MUST NOT expose internal details in error messages.**
177
-
178
- ### MUST: Use Helper Functions in RLS
179
-
180
- **RLS policies MUST use STABLE SECURITY DEFINER helper functions:**
181
- - `STABLE` - Results consistent within transaction
182
- - `SECURITY DEFINER` - Bypass RLS to avoid recursion
183
- - `SET search_path TO 'public'` - Prevent search path injection
184
-
185
- ## Testing Standard
186
-
187
- ### MUST: Meet Coverage Requirements
188
-
189
- **MUST achieve:**
190
- - ≥90% coverage for utils & hooks
191
- - ≥70% coverage for components
192
-
193
-
194
- ### MUST: Enforce Coverage Thresholds in Tooling
195
-
196
- Coverage requirements must be **machine-enforced**, not aspirational:
197
-
198
- - **MUST** provide a script: `npm run test:coverage`
199
- - **MUST** configure the test runner (Vitest/Jest) to enforce the thresholds:
200
- - ≥90% for utils & hooks
201
- - ≥70% for components
202
- - **MUST** fail the command when thresholds are not met (CI or local execution).
203
-
204
- **Verification:**
205
- - `npm run test:coverage` exits non-zero when below threshold.
206
- - A coverage summary artifact is produced (e.g., `coverage/coverage-summary.json` or equivalent).
207
-
208
- ### MUST: Use React Testing Library
209
-
210
- **MUST use React Testing Library + userEvent for component tests.**
211
-
212
- ### SHOULD: Colocate Tests
213
-
214
- **Tests SHOULD be colocated: `*.test.ts` or `*.test.tsx`**
215
-
216
- ### SHOULD: Test Critical Paths
217
-
218
- **SHOULD test:**
219
- - Key user interactions
220
- - Error handling
221
- - Edge cases
222
- - Critical business logic
223
-
224
- ## RBAC & RLS Standard
225
-
226
- ### MUST: Use Helper Functions
227
-
228
- **All RLS policies MUST use helper functions with:**
229
- - `STABLE` attribute
230
- - `SECURITY DEFINER` attribute
231
- - `SET search_path TO 'public'`
232
-
233
- ### MUST: Follow Policy Naming
234
-
235
- **RLS policies MUST follow pattern: `rbac_{operation}_{table_name}_{scope}`**
236
-
237
- Example: `rbac_select_users_organisation`
238
-
239
- ### MUST: Include Organisation Context
240
-
241
- **RLS policies MUST include `organisation_id` for multi-tenant isolation.**
242
-
243
- ### MUST: Include Super Admin Checks
244
-
245
- **RLS policies SHOULD include super admin checks where appropriate.**
246
-
247
- ## Standards Precedence
248
-
249
- When standards conflict, follow this order:
250
- 1. Security Standard (highest priority)
251
- 2. API & RPC Standard
252
- 3. Component Standard
253
- 4. Code Style Standard
254
- 5. Testing Standard
255
- 6. Documentation Standard
256
-
257
- ## Compliance Checklist
258
-
259
- Before committing code, verify:
260
- - [ ] RLS policies use helper functions (no subqueries)
261
- - [ ] RPCs follow naming convention
262
- - [ ] Components are accessible and typed
263
- - [ ] No `any` types used
264
- - [ ] Inputs are validated
265
- - [ ] Tests meet coverage requirements
266
- - [ ] No sensitive data in logs
267
- - [ ] Error messages are safe
268
-
269
- ## Reference
270
-
271
- **📚 Human-Readable Standard**: See [01-standards-compliance.md](../../packages/core/docs/standards/01-standards-compliance.md) for complete documentation.
272
-
273
- **Related Standards** (all have corresponding cursor rules):
274
- - **00-pace-core-compliance.mdc** - pace-core usage patterns
275
- - **02-project-structure.mdc** - Project structure and organization
276
- - **03-solid-principles.mdc** - SOLID architecture principles
277
- - **04-testing-standards.mdc** - Testing framework standards
278
- - **05-bug-reports-and-features.mdc** - Issue reporting templates
279
- - **06-code-quality.mdc** - Code quality and TypeScript standards
280
- - **07-tech-stack-compliance.mdc** - Tech stack and API/RPC standards
281
- - **08-markup-quality.mdc** - Markup and styling standards
282
- - **09-rbac-compliance.mdc** - RBAC and RLS standards
283
- - **10-error-handling-patterns.mdc** - Error handling patterns
284
- - **11-performance-optimization.mdc** - Performance optimization
285
- - **12-ci-cd-integration.mdc** - CI/CD integration patterns
@@ -1,270 +0,0 @@
1
- ---
2
- description: Enforce testing framework consistency and standards for consuming apps
3
- globs: ["**/*.{test,spec}.{ts,tsx}"]
4
- alwaysApply: false
5
- paceCoreVersion: "0.6.x"
6
- rulesVersion: "2025-01-28"
7
- ---
8
- # Testing Standards Guide
9
-
10
- **📚 Human-Readable Standard**: See [04-testing-standards.md](../../packages/core/docs/standards/04-testing-standards.md) for complete documentation.
11
-
12
- This guide ensures consistent, high-quality testing across consuming apps in the PACE suite.
13
-
14
- ## MUST: Meet Coverage Requirements
15
-
16
- **MUST achieve minimum coverage:**
17
- - ≥90% coverage for utils & hooks
18
- - ≥70% coverage for components
19
-
20
- **Verify coverage:**
21
- ```bash
22
- npm run test:coverage
23
- ```
24
-
25
- ## MUST: Use React Testing Library
26
-
27
- **MUST use React Testing Library + userEvent for all component tests.**
28
-
29
- ```tsx
30
- // ✅ CORRECT: React Testing Library + userEvent
31
- import { render, screen } from '@testing-library/react';
32
- import userEvent from '@testing-library/user-event';
33
- test('button clicks work', async () => {
34
- const user = userEvent.setup();
35
- const handleClick = vi.fn();
36
- render(<Button onClick={handleClick}>Click me</Button>);
37
- await user.click(screen.getByRole('button', { name: /click me/i }));
38
- expect(handleClick).toHaveBeenCalledTimes(1);
39
- });
40
-
41
- // ❌ WRONG: Enzyme or other testing libraries
42
- ```
43
-
44
- ## MUST: Colocate Tests
45
-
46
- **Tests MUST be colocated with source files:**
47
-
48
- ```
49
- src/
50
- ├── components/
51
- │ └── EventCard/
52
- │ ├── EventCard.tsx
53
- │ └── EventCard.test.tsx
54
- ├── hooks/
55
- │ ├── useEventData.ts
56
- │ └── useEventData.test.ts
57
- └── utils/
58
- ├── formatEvent.ts
59
- └── formatEvent.test.ts
60
- ```
61
-
62
- ## MUST: Use Vitest
63
-
64
- **MUST use Vitest for all testing:**
65
-
66
- ```typescript
67
- // vitest.config.ts
68
- import { defineConfig } from 'vitest/config';
69
-
70
- export default defineConfig({
71
- test: {
72
- environment: 'jsdom',
73
- setupFiles: ['./vitest.setup.ts'],
74
- coverage: {
75
- provider: 'v8',
76
- reporter: ['text', 'json', 'html'],
77
- thresholds: {
78
- lines: 80,
79
- functions: 80,
80
- branches: 80,
81
- statements: 80,
82
- },
83
- },
84
- },
85
- });
86
- ```
87
-
88
- ## MUST: Test User Behavior, Not Implementation
89
-
90
- **Tests MUST focus on what users see and do:**
91
-
92
- ```tsx
93
- // ❌ WRONG: Testing implementation (component.state.count)
94
- test('calls setState', () => { const component = render(<Counter />); expect(component.state.count).toBe(0); });
95
-
96
- // ✅ CORRECT: Testing user behavior (what user sees and does)
97
- test('displays count and increments on button click', async () => {
98
- const user = userEvent.setup();
99
- render(<Counter />);
100
- expect(screen.getByText('Count: 0')).toBeInTheDocument();
101
- await user.click(screen.getByRole('button', { name: /increment/i }));
102
- expect(screen.getByText('Count: 1')).toBeInTheDocument();
103
- });
104
- ```
105
-
106
- ## MUST: Use Accessible Queries
107
-
108
- **MUST prefer accessible queries (byRole, byLabelText, etc.):**
109
-
110
- ```tsx
111
- // ✅ CORRECT: Accessible queries (byRole, byLabelText, byText)
112
- screen.getByRole('button', { name: /submit/i });
113
- screen.getByLabelText(/email address/i);
114
-
115
- // ❌ AVOID: Non-accessible queries (getByTestId, getByClassName - use as last resort)
116
- ```
117
-
118
- ## SHOULD: Test Critical Paths
119
-
120
- **SHOULD test:**
121
- - User workflows and interactions
122
- - Error handling and edge cases
123
- - Form validation
124
- - Permission checks (RBAC)
125
- - Data loading states
126
- - Error states
127
-
128
- ## SHOULD: Use Descriptive Test Names
129
-
130
- **Test names SHOULD describe behavior:**
131
-
132
- ```tsx
133
- // ❌ WRONG - Vague
134
- test('button works', () => { ... });
135
-
136
- // ✅ CORRECT - Descriptive
137
- test('increments counter when increment button is clicked', () => { ... });
138
- test('displays error message when API call fails', () => { ... });
139
- ```
140
-
141
- ## SHOULD: Group Related Tests
142
-
143
- **SHOULD use `describe` blocks to group related tests:**
144
-
145
- ```tsx
146
- describe('EventCard', () => {
147
- describe('rendering', () => {
148
- test('displays event title', () => { ... });
149
- test('displays event date', () => { ... });
150
- });
151
-
152
- describe('interactions', () => {
153
- test('calls onEdit when edit button clicked', () => { ... });
154
- test('calls onDelete when delete button clicked', () => { ... });
155
- });
156
- });
157
- ```
158
-
159
- ## MUST: Avoid Unnecessary Mocks
160
-
161
- **MUST NOT mock unless necessary:**
162
-
163
- ```tsx
164
- // ❌ WRONG: Unnecessary mock (global.fetch = mockFetch)
165
- // ✅ CORRECT: Use real implementation or MSW
166
- import { server } from './mocks/server';
167
- server.use(rest.get('/api/events', (req, res, ctx) => res(ctx.json([{ id: '1', name: 'Event' }]))));
168
- ```
169
-
170
- ## MUST: Test Async Code Properly
171
-
172
- **MUST handle async operations correctly:**
173
-
174
- ```tsx
175
- // ✅ CORRECT: Async testing with waitFor
176
- test('loads and displays events', async () => {
177
- render(<EventList />);
178
- expect(screen.getByText(/loading/i)).toBeInTheDocument();
179
- await waitFor(() => expect(screen.getByText('Event 1')).toBeInTheDocument());
180
- expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
181
- });
182
- ```
183
-
184
- ## MUST: Clean Up After Tests
185
-
186
- **MUST clean up resources:**
187
-
188
- ```tsx
189
- // ✅ CORRECT: Cleanup after tests
190
- afterEach(() => { cleanup(); vi.clearAllMocks(); });
191
- ```
192
-
193
- ## SHOULD: Use Test Utilities
194
-
195
- **SHOULD create reusable test utilities:**
196
-
197
- ```tsx
198
- // ✅ CORRECT: Reusable test utilities
199
- export function renderWithProviders(ui: React.ReactElement) {
200
- return render(<UnifiedAuthProvider supabaseClient={mockSupabase} appName="Test App">{ui}</UnifiedAuthProvider>);
201
- }
202
- // Usage: renderWithProviders(<MyComponent />);
203
- ```
204
-
205
- ## MUST: Include Timeout Parameters
206
-
207
- **Tests MUST include timeout parameters to prevent hanging:**
208
-
209
- ```tsx
210
- // ✅ CORRECT: Include timeout parameters to prevent hanging
211
- test('async operation completes', async () => {
212
- await waitFor(() => expect(screen.getByText('Loaded')).toBeInTheDocument(), { timeout: 5000 });
213
- }, { timeout: 10000 });
214
- ```
215
-
216
- ## Testing Checklist
217
-
218
- Before committing tests, verify:
219
- - [ ] Coverage meets requirements (≥90% utils, ≥70% components)
220
- - [ ] Using React Testing Library + userEvent
221
- - [ ] Tests are colocated with source files
222
- - [ ] Testing user behavior, not implementation
223
- - [ ] Using accessible queries (byRole, byLabelText)
224
- - [ ] Test names are descriptive
225
- - [ ] Related tests grouped with describe
226
- - [ ] No unnecessary mocks
227
- - [ ] Async code tested properly
228
- - [ ] Cleanup after tests
229
- - [ ] Timeout parameters included
230
-
231
- ## Test Structure Template
232
-
233
- ```tsx
234
- import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
235
- import { render, screen, waitFor } from '@testing-library/react';
236
- import userEvent from '@testing-library/user-event';
237
- import { ComponentName } from './ComponentName';
238
-
239
- describe('ComponentName', () => {
240
- beforeEach(() => {
241
- // Setup
242
- });
243
-
244
- afterEach(() => {
245
- // Cleanup
246
- vi.clearAllMocks();
247
- });
248
-
249
- describe('rendering', () => {
250
- test('renders correctly', () => {
251
- render(<ComponentName />);
252
- // Assertions
253
- });
254
- });
255
-
256
- describe('interactions', () => {
257
- test('handles user interaction', async () => {
258
- const user = userEvent.setup();
259
- render(<ComponentName />);
260
- // Test interaction
261
- });
262
- });
263
- });
264
- ```
265
-
266
- ## Reference
267
-
268
- - React Testing Library: https://testing-library.com/react
269
- - Vitest: https://vitest.dev
270
- - Testing Standards: See `06-testing-and-docs-standard.md` in pace-core docs