@jmruthers/pace-core 0.6.6 → 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 (246) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +255 -0
  4. package/audit-tool/audits/03-architecture.cjs +196 -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 +544 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +301 -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 +291 -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 +241 -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-7PMH7XN7.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-DlsCaR5v.d.ts} +26 -16
  28. package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
  29. package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
  30. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  31. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  32. package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
  33. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  34. package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
  35. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  36. package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
  37. package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
  38. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  39. package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
  40. package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
  41. package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
  42. package/dist/components.d.ts +5 -4
  43. package/dist/components.js +27 -32
  44. package/dist/eslint-rules/index.cjs +22 -9
  45. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  46. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  47. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  48. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
  49. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  50. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  51. package/dist/hooks.d.ts +5 -5
  52. package/dist/hooks.js +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +18 -17
  55. package/dist/rbac/index.js +6 -6
  56. package/dist/theming/runtime.d.ts +14 -1
  57. package/dist/theming/runtime.js +1 -1
  58. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  59. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  60. package/dist/utils.d.ts +2 -2
  61. package/dist/utils.js +8 -8
  62. package/docs/README.md +1 -1
  63. package/docs/api/modules.md +47 -31
  64. package/docs/api-reference/components.md +18 -20
  65. package/docs/api-reference/hooks.md +80 -80
  66. package/docs/api-reference/types.md +1 -1
  67. package/docs/api-reference/utilities.md +1 -1
  68. package/docs/architecture/README.md +1 -1
  69. package/docs/core-concepts/events.md +3 -3
  70. package/docs/core-concepts/organisations.md +6 -6
  71. package/docs/core-concepts/permissions.md +6 -6
  72. package/docs/documentation-index.md +12 -18
  73. package/docs/getting-started/documentation-index.md +1 -1
  74. package/docs/getting-started/examples/README.md +4 -4
  75. package/docs/getting-started/examples/full-featured-app.md +1 -1
  76. package/docs/getting-started/faq.md +2 -2
  77. package/docs/getting-started/quick-reference.md +4 -4
  78. package/docs/implementation-guides/authentication.md +15 -15
  79. package/docs/implementation-guides/component-styling.md +1 -1
  80. package/docs/implementation-guides/data-tables.md +126 -33
  81. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  82. package/docs/implementation-guides/dynamic-colors.md +3 -3
  83. package/docs/implementation-guides/file-upload-storage.md +2 -2
  84. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  85. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  86. package/docs/implementation-guides/large-datasets.md +3 -2
  87. package/docs/implementation-guides/organisation-security.md +2 -2
  88. package/docs/implementation-guides/performance.md +2 -2
  89. package/docs/implementation-guides/permission-enforcement.md +1 -1
  90. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  91. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  92. package/docs/rbac/README.md +5 -5
  93. package/docs/rbac/advanced-patterns.md +6 -6
  94. package/docs/rbac/api-reference.md +20 -20
  95. package/docs/rbac/event-based-apps.md +3 -3
  96. package/docs/rbac/examples.md +41 -41
  97. package/docs/rbac/getting-started.md +37 -37
  98. package/docs/rbac/performance.md +1 -1
  99. package/docs/rbac/quick-start.md +52 -52
  100. package/docs/rbac/secure-client-protection.md +1 -1
  101. package/docs/rbac/troubleshooting.md +1 -1
  102. package/docs/security/README.md +5 -5
  103. package/docs/standards/0-standards-overview.md +220 -0
  104. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
  105. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  106. package/docs/standards/3-architecture-standards.md +606 -0
  107. package/docs/standards/4-code-quality-standards.md +728 -0
  108. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  109. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  110. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  111. package/docs/standards/8-testing-documentation-standards.md +401 -0
  112. package/docs/standards/9-operations-standards.md +1102 -0
  113. package/docs/standards/README.md +203 -104
  114. package/docs/troubleshooting/README.md +4 -4
  115. package/docs/troubleshooting/common-issues.md +2 -2
  116. package/docs/troubleshooting/debugging.md +9 -9
  117. package/docs/troubleshooting/migration.md +4 -4
  118. package/eslint-config-pace-core.cjs +21 -10
  119. package/package.json +6 -5
  120. package/scripts/install-cursor-rules.cjs +11 -243
  121. package/scripts/install-eslint-config.cjs +284 -0
  122. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  123. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  124. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
  125. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  126. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  127. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  128. package/src/__tests__/templates/component.test.template.tsx +18 -15
  129. package/src/components/Calendar/Calendar.tsx +201 -47
  130. package/src/components/ContextSelector/ContextSelector.tsx +137 -153
  131. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  132. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  133. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  134. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  135. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  136. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  137. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  138. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  139. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  140. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  141. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  142. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  143. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  144. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  145. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  146. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  147. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  148. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  149. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  150. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  151. package/src/components/DataTable/components/index.ts +2 -1
  152. package/src/components/DataTable/types.ts +0 -18
  153. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  154. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  155. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  156. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  157. package/src/components/Dialog/Dialog.test.tsx +1 -0
  158. package/src/components/Dialog/Dialog.tsx +25 -8
  159. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  160. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  161. package/src/components/FileUpload/FileUpload.tsx +112 -130
  162. package/src/components/Progress/Progress.tsx +2 -4
  163. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  164. package/src/components/Select/Select.tsx +86 -77
  165. package/src/components/Select/types.ts +3 -0
  166. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  167. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  168. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  169. package/src/hooks/public/usePublicEvent.ts +5 -5
  170. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  171. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  172. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  173. package/src/hooks/useAppConfig.ts +2 -2
  174. package/src/hooks/useEventTheme.test.ts +7 -7
  175. package/src/hooks/useEventTheme.ts +1 -4
  176. package/src/hooks/useFileDisplay.ts +2 -2
  177. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  178. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  179. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  180. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  181. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  182. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  183. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  184. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  185. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  186. package/src/styles/core.css +7 -0
  187. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  188. package/src/theming/parseEventColours.ts +22 -10
  189. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  190. package/src/utils/storage/README.md +1 -1
  191. package/cursor-rules/01-standards-compliance.mdc +0 -285
  192. package/cursor-rules/04-testing-standards.mdc +0 -270
  193. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  194. package/cursor-rules/06-code-quality.mdc +0 -311
  195. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  196. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  197. package/cursor-rules/11-performance-optimization.mdc +0 -169
  198. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  199. package/dist/DataTable-LRJL4IRV.js +0 -15
  200. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  201. package/dist/eslint-rules/rules/components.cjs +0 -113
  202. package/dist/eslint-rules/rules/imports.cjs +0 -102
  203. package/docs/best-practices/README.md +0 -472
  204. package/docs/best-practices/accessibility.md +0 -604
  205. package/docs/best-practices/common-patterns.md +0 -516
  206. package/docs/best-practices/deployment.md +0 -1103
  207. package/docs/best-practices/performance.md +0 -1328
  208. package/docs/best-practices/security.md +0 -940
  209. package/docs/best-practices/testing.md +0 -1034
  210. package/docs/rbac/compliance/compliance-guide.md +0 -544
  211. package/docs/standards/01-standards-compliance.md +0 -188
  212. package/docs/standards/03-solid-principles.md +0 -39
  213. package/docs/standards/04-testing-standards.md +0 -36
  214. package/docs/standards/05-bug-reports-and-features.md +0 -27
  215. package/docs/standards/06-code-quality.md +0 -34
  216. package/docs/standards/07-tech-stack-compliance.md +0 -30
  217. package/docs/standards/10-error-handling-patterns.md +0 -401
  218. package/docs/standards/11-performance-optimization.md +0 -348
  219. package/docs/standards/12-ci-cd-integration.md +0 -370
  220. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  221. package/scripts/audit/audit-compliance.cjs +0 -1295
  222. package/scripts/audit/audit-components.cjs +0 -260
  223. package/scripts/audit/audit-rbac.cjs +0 -954
  224. package/scripts/audit/audit-standards.cjs +0 -1268
  225. package/scripts/audit/index.cjs +0 -1927
  226. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  227. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  228. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  229. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  230. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  231. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  232. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  233. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  234. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  235. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  236. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  237. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  238. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  239. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  240. package/src/components/DataTable/utils/debugTools.ts +0 -514
  241. package/src/eslint-rules/index.cjs +0 -22
  242. package/src/eslint-rules/rules/components.cjs +0 -113
  243. package/src/eslint-rules/rules/imports.cjs +0 -102
  244. package/src/eslint-rules/rules/rbac.cjs +0 -790
  245. package/src/eslint-rules/utils/helpers.cjs +0 -42
  246. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -0,0 +1,419 @@
