@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.
- package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +47 -31
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -7,15 +7,41 @@ rulesVersion: "2025-01-28"
|
|
|
7
7
|
---
|
|
8
8
|
# pace-core Compliance Guide
|
|
9
9
|
|
|
10
|
-
**📚 Human-Readable Standard**: See [
|
|
10
|
+
**📚 Human-Readable Standard**: See [1-pace-core-compliance-standards.md](../../packages/core/docs/standards/1-pace-core-compliance-standards.md) for complete documentation.
|
|
11
11
|
|
|
12
12
|
This guide ensures consuming apps use pace-core components, hooks, and utilities correctly, preventing duplication and maintaining consistency across the PACE suite.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## AI Agent Instructions
|
|
15
|
+
|
|
16
|
+
**When writing or modifying code, ALWAYS:**
|
|
17
|
+
1. **Check pace-core first** - Before creating any component, hook, or utility, verify if pace-core provides it
|
|
18
|
+
2. **Use pace-core components** - Never use native HTML elements (`<button>`, `<input>`) when pace-core provides components
|
|
19
|
+
3. **Use pace-core hooks** - Never create custom hooks when pace-core provides equivalent functionality
|
|
20
|
+
4. **Use secure Supabase client** - Always use `useSecureSupabase()`, never `createClient()` for queries
|
|
21
|
+
5. **Read documentation** - Before using any pace-core component, check its documentation for required props and usage patterns
|
|
22
|
+
6. **Follow provider nesting** - Always nest providers in the correct order (QueryClientProvider → BrowserRouter → UnifiedAuthProvider → OrganisationProvider)
|
|
23
|
+
7. **Configure Vite correctly** - Always exclude `@jmruthers/pace-core` and `react-router-dom` from pre-bundling
|
|
24
|
+
|
|
25
|
+
**Decision Tree: Should I create this or use pace-core?**
|
|
26
|
+
```
|
|
27
|
+
1. What am I trying to create?
|
|
28
|
+
├─ Component (Button, Input, Card, etc.) → Use pace-core
|
|
29
|
+
├─ Hook (auth, permissions, debounce, etc.) → Use pace-core
|
|
30
|
+
├─ Utility (formatDate, cn, validation, etc.) → Use pace-core
|
|
31
|
+
└─ App-specific domain logic → Create custom (but follow pace-core patterns)
|
|
32
|
+
|
|
33
|
+
2. Does pace-core provide this?
|
|
34
|
+
├─ YES → Use pace-core (import from '@jmruthers/pace-core')
|
|
35
|
+
└─ NO → Check if it should be added to pace-core (for shared use)
|
|
36
|
+
|
|
37
|
+
3. Am I about to use native HTML?
|
|
38
|
+
├─ YES → Check if pace-core has equivalent component
|
|
39
|
+
└─ NO → Continue
|
|
40
|
+
```
|
|
15
41
|
|
|
16
42
|
## MUST: Use pace-core Instead of Custom Solutions
|
|
17
43
|
|
|
18
|
-
**
|
|
44
|
+
**ALWAYS use pace-core components, hooks, and utilities when they exist.** Creating custom solutions duplicates functionality and breaks consistency.
|
|
19
45
|
|
|
20
46
|
### Components
|
|
21
47
|
|
|
@@ -33,10 +59,28 @@ This guide ensures consuming apps use pace-core components, hooks, and utilities
|
|
|
33
59
|
- Import directly from `@radix-ui/*` - Use pace-core wrappers instead
|
|
34
60
|
- Import directly from `lucide-react` - Import icons from `@jmruthers/pace-core/icons` instead
|
|
35
61
|
|
|
36
|
-
**
|
|
62
|
+
**Examples:**
|
|
37
63
|
```tsx
|
|
38
|
-
// ❌ WRONG:
|
|
39
|
-
|
|
64
|
+
// ❌ WRONG: Native HTML button
|
|
65
|
+
<button className="btn-primary" onClick={handleClick}>
|
|
66
|
+
Click me
|
|
67
|
+
</button>
|
|
68
|
+
|
|
69
|
+
// ✅ CORRECT: pace-core Button component
|
|
70
|
+
import { Button } from '@jmruthers/pace-core';
|
|
71
|
+
<Button onClick={handleClick}>Click me</Button>
|
|
72
|
+
|
|
73
|
+
// ❌ WRONG: Native HTML input
|
|
74
|
+
<input
|
|
75
|
+
type="text"
|
|
76
|
+
className="form-input"
|
|
77
|
+
value={value}
|
|
78
|
+
onChange={handleChange}
|
|
79
|
+
/>
|
|
80
|
+
|
|
81
|
+
// ✅ CORRECT: pace-core Input component
|
|
82
|
+
import { Input } from '@jmruthers/pace-core';
|
|
83
|
+
<Input type="text" value={value} onChange={handleChange} />
|
|
40
84
|
```
|
|
41
85
|
|
|
42
86
|
### Hooks
|
|
@@ -81,8 +125,13 @@ This guide ensures consuming apps use pace-core components, hooks, and utilities
|
|
|
81
125
|
|
|
82
126
|
## MUST: Use Secure Supabase Client
|
|
83
127
|
|
|
84
|
-
**
|
|
85
|
-
|
|
128
|
+
**ALWAYS use `useSecureSupabase()` for all database operations.** Never use the base Supabase client directly for queries.
|
|
129
|
+
|
|
130
|
+
**When writing database code:**
|
|
131
|
+
1. Import: `import { useSecureSupabase } from '@jmruthers/pace-core/rbac'`
|
|
132
|
+
2. Call hook: `const secureSupabase = useSecureSupabase()`
|
|
133
|
+
3. Use for queries: `await secureSupabase.from('table').select('*')`
|
|
134
|
+
4. Never use: `createClient()` for queries (only for provider setup)
|
|
86
135
|
|
|
87
136
|
### Hard Requirements
|
|
88
137
|
|
|
@@ -174,16 +223,11 @@ const { data } = await supabase.from('users').select('*'); // Bypasses RLS
|
|
|
174
223
|
|
|
175
224
|
**NO OTHER EXCEPTIONS ARE PERMITTED** - All other uses of `createClient()` are security violations and MUST be fixed.
|
|
176
225
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- `rg "createClient\(" src` must return **exactly ONE match** in the file that creates the base client for `UnifiedAuthProvider`.
|
|
180
|
-
- That file MUST be one of: `main.tsx`, `App.tsx`, or `lib/supabase.ts` (or `.jsx`/`.js` equivalents).
|
|
181
|
-
- No `.from(` / `.rpc(` calls may be performed on an insecure client reference.
|
|
182
|
-
- All `useSecureSupabase()` calls should be without parameters.
|
|
226
|
+
**Note**: System-level validation of Supabase client usage is handled by the audit tool. See [1-pace-core-compliance-standards.md](../../packages/core/docs/standards/1-pace-core-compliance-standards.md) for complete enforcement details.
|
|
183
227
|
|
|
184
228
|
## MUST: Setup RBAC Before Use
|
|
185
229
|
|
|
186
|
-
**
|
|
230
|
+
**ALWAYS call `setupRBAC()` before any RBAC usage.** This is non-negotiable.
|
|
187
231
|
|
|
188
232
|
```tsx
|
|
189
233
|
// main.tsx - MUST be first
|
|
@@ -194,7 +238,7 @@ setupRBAC(supabase);
|
|
|
194
238
|
|
|
195
239
|
## MUST: Read Documentation Before Using Components
|
|
196
240
|
|
|
197
|
-
**
|
|
241
|
+
**ALWAYS read pace-core component documentation before using any component.** Never guess about props, usage patterns, or behavior.
|
|
198
242
|
|
|
199
243
|
### Where to Find Documentation
|
|
200
244
|
|
|
@@ -292,20 +336,97 @@ Before using any pace-core component:
|
|
|
292
336
|
- Document why custom solution is needed
|
|
293
337
|
- Follow pace-core patterns for consistency
|
|
294
338
|
|
|
295
|
-
## MUST:
|
|
339
|
+
## MUST: Provider Nesting Order
|
|
296
340
|
|
|
297
|
-
|
|
341
|
+
**⚠️ CRITICAL: Provider nesting order matters!** Incorrect nesting causes React context errors.
|
|
342
|
+
|
|
343
|
+
**MUST** nest providers in this exact order (outermost to innermost):
|
|
344
|
+
|
|
345
|
+
1. `QueryClientProvider` (outermost)
|
|
346
|
+
2. `BrowserRouter`
|
|
347
|
+
3. `UnifiedAuthProvider`
|
|
348
|
+
4. `OrganisationProvider`
|
|
349
|
+
5. `App` (innermost)
|
|
298
350
|
|
|
299
351
|
```tsx
|
|
352
|
+
// ✅ CORRECT: main.tsx
|
|
353
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
354
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
300
355
|
import { UnifiedAuthProvider, OrganisationProvider } from '@jmruthers/pace-core';
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
356
|
+
import { createClient } from '@supabase/supabase-js';
|
|
357
|
+
|
|
358
|
+
const queryClient = new QueryClient();
|
|
359
|
+
const supabase = createClient(
|
|
360
|
+
import.meta.env.VITE_SUPABASE_URL,
|
|
361
|
+
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
createRoot(document.getElementById("root")!).render(
|
|
365
|
+
<QueryClientProvider client={queryClient}>
|
|
366
|
+
<BrowserRouter>
|
|
367
|
+
<UnifiedAuthProvider supabaseClient={supabase} appName="YourApp">
|
|
368
|
+
<OrganisationProvider>
|
|
369
|
+
<App />
|
|
370
|
+
</OrganisationProvider>
|
|
371
|
+
</UnifiedAuthProvider>
|
|
372
|
+
</BrowserRouter>
|
|
373
|
+
</QueryClientProvider>
|
|
374
|
+
);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Common mistakes to avoid:**
|
|
378
|
+
- ❌ `BrowserRouter` inside `UnifiedAuthProvider` (causes Router context errors)
|
|
379
|
+
- ❌ `UnifiedAuthProvider` wrapping `BrowserRouter` (causes context errors)
|
|
380
|
+
- ❌ Missing `BrowserRouter` (causes `useNavigate` errors)
|
|
381
|
+
|
|
382
|
+
## MUST: Vite Configuration
|
|
383
|
+
|
|
384
|
+
**⚠️ CRITICAL: Vite configuration prevents React context mismatches!**
|
|
385
|
+
|
|
386
|
+
**MUST** configure Vite to exclude `@jmruthers/pace-core` and `react-router-dom` from pre-bundling:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// vite.config.ts
|
|
390
|
+
import { defineConfig } from 'vite';
|
|
391
|
+
import react from '@vitejs/plugin-react';
|
|
392
|
+
import path from 'path';
|
|
393
|
+
|
|
394
|
+
export default defineConfig({
|
|
395
|
+
plugins: [react()],
|
|
396
|
+
resolve: {
|
|
397
|
+
alias: {
|
|
398
|
+
'@': path.resolve(__dirname, './src'),
|
|
399
|
+
},
|
|
400
|
+
// CRITICAL: Dedupe React dependencies
|
|
401
|
+
dedupe: ['react', 'react-dom', 'react-router-dom'],
|
|
402
|
+
},
|
|
403
|
+
optimizeDeps: {
|
|
404
|
+
include: [
|
|
405
|
+
'react',
|
|
406
|
+
'react-dom',
|
|
407
|
+
'react/jsx-runtime',
|
|
408
|
+
],
|
|
409
|
+
// CRITICAL: Exclude pace-core to prevent React context mismatches
|
|
410
|
+
exclude: ['@jmruthers/pace-core', 'react-router-dom'],
|
|
411
|
+
},
|
|
412
|
+
});
|
|
304
413
|
```
|
|
305
414
|
|
|
415
|
+
**Why this matters:**
|
|
416
|
+
- Pre-bundling `@jmruthers/pace-core` creates separate React instances
|
|
417
|
+
- This causes "useUnifiedAuth must be used within a UnifiedAuthProvider" errors
|
|
418
|
+
- Excluding it ensures pace-core uses the same React instance as your app
|
|
419
|
+
- `react-router-dom` must also be excluded and deduped to prevent Router context errors
|
|
420
|
+
|
|
421
|
+
**If you encounter context errors:**
|
|
422
|
+
1. Verify `@jmruthers/pace-core` is in `optimizeDeps.exclude`
|
|
423
|
+
2. Verify `react-router-dom` is in both `resolve.dedupe` and `optimizeDeps.exclude`
|
|
424
|
+
3. Clear Vite cache: `rm -rf node_modules/.vite`
|
|
425
|
+
4. Restart dev server
|
|
426
|
+
|
|
306
427
|
## MUST: Import Core Styles
|
|
307
428
|
|
|
308
|
-
**
|
|
429
|
+
**ALWAYS import pace-core styles via app.css:**
|
|
309
430
|
|
|
310
431
|
The correct pattern is a two-file CSS architecture:
|
|
311
432
|
1. `src/app.css` - Contains `@import "@jmruthers/pace-core/styles/core.css";` (CSS @import)
|
|
@@ -326,11 +447,11 @@ import './app.css'; // ✅ CORRECT - app.css imports core.css
|
|
|
326
447
|
- Import `core.css` directly in `main.tsx` or `App.tsx` - This causes duplicate imports
|
|
327
448
|
- Use JavaScript import for `core.css` - Use CSS `@import` in `app.css` instead
|
|
328
449
|
|
|
329
|
-
**See [
|
|
450
|
+
**See [5-styling-standards.md](../../packages/core/docs/standards/5-styling-standards.md) for complete CSS setup instructions.**
|
|
330
451
|
|
|
331
452
|
## MUST NOT: Use Inline Styles
|
|
332
453
|
|
|
333
|
-
**
|
|
454
|
+
**NEVER use inline styles (`style={{...}}`).** All styling MUST come from pace-core components and Tailwind classes.
|
|
334
455
|
|
|
335
456
|
### Why No Inline Styles
|
|
336
457
|
|
|
@@ -392,14 +513,46 @@ Before adding any styling:
|
|
|
392
513
|
|
|
393
514
|
## Common Mistakes to Avoid
|
|
394
515
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
516
|
+
**When writing code, NEVER:**
|
|
517
|
+
1. **Use native HTML when pace-core provides components** - Always check pace-core first
|
|
518
|
+
```tsx
|
|
519
|
+
// ❌ WRONG
|
|
520
|
+
<button>Click</button>
|
|
521
|
+
<input type="text" />
|
|
522
|
+
|
|
523
|
+
// ✅ CORRECT
|
|
524
|
+
<Button>Click</Button>
|
|
525
|
+
<Input type="text" />
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
2. **Create wrapper functions around pace-core hooks** - Use hooks directly
|
|
529
|
+
```tsx
|
|
530
|
+
// ❌ WRONG
|
|
531
|
+
function useMyAuth() {
|
|
532
|
+
const auth = useUnifiedAuth();
|
|
533
|
+
return { user: auth.user, isAdmin: auth.user?.role === 'admin' };
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// ✅ CORRECT
|
|
537
|
+
const { user } = useUnifiedAuth();
|
|
538
|
+
const { canManage } = useCan(user?.id, scope, 'manage:users');
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
3. **Use createClient() for queries** - Always use `useSecureSupabase()`
|
|
542
|
+
```tsx
|
|
543
|
+
// ❌ WRONG
|
|
544
|
+
const supabase = createClient(url, key);
|
|
545
|
+
const { data } = await supabase.from('users').select('*');
|
|
546
|
+
|
|
547
|
+
// ✅ CORRECT
|
|
548
|
+
const secureSupabase = useSecureSupabase();
|
|
549
|
+
const { data } = await secureSupabase.from('users').select('*');
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
4. **Guess component props** - Always read documentation first
|
|
553
|
+
5. **Use inline styles** - Use pace-core components and Tailwind classes
|
|
554
|
+
6. **Skip provider nesting** - Always nest in correct order
|
|
555
|
+
7. **Skip Vite configuration** - Always exclude pace-core from pre-bundling
|
|
403
556
|
|
|
404
557
|
## Compliance Exceptions
|
|
405
558
|
|
|
@@ -424,8 +577,8 @@ If you encounter a situation where a rule seems to conflict with a legitimate re
|
|
|
424
577
|
|
|
425
578
|
## Reference
|
|
426
579
|
|
|
427
|
-
- **pace-core Exports**: See
|
|
428
|
-
- **RBAC Implementation**: See
|
|
580
|
+
- **pace-core Exports**: See [pace-core documentation](../../packages/core/docs/README.md) for complete export reference
|
|
581
|
+
- **RBAC Implementation**: See [6-security-rbac-standards.md](../../packages/core/docs/standards/6-security-rbac-standards.md) for RBAC patterns
|
|
429
582
|
- **Component Documentation**:
|
|
430
583
|
- API Reference: `node_modules/@jmruthers/pace-core/docs/api-reference/components.md`
|
|
431
584
|
- Implementation Guides: `node_modules/@jmruthers/pace-core/docs/implementation-guides/`
|
|
@@ -7,10 +7,42 @@ rulesVersion: "2025-01-28"
|
|
|
7
7
|
---
|
|
8
8
|
# Project Structure Standard
|
|
9
9
|
|
|
10
|
-
**📚 Human-Readable Standard**: See [
|
|
10
|
+
**📚 Human-Readable Standard**: See [2-project-structure-standards.md](../../packages/core/docs/standards/2-project-structure-standards.md) for complete documentation including migration guides and detailed examples.
|
|
11
11
|
|
|
12
12
|
This guide defines the standard folder structure and file organization for consuming apps in the PACE suite.
|
|
13
13
|
|
|
14
|
+
## AI Agent Instructions
|
|
15
|
+
|
|
16
|
+
**When creating or organizing files, ALWAYS:**
|
|
17
|
+
1. **Organize by feature** - Group components, hooks, and utilities by feature/domain, not by type
|
|
18
|
+
2. **Colocate tests** - Place test files next to source files (`Component.test.tsx` next to `Component.tsx`)
|
|
19
|
+
3. **Follow naming conventions** - Components: `PascalCase.tsx`, Hooks: `use*.ts`, Utils: `camelCase.ts`
|
|
20
|
+
4. **Use absolute imports** - Use `@/` path alias for imports, never relative imports for distant files
|
|
21
|
+
5. **Keep root clean** - Only configuration files and documentation in root, never source files
|
|
22
|
+
6. **Place migrations correctly** - All migrations in `supabase/migrations/` with timestamp format
|
|
23
|
+
|
|
24
|
+
**Decision Tree: File Organization**
|
|
25
|
+
```
|
|
26
|
+
1. Where should this file go?
|
|
27
|
+
├─ Component → src/components/<feature>/ComponentName.tsx
|
|
28
|
+
├─ Hook → src/hooks/useHookName.ts (or colocated with component)
|
|
29
|
+
├─ Utility → src/utils/utilityName.ts
|
|
30
|
+
├─ Type → src/types/typeName.ts (or colocated with feature)
|
|
31
|
+
├─ Test → Next to source file (ComponentName.test.tsx)
|
|
32
|
+
└─ Migration → supabase/migrations/YYYYMMDDHHMMSS_description.sql
|
|
33
|
+
|
|
34
|
+
2. How should I name it?
|
|
35
|
+
├─ Component → PascalCase (EventCard.tsx)
|
|
36
|
+
├─ Hook → camelCase with use prefix (useEventData.ts)
|
|
37
|
+
├─ Utility → camelCase (formatEvent.ts)
|
|
38
|
+
└─ Test → Same as source + .test (EventCard.test.tsx)
|
|
39
|
+
|
|
40
|
+
3. Should I use absolute or relative imports?
|
|
41
|
+
├─ Same directory → Relative (./Component)
|
|
42
|
+
├─ Different directory → Absolute (@/components/events/EventCard)
|
|
43
|
+
└─ pace-core → Package import (@jmruthers/pace-core)
|
|
44
|
+
```
|
|
45
|
+
|
|
14
46
|
## MUST: Follow Standard Directory Structure
|
|
15
47
|
|
|
16
48
|
**Consuming apps MUST follow this structure:**
|
|
@@ -42,7 +74,7 @@ your-app/
|
|
|
42
74
|
|
|
43
75
|
## MUST: Organize Components by Feature
|
|
44
76
|
|
|
45
|
-
**
|
|
77
|
+
**ALWAYS organize components by feature/domain, not by type:**
|
|
46
78
|
|
|
47
79
|
```
|
|
48
80
|
src/
|
|
@@ -64,7 +96,7 @@ src/
|
|
|
64
96
|
|
|
65
97
|
## MUST: Colocate Tests
|
|
66
98
|
|
|
67
|
-
**
|
|
99
|
+
**ALWAYS colocate tests with source files:**
|
|
68
100
|
|
|
69
101
|
```
|
|
70
102
|
src/
|
|
@@ -143,7 +175,7 @@ src/
|
|
|
143
175
|
|
|
144
176
|
## MUST: Use Consistent Import Paths
|
|
145
177
|
|
|
146
|
-
**
|
|
178
|
+
**ALWAYS use consistent import patterns:**
|
|
147
179
|
|
|
148
180
|
```tsx
|
|
149
181
|
// ✅ CORRECT - Absolute imports from src
|
|
@@ -203,4 +235,4 @@ Before committing, verify:
|
|
|
203
235
|
|
|
204
236
|
## Reference
|
|
205
237
|
|
|
206
|
-
See
|
|
238
|
+
**Note**: File structure validation is handled by the audit tool. See [2-project-structure-standards.md](../../packages/core/docs/standards/2-project-structure-standards.md) for complete enforcement details.
|
|
@@ -1,15 +1,43 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce SOLID architecture principles
|
|
2
|
+
description: Enforce SOLID architecture principles, component design, and API design patterns
|
|
3
3
|
globs: ["src/**/*.{ts,tsx}"]
|
|
4
4
|
alwaysApply: false
|
|
5
5
|
paceCoreVersion: "0.6.x"
|
|
6
6
|
rulesVersion: "2025-01-28"
|
|
7
7
|
---
|
|
8
|
-
#
|
|
8
|
+
# Architecture Standards Guide
|
|
9
9
|
|
|
10
|
-
**📚 Human-Readable Standard**: See [
|
|
10
|
+
**📚 Human-Readable Standard**: See [3-architecture-standards.md](../../packages/core/docs/standards/3-architecture-standards.md) for complete documentation.
|
|
11
11
|
|
|
12
|
-
This guide enforces SOLID architecture principles to ensure maintainable, extensible, and testable code.
|
|
12
|
+
This guide enforces SOLID architecture principles, component design patterns, and API design patterns to ensure maintainable, extensible, and testable code.
|
|
13
|
+
|
|
14
|
+
## AI Agent Instructions
|
|
15
|
+
|
|
16
|
+
**When writing or modifying code, ALWAYS:**
|
|
17
|
+
1. **Extract complex logic** - Move business logic out of components into hooks, services, or utilities
|
|
18
|
+
2. **Use composition** - Extend functionality through composition, not modification of pace-core components
|
|
19
|
+
3. **Keep components simple** - Components should only handle UI rendering, not data fetching or business logic
|
|
20
|
+
4. **Use focused interfaces** - Create small, specific interfaces instead of large, generic ones
|
|
21
|
+
5. **Depend on abstractions** - Use interfaces/types, not concrete implementations
|
|
22
|
+
6. **Follow ApiResult pattern** - All RPCs must return ApiResult shape with proper error handling
|
|
23
|
+
|
|
24
|
+
**Decision Tree: Where should this logic live?**
|
|
25
|
+
```
|
|
26
|
+
1. What type of logic is this?
|
|
27
|
+
├─ UI rendering → Component
|
|
28
|
+
├─ Data fetching → Hook or service
|
|
29
|
+
├─ Business logic → Hook, service, or utility
|
|
30
|
+
├─ Formatting/transformation → Utility function
|
|
31
|
+
└─ Validation → Zod schema or utility
|
|
32
|
+
|
|
33
|
+
2. Is this logic complex?
|
|
34
|
+
├─ YES → Extract to hook/service/utility
|
|
35
|
+
└─ NO → Can stay in component if simple
|
|
36
|
+
|
|
37
|
+
3. Does this modify pace-core behavior?
|
|
38
|
+
├─ YES → Use composition (wrap pace-core component)
|
|
39
|
+
└─ NO → Continue
|
|
40
|
+
```
|
|
13
41
|
|
|
14
42
|
## Single Responsibility Principle (SRP)
|
|
15
43
|
|
|
@@ -206,17 +234,103 @@ Before committing code, verify:
|
|
|
206
234
|
- [ ] No god objects or bloated components
|
|
207
235
|
- [ ] Code is testable and maintainable
|
|
208
236
|
|
|
209
|
-
##
|
|
237
|
+
## Common Mistakes to Avoid
|
|
238
|
+
|
|
239
|
+
**When writing code, NEVER:**
|
|
240
|
+
1. **Create god objects** - Components/classes that do too much
|
|
241
|
+
```tsx
|
|
242
|
+
// ❌ WRONG: Component does everything
|
|
243
|
+
function UserDashboard({ userId }) {
|
|
244
|
+
const [user, setUser] = useState(null);
|
|
245
|
+
const [events, setEvents] = useState([]);
|
|
246
|
+
const [organisations, setOrganisations] = useState([]);
|
|
247
|
+
// 200+ lines of logic...
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ✅ CORRECT: Separated concerns
|
|
251
|
+
function UserDashboard({ userId }) {
|
|
252
|
+
const user = useUser(userId);
|
|
253
|
+
const events = useUserEvents(userId);
|
|
254
|
+
const organisations = useUserOrganisations(userId);
|
|
255
|
+
return <DashboardContent user={user} events={events} organisations={organisations} />;
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
2. **Put business logic in components** - Extract to hooks/services
|
|
260
|
+
3. **Create large interfaces** - Use focused, specific interfaces
|
|
261
|
+
4. **Depend on concrete implementations** - Use abstractions (interfaces/types)
|
|
262
|
+
5. **Modify pace-core components** - Use composition instead
|
|
263
|
+
6. **Use boolean flags for states** - Use discriminated unions
|
|
264
|
+
|
|
265
|
+
## API Design Patterns
|
|
266
|
+
|
|
267
|
+
### MUST: Follow API Design Principles
|
|
268
|
+
|
|
269
|
+
**APIs MUST be:**
|
|
270
|
+
- Intuitive and consistent
|
|
271
|
+
- Extensible without breaking changes
|
|
272
|
+
- Clear about errors and edge cases
|
|
273
|
+
|
|
274
|
+
### MUST: Use ApiResult Pattern
|
|
275
|
+
|
|
276
|
+
**All RPCs MUST return ApiResult shape:**
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
type ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError };
|
|
280
|
+
type ApiError = { code: string; message: string; details?: object };
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
// ✅ CORRECT: RPC returns ApiResult
|
|
285
|
+
const result = await supabase.rpc('app_events_create', { name, date });
|
|
286
|
+
if (!result.ok) {
|
|
287
|
+
// Handle error
|
|
288
|
+
return { ok: false, error: result.error };
|
|
289
|
+
}
|
|
290
|
+
return { ok: true, data: result.data };
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### SHOULD: Make Write RPCs Idempotent
|
|
210
294
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
295
|
+
**Write RPCs SHOULD be idempotent when possible:**
|
|
296
|
+
|
|
297
|
+
```sql
|
|
298
|
+
-- ✅ CORRECT: Idempotent create (ON CONFLICT DO NOTHING)
|
|
299
|
+
INSERT INTO events (id, name, date)
|
|
300
|
+
VALUES (p_event_id, p_name, p_date)
|
|
301
|
+
ON CONFLICT (id) DO NOTHING;
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Component Design Patterns
|
|
305
|
+
|
|
306
|
+
### MUST: Follow Component Principles
|
|
307
|
+
|
|
308
|
+
**Components MUST:**
|
|
309
|
+
- Be stateless when possible
|
|
310
|
+
- Use composable structure
|
|
311
|
+
- Be accessible by default
|
|
312
|
+
- Be fully typed
|
|
313
|
+
- Have small surface area
|
|
314
|
+
|
|
315
|
+
### MUST NOT: Add Domain Logic to Components
|
|
316
|
+
|
|
317
|
+
**Components MUST NOT:**
|
|
318
|
+
- Include domain-specific logic
|
|
319
|
+
- Fetch data directly (use hooks/services)
|
|
320
|
+
- Include business workflows
|
|
321
|
+
|
|
322
|
+
### MUST: Ensure Accessibility
|
|
323
|
+
|
|
324
|
+
**Components MUST:**
|
|
325
|
+
- Be keyboard operable
|
|
326
|
+
- Have correct ARIA roles
|
|
327
|
+
- Have visible focus states
|
|
328
|
+
- Avoid inaccessible interactions
|
|
217
329
|
|
|
218
330
|
## Reference
|
|
219
331
|
|
|
332
|
+
**Note**: RLS policy validation is handled by the audit tool. See [3-architecture-standards.md](../../packages/core/docs/standards/3-architecture-standards.md) for complete enforcement details.
|
|
333
|
+
|
|
220
334
|
- Single Responsibility: Each module has one reason to change
|
|
221
335
|
- Open/Closed: Open for extension, closed for modification
|
|
222
336
|
- Liskov Substitution: Subtypes must be substitutable
|