1
+ ---
2
+ description: Enforce code quality standards including TypeScript, ESLint, formatting, performance, and accessibility
3
+ globs: ["src/**/*.{ts,tsx,js,jsx}"]
4
+ alwaysApply: false
5
+ paceCoreVersion: "0.6.x"
6
+ rulesVersion: "2025-01-28"
7
+ ---
8
+ # Code Quality Guide
9
+
10
+ **📚 Human-Readable Standard**: See [4-code-quality-standards.md](../../packages/core/docs/standards/4-code-quality-standards.md) for complete documentation.
11
+
12
+ This guide enforces code quality standards to ensure maintainable, performant, and accessible code.
13
+
14
+ ## AI Agent Instructions
15
+
16
+ **When writing or modifying code, ALWAYS:**
17
+ 1. **Use strict TypeScript** - Never use `any`, always use proper types or `unknown` with type guards
18
+ 2. **Use discriminated unions** - Replace boolean flags with discriminated unions for better type safety
19
+ 3. **Use ReadonlyArray** - Use `ReadonlyArray` for immutable arrays
20
+ 4. **Ensure accessibility** - All components must be keyboard accessible, have ARIA labels, and visible focus states
21
+ 5. **Use semantic HTML** - Use semantic elements (`<main>`, `<section>`, `<article>`, etc.) instead of `<div>` wrappers
22
+ 6. **Memoize appropriately** - Use `useMemo` and `useCallback` for expensive computations and stable references
23
+ 7. **Early returns** - Use early returns to reduce nesting and improve readability
24
+
25
+ **Decision Tree: Type Safety**
26
+ ```
27
+ 1. What type should I use?
28
+ ├─ Known structure → Interface or type
29
+ ├─ Truly unknown → unknown (with type guard)
30
+ └─ Multiple variants → Discriminated union (not boolean flags)
31
+
32
+ 2. Is this an array that shouldn't be mutated?
33
+ ├─ YES → ReadonlyArray<T>
34
+ └─ NO → Array<T> or T[]
35
+
36
+ 3. Do I need multiple states?
37
+ ├─ YES → Discriminated union (type: 'loading' | 'success' | 'error')
38
+ └─ NO → Single type
39
+ ```
40
+
41
+ ## TypeScript Standards
42
+
43
+ ### MUST: Use Strict Mode
44
+
45
+ **TypeScript MUST use strict mode:**
46
+
47
+ ```json
48
+ // tsconfig.json
49
+ {
50
+ "compilerOptions": {
51
+ "strict": true,
52
+ "noImplicitAny": true,
53
+ "strictNullChecks": true,
54
+ "strictFunctionTypes": true,
55
+ "strictBindCallApply": true,
56
+ "strictPropertyInitialization": true,
57
+ "noImplicitThis": true,
58
+ "alwaysStrict": true
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### MUST NOT: Use `any`
64
+
65
+ **MUST NOT use `any` type. Use `unknown` if type is truly unknown:**
66
+
67
+ ```tsx
68
+ // ❌ WRONG: Using any
69
+ function processData(data: any) { return data.value; }
70
+
71
+ // ✅ CORRECT: Using unknown with type guard or proper types
72
+ function processData(data: unknown) {
73
+ if (typeof data === 'object' && data !== null && 'value' in data) {
74
+ return (data as { value: string }).value;
75
+ }
76
+ throw new Error('Invalid data');
77
+ }
78
+ // Or: interface Data { value: string; } function processData(data: Data) { return data.value; }
79
+ ```
80
+
81
+ ### MUST: Use Discriminated Unions
82
+
83
+ **MUST use discriminated unions instead of boolean flags:**
84
+
85
+ ```tsx
86
+ // ❌ WRONG: Boolean flags (confusing: what if both are true?)
87
+ interface User { isAdmin: boolean; isGuest: boolean; }
88
+
89
+ // ✅ CORRECT: Discriminated union
90
+ type User = { type: 'admin'; permissions: Permission[] } | { type: 'guest'; limitedAccess: boolean } | { type: 'user'; role: UserRole };
91
+ ```
92
+
93
+ ### SHOULD: Use ReadonlyArray
94
+
95
+ **SHOULD use ReadonlyArray for immutable arrays:**
96
+
97
+ ```tsx
98
+ // ✅ CORRECT - ReadonlyArray
99
+ function processItems(items: ReadonlyArray<Item>) {
100
+ // Can't mutate items
101
+ return items.map(item => transform(item));
102
+ }
103
+ ```
104
+
105
+ ## ESLint Configuration
106
+
107
+ **Note**: ESLint configuration and enforcement is handled by ESLint (Layer 3). See [4-code-quality-standards.md](../../packages/core/docs/standards/4-code-quality-standards.md) for complete ESLint setup instructions.
108
+
109
+ **MUST:**
110
+ - Use pace-core ESLint config
111
+ - Fix all ESLint errors before committing
112
+ - Run `npm run lint` before committing
113
+
114
+ ## Code Formatting
115
+
116
+ ### MUST: Use Consistent Formatting
117
+
118
+ **MUST use Prettier or equivalent for consistent formatting:**
119
+
120
+ ```json
121
+ // .prettierrc
122
+ {
123
+ "semi": true,
124
+ "singleQuote": true,
125
+ "tabWidth": 2,
126
+ "trailingComma": "es5",
127
+ "printWidth": 100
128
+ }
129
+ ```
130
+
131
+ ### MUST: Format Before Committing
132
+
133
+ **MUST format code before committing:**
134
+
135
+ ```bash
136
+ npm run format
137
+ # Or use pre-commit hook
138
+ ```
139
+
140
+ ## Performance Considerations
141
+
142
+ ### SHOULD: Optimize Re-renders
143
+
144
+ **SHOULD use React.memo, useMemo, useCallback appropriately:**
145
+
146
+ ```tsx
147
+ // ✅ CORRECT: Memoize expensive computations, callbacks, and components
148
+ const expensiveValue = useMemo(() => computeExpensiveValue(data), [data]);
149
+ const handleClick = useCallback(() => doSomething(id), [id]);
150
+ const ExpensiveComponent = React.memo(({ data }) => <div>{/* ... */}</div>);
151
+ ```
152
+
153
+ ### SHOULD: Avoid Unnecessary Re-renders
154
+
155
+ **SHOULD avoid causing unnecessary re-renders:**
156
+
157
+ ```tsx
158
+ // ❌ WRONG: New object on every render (causes unnecessary re-renders)
159
+ function Component({ items }) { const config = { items, enabled: true }; return <Child config={config} />; }
160
+
161
+ // ✅ CORRECT: Memoize object
162
+ function Component({ items }) {
163
+ const config = useMemo(() => ({ items, enabled: true }), [items]);
164
+ return <Child config={config} />;
165
+ }
166
+ ```
167
+
168
+ ### SHOULD: Lazy Load Heavy Components
169
+
170
+ **SHOULD lazy load heavy components:**
171
+
172
+ ```tsx
173
+ // ✅ CORRECT: Lazy load heavy components
174
+ import { lazy, Suspense } from 'react';
175
+ const HeavyComponent = lazy(() => import('./HeavyComponent'));
176
+ function App() {
177
+ return <Suspense fallback={<Loading />}><HeavyComponent /></Suspense>;
178
+ }
179
+ ```
180
+
181
+ ## Accessibility Requirements
182
+
183
+ **MUST** ensure all components and pages meet WCAG 2.1 Level AA standards.
184
+
185
+ ### Core Principles
186
+
187
+ 1. **Semantic HTML** - Use semantic elements (`<main>`, `<section>`, `<article>`, `<nav>`, etc.) instead of `<div>` wrappers
188
+ 2. **Keyboard Navigation** - All interactive elements must be accessible via keyboard
189
+ 3. **ARIA Labels** - Provide clear labels for screen readers when visible text isn't sufficient
190
+ 4. **Focus Management** - Visible focus indicators on all interactive elements
191
+ 5. **Color Contrast** - Text must meet 4.5:1 contrast ratio (WCAG AA)
192
+
193
+ ### Implementation Requirements
194
+
195
+ ```tsx
196
+ // ✅ CORRECT - Semantic HTML with ARIA
197
+ <main>
198
+ <h1>Page Title</h1>
199
+ <section aria-labelledby="section-title">
200
+ <h2 id="section-title">Section Title</h2>
201
+ <Button
202
+ aria-label="Delete user"
203
+ aria-describedby="delete-help"
204
+ >
205
+ Delete
206
+ </Button>
207
+ <span id="delete-help" className="sr-only">
208
+ Permanently removes the user account
209
+ </span>
210
+ </section>
211
+ </main>
212
+
213
+ // ❌ WRONG - Non-semantic structure
214
+ <div>
215
+ <div className="title">Page Title</div>
216
+ <div>
217
+ <button>Delete</button>
218
+ </div>
219
+ </div>
220
+ ```
221
+
222
+ ### Keyboard Navigation
223
+
224
+ **MUST** ensure all interactive elements are keyboard accessible:
225
+
226
+ ```tsx
227
+ // ✅ CORRECT - pace-core components handle keyboard navigation automatically
228
+ import { Button, DataTable } from '@jmruthers/pace-core';
229
+
230
+ <Button onClick={handleClick}>Click me</Button>
231
+ <DataTable data={data} columns={columns} />
232
+ ```
233
+
234
+ ### Screen Reader Support
235
+
236
+ **MUST** provide appropriate ARIA attributes:
237
+
238
+ ```tsx
239
+ // ✅ CORRECT - ARIA labels for icons
240
+ <Button aria-label="Close dialog">
241
+ <Icon name="x" aria-hidden="true" />
242
+ </Button>
243
+
244
+ // ✅ CORRECT - Error messages with role="alert"
245
+ {error && (
246
+ <div role="alert" aria-live="polite">
247
+ {error.message}
248
+ </div>
249
+ )}
250
+
251
+ // ✅ CORRECT - Loading states
252
+ <div role="status" aria-live="polite" aria-busy={loading}>
253
+ {loading && <span className="sr-only">Loading data...</span>}
254
+ {loading ? <Spinner /> : <Content />}
255
+ </div>
256
+ ```
257
+
258
+ ### Testing Accessibility
259
+
260
+ **MUST** test with:
261
+ - Keyboard navigation (Tab, Enter, Space, Arrow keys)
262
+ - Screen readers (NVDA, JAWS, VoiceOver)
263
+ - Automated tools (axe DevTools, WAVE, Lighthouse)
264
+
265
+ **Accessibility Checklist:**
266
+ - [ ] All interactive elements keyboard accessible
267
+ - [ ] Visible focus indicators on all interactive elements
268
+ - [ ] ARIA labels provided for icons and images
269
+ - [ ] Semantic HTML used appropriately
270
+ - [ ] Error messages properly associated with form fields
271
+ - [ ] Color contrast meets WCAG AA (4.5:1 for text)
272
+ - [ ] Screen reader announcements work correctly
273
+ - [ ] Focus management in modals and dynamic content
274
+
275
+ ## Code Review Checklist
276
+
277
+ **Before submitting code for review, verify:**
278
+
279
+ - [ ] TypeScript strict mode enabled
280
+ - [ ] No `any` types used
281
+ - [ ] ESLint passes with no errors
282
+ - [ ] Code is formatted consistently
283
+ - [ ] Performance optimizations applied where needed
284
+ - [ ] Accessibility requirements met
285
+ - [ ] Semantic HTML used
286
+ - [ ] ARIA labels provided
287
+ - [ ] Keyboard navigation works
288
+ - [ ] Focus indicators visible
289
+ - [ ] Code is readable and maintainable
290
+ - [ ] Comments explain "why", not "what"
291
+
292
+ ## Code Complexity
293
+
294
+ ### SHOULD: Keep Functions Small
295
+
296
+ **Functions SHOULD be small and focused:**
297
+
298
+ ```tsx
299
+ // ❌ WRONG: Large function (100+ lines, multiple responsibilities)
300
+ function processUserData(user) { /* 100+ lines of logic */ }
301
+
302
+ // ✅ CORRECT: Small, focused functions
303
+ function validateUser(user: User): ValidationResult { /* Validation logic */ }
304
+ function transformUser(user: User): TransformedUser { /* Transformation logic */ }
305
+ function processUserData(user: User) {
306
+ const validation = validateUser(user);
307
+ if (!validation.valid) return validation;
308
+ return transformUser(user);
309
+ }
310
+ ```
311
+
312
+ ### SHOULD: Limit Cyclomatic Complexity
313
+
314
+ **Functions SHOULD have low cyclomatic complexity (< 10):**
315
+
316
+ ```tsx
317
+ // ❌ WRONG: High complexity (many nested conditions)
318
+ function processData(data) { if (condition1) { if (condition2) { if (condition3) { /* ... */ } } } }
319
+
320
+ // ✅ CORRECT: Lower complexity (early returns)
321
+ function processData(data) { if (!condition1) return; if (!condition2) return; if (!condition3) return; /* Process */ }
322
+ ```
323
+
324
+ ## Error Handling
325
+
326
+ ### MUST: Handle Errors Gracefully
327
+
328
+ **MUST handle errors and provide user feedback:**
329
+
330
+ ```tsx
331
+ // ✅ CORRECT: Handle errors gracefully with user feedback
332
+ try {
333
+ const data = await fetchData();
334
+ setData(data);
335
+ } catch (error) {
336
+ logger.error('Failed to fetch data', error);
337
+ toast.error('Failed to load data. Please try again.');
338
+ }
339
+ ```
340
+
341
+ ### MUST: Use Type-Safe Error Handling
342
+
343
+ **MUST use type-safe error handling:**
344
+
345
+ ```tsx
346
+ // ✅ CORRECT: Type-safe error handling
347
+ function isApiError(error: unknown): error is ApiError {
348
+ return typeof error === 'object' && error !== null && 'code' in error && 'message' in error;
349
+ }
350
+ try {
351
+ await apiCall();
352
+ } catch (error) {
353
+ if (isApiError(error)) handleApiError(error);
354
+ else handleUnknownError(error);
355
+ }
356
+ ```
357
+
358
+ ## Common Mistakes to Avoid
359
+
360
+ **When writing code, NEVER:**
361
+ 1. **Use `any` type** - Always use proper types or `unknown` with type guards
362
+ ```tsx
363
+ // ❌ WRONG
364
+ function process(data: any) {
365
+ return data.value;
366
+ }
367
+
368
+ // ✅ CORRECT
369
+ function process(data: unknown) {
370
+ if (typeof data === 'object' && data !== null && 'value' in data) {
371
+ return (data as { value: string }).value;
372
+ }
373
+ throw new Error('Invalid data');
374
+ }
375
+ ```
376
+
377
+ 2. **Use boolean flags for multiple states** - Use discriminated unions
378
+ ```tsx
379
+ // ❌ WRONG
380
+ interface User { isAdmin: boolean; isGuest: boolean; }
381
+
382
+ // ✅ CORRECT
383
+ type User =
384
+ | { type: 'admin'; permissions: Permission[] }
385
+ | { type: 'guest'; limitedAccess: boolean }
386
+ | { type: 'user'; role: UserRole };
387
+ ```
388
+
389
+ 3. **Forget accessibility** - Always ensure keyboard navigation, ARIA labels, and semantic HTML
390
+ 4. **Create mutable arrays when they shouldn't change** - Use `ReadonlyArray`
391
+ 5. **Skip memoization for expensive operations** - Use `useMemo` and `useCallback` appropriately
392
+
393
+ ## Code Quality Checklist
394
+
395
+ Before committing, verify:
396
+ - [ ] TypeScript strict mode enabled
397
+ - [ ] No `any` types (use `unknown` with type guards)
398
+ - [ ] Discriminated unions used instead of boolean flags
399
+ - [ ] `ReadonlyArray` used for immutable arrays
400
+ - [ ] Naming conventions followed (hooks: `use*`, providers: `*Provider`, etc.)
401
+ - [ ] Pure functions preferred (no side effects)
402
+ - [ ] Early returns used to reduce nesting
403
+ - [ ] Complex logic extracted to helpers
404
+ - [ ] Components are small and focused
405
+ - [ ] Functional components only (no class components)
406
+ - [ ] Hook dependencies are complete
407
+ - [ ] Memoization used when appropriate
408
+ - [ ] Accessibility requirements met (WCAG 2.1 AA)
409
+ - [ ] Keyboard navigation supported
410
+ - [ ] ARIA labels provided where needed
411
+ - [ ] Semantic HTML used appropriately
412
+
413
+ ## Reference
414
+
415
+ **Note**: ESLint configuration details and mechanical type checking are handled by ESLint (Layer 3). See [4-code-quality-standards.md](../../packages/core/docs/standards/4-code-quality-standards.md) for complete enforcement details.
416
+
417
+ - TypeScript Handbook: https://www.typescriptlang.org/docs/
418
+ - React Performance: https://react.dev/learn/render-and-commit
419
+ - Web Accessibility: https://www.w3.org/WAI/
@@ -7,15 +7,49 @@ rulesVersion: "2025-01-28"
7
7
  ---
8
8
  # Markup Quality Guide
9
9
 
10
- **📚 Human-Readable Standard**: See [08-markup-quality.md](../../packages/core/docs/standards/08-markup-quality.md) for complete documentation including **CRITICAL CSS configuration requirements**.
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
11
 
12
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
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
+
14
48
  ## ⚠️ CRITICAL: CSS Configuration Required
15
49
 
16
50
  **Before using pace-core components, you MUST configure CSS correctly.** Without proper configuration, pace-core components will appear unstyled or with incorrect styling.
17
51
 
18
- **MUST read the standard for complete CSS setup instructions**: [08-markup-quality.md](../../packages/core/docs/standards/08-markup-quality.md)
52
+ **MUST read the standard for complete CSS setup instructions**: [5-styling-standards.md](../../packages/core/docs/standards/5-styling-standards.md)
19
53
 
20
54
  **Quick checklist:**
21
55
  - [ ] `src/app.css` exists with `@import "tailwindcss";`
@@ -38,18 +72,29 @@ This guide enforces clean markup standards, semantic HTML usage, and proper pace
38
72
 
39
73
  ```tsx
40
74
  // ❌ WRONG: Custom button or native HTML element
41
- <button className="btn-primary">Click me</button>
42
- <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
+ />
43
84
 
44
85
  // ✅ CORRECT: Use pace-core components
45
86
  import { Button, Input } from '@jmruthers/pace-core';
46
- <Button>Click me</Button>
47
- <Input type="text" />
87
+ <Button onClick={handleClick}>Click me</Button>
88
+ <Input
89
+ type="text"
90
+ value={value}
91
+ onChange={handleChange}
92
+ />
48
93
  ```
49
94
 
50
95
  ### MUST NOT: Add Custom Styles to pace-core Components
51
96
 
52
- **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.**
53
98
 
54
99
  ```tsx
55
100
  // ❌ WRONG: Overriding pace-core component styles
@@ -111,7 +156,7 @@ import { Button, Input } from '@jmruthers/pace-core';
111
156
 
112
157
  ### MUST: Prefer Semantic HTML (Limit `<div>`)
113
158
 
114
- **You MUST prefer semantic HTML elements** (`<main>`, `<section>`, `<article>`, `<header>`, `<footer>`, `<nav>`, lists, etc.).
159
+ **ALWAYS prefer semantic HTML elements** (`<main>`, `<section>`, `<article>`, `<header>`, `<footer>`, `<nav>`, lists, etc.).
115
160
  Using semantic elements improves accessibility, maintainability, and consistency.
116
161
 
117
162
  #### `<div>` usage policy
@@ -470,8 +515,8 @@ Before committing code, verify:
470
515
 
471
516
  ## Reference
472
517
 
473
- - **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
474
519
  - **Semantic HTML**: https://developer.mozilla.org/en-US/docs/Glossary/Semantics
475
520
  - **React Fragments**: https://react.dev/reference/react/Fragment
476
- - **Accessibility**: See `06-code-quality.mdc` for accessibility requirements
521
+ - **Accessibility**: See [04-code-quality.mdc](./04-code-quality.mdc) for accessibility requirements
477
522
  - **When in doubt**: Remove the element, remove the style, and rely on pace-core or semantic HTML
@@ -1,18 +1,48 @@
1
1
  ---
2
- description: Enforce RBAC contract compliance - strict rules for permission checking, page protection, and RBAC usage patterns
3
- globs: ["src/**/*.{ts,tsx,js,jsx}"]
2
+ description: Enforce RBAC contract compliance, RLS policy patterns, and security requirements
3
+ globs: ["src/**/*.{ts,tsx,js,jsx}", "supabase/migrations/**/*.sql"]
4
4
  alwaysApply: false
5
5
  paceCoreVersion: "0.6.x"
6
6
  rulesVersion: "2025-01-28"
7
7
  ---
8
- # RBAC Compliance Guide
8
+ # Security & RBAC Standards Guide
9
9
 
10
- **📚 Human-Readable Standard**: See [09-rbac-compliance.md](../../packages/core/docs/standards/09-rbac-compliance.md) for complete documentation including RLS policy patterns, helper functions, and security requirements.
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
11
 
12
- This guide enforces the **mandatory RBAC contract** between pace-core and consuming apps. These rules are **enforced by ESLint** and violations will result in build errors.
12
+ This guide enforces the **mandatory RBAC contract** and security patterns between pace-core and consuming apps.
13
13
 
14
14
  **⚠️ CRITICAL**: This contract is **non-negotiable**. See [RBAC Contract](../../packages/core/docs/rbac/RBAC_CONTRACT.md) for complete documentation.
15
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
+
16
46
  ## MUST: Use PagePermissionGuard for All Protected Pages
17
47
 
18
48
  **MUST wrap all protected pages with `PagePermissionGuard`:**
@@ -358,6 +388,32 @@ These rules are enforced by ESLint rules (all ERROR severity):
358
388
  7. **`no-resource-permission-string-literals`** - Detects string literals in `useResourcePermissions` calls
359
389
  8. **`no-permission-wrapper-functions`** - Detects wrapper functions around pace-core permission hooks
360
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
+
361
417
  ## Compliance Checklist
362
418
 
363
419
  Before committing RBAC-related code, verify:
@@ -459,4 +515,4 @@ $$;
459
515
  - **Migration Guide**: `packages/core/docs/rbac/MIGRATION_GUIDE.md` - Migrating to RBAC Contract v2.0.0
460
516
  - **Quick Start**: `packages/core/docs/rbac/quick-start.md` - Getting started guide
461
517
  - **API Reference**: `packages/core/docs/rbac/api-reference.md` - Complete API documentation
462
- - **RLS Standards**: `packages/core/docs/standards/09-rbac-compliance.md` - RLS policy patterns and super-admin requirements
518
+ - **RLS Standards**: [6-security-rbac-standards.md](../../packages/core/docs/standards/6-security-rbac-standards.md) - RLS policy patterns and super-admin requirements