@jmruthers/pace-core 0.6.4 → 0.6.6
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/CHANGELOG.md +104 -0
- package/README.md +5 -403
- package/core-usage-manifest.json +93 -0
- package/cursor-rules/00-pace-core-compliance.mdc +128 -26
- package/cursor-rules/01-standards-compliance.mdc +49 -8
- package/cursor-rules/02-project-structure.mdc +6 -0
- package/cursor-rules/03-solid-principles.mdc +2 -0
- package/cursor-rules/04-testing-standards.mdc +2 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
- package/cursor-rules/06-code-quality.mdc +2 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
- package/cursor-rules/08-markup-quality.mdc +52 -27
- package/cursor-rules/09-rbac-compliance.mdc +462 -0
- package/cursor-rules/10-error-handling-patterns.mdc +179 -0
- package/cursor-rules/11-performance-optimization.mdc +169 -0
- package/cursor-rules/12-ci-cd-integration.mdc +150 -0
- package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
- package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
- package/dist/DataTable-LRJL4IRV.js +15 -0
- package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
- package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
- package/dist/api-Y4MQWOFW.js +4 -0
- package/dist/audit-MYQXYZFU.js +3 -0
- package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
- package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
- package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
- package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
- package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
- package/dist/chunk-4T7OBVTU.js +62 -0
- package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
- package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
- package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
- package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
- package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
- package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
- package/dist/chunk-C7NSAPTL.js +1 -0
- package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
- package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
- package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
- package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
- package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
- package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
- package/dist/chunk-MBADTM7L.js +64 -0
- package/dist/chunk-OHIK3MIO.js +994 -0
- package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
- package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
- package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
- package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
- package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
- package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
- package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
- package/dist/components.d.ts +6 -6
- package/dist/components.js +57 -267
- package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
- package/dist/eslint-rules/index.cjs +22 -0
- package/dist/eslint-rules/rules/compliance.cjs +348 -0
- package/dist/eslint-rules/rules/components.cjs +113 -0
- package/dist/eslint-rules/rules/imports.cjs +102 -0
- package/dist/eslint-rules/rules/rbac.cjs +790 -0
- package/dist/eslint-rules/utils/helpers.cjs +42 -0
- package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +62 -270
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +36 -26
- package/dist/index.js +87 -690
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +8 -35
- package/dist/rbac/eslint-rules.d.ts +46 -44
- package/dist/rbac/eslint-rules.js +7 -4
- package/dist/rbac/index.d.ts +124 -594
- package/dist/rbac/index.js +14 -207
- package/dist/styles/index.js +2 -12
- package/dist/theming/runtime.js +3 -19
- package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
- package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
- package/dist/types-t9H8qKRw.d.ts +55 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +7 -94
- package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
- package/dist/utils.d.ts +24 -117
- package/dist/utils.js +54 -392
- package/docs/README.md +16 -6
- package/docs/api/README.md +4 -402
- package/docs/api/modules.md +454 -930
- package/docs/api-reference/components.md +3 -1
- package/docs/api-reference/deprecated.md +31 -6
- package/docs/api-reference/rpc-functions.md +78 -3
- package/docs/best-practices/accessibility.md +6 -3
- package/docs/getting-started/cursor-rules.md +3 -23
- package/docs/getting-started/dependencies.md +650 -0
- package/docs/getting-started/installation-guide.md +20 -7
- package/docs/getting-started/quick-start.md +23 -12
- package/docs/implementation-guides/permission-enforcement.md +4 -0
- package/docs/rbac/MIGRATION_GUIDE.md +819 -0
- package/docs/rbac/RBAC_CONTRACT.md +724 -0
- package/docs/rbac/README.md +12 -3
- package/docs/rbac/edge-functions-guide.md +376 -0
- package/docs/rbac/secure-client-protection.md +0 -34
- package/docs/standards/00-pace-core-compliance.md +967 -0
- package/docs/standards/01-standards-compliance.md +188 -0
- package/docs/standards/02-project-structure.md +985 -0
- package/docs/standards/03-solid-principles.md +39 -0
- package/docs/standards/04-testing-standards.md +36 -0
- package/docs/standards/05-bug-reports-and-features.md +27 -0
- package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
- package/docs/standards/07-tech-stack-compliance.md +30 -0
- package/docs/standards/08-markup-quality.md +345 -0
- package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
- package/docs/standards/10-error-handling-patterns.md +401 -0
- package/docs/standards/11-performance-optimization.md +348 -0
- package/docs/standards/12-ci-cd-integration.md +370 -0
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
- package/docs/standards/README.md +62 -33
- package/docs/troubleshooting/organisation-context-setup.md +42 -19
- package/eslint-config-pace-core.cjs +20 -4
- package/package.json +31 -21
- package/scripts/audit/audit-compliance.cjs +1295 -0
- package/scripts/audit/audit-components.cjs +260 -0
- package/scripts/audit/audit-dependencies.cjs +395 -0
- package/scripts/audit/audit-rbac.cjs +954 -0
- package/scripts/audit/audit-standards.cjs +1268 -0
- package/scripts/audit/index.cjs +1898 -194
- package/scripts/install-cursor-rules.cjs +259 -8
- package/scripts/validate-master.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +1 -1
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
- package/src/__tests__/helpers/component-test-utils.tsx +1 -1
- package/src/__tests__/helpers/supabaseMock.ts +2 -2
- package/src/__tests__/public-recipe-view.test.ts +38 -9
- package/src/components/Button/Button.tsx +5 -1
- package/src/components/ContextSelector/ContextSelector.tsx +42 -39
- package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
- package/src/components/DataTable/components/DataTableBody.tsx +55 -31
- package/src/components/DataTable/components/DataTableCore.tsx +186 -13
- package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
- package/src/components/DataTable/components/EditFields.tsx +23 -3
- package/src/components/DataTable/components/EditableRow.tsx +7 -2
- package/src/components/DataTable/components/ImportModal.tsx +4 -6
- package/src/components/DataTable/components/RowComponent.tsx +12 -0
- package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
- package/src/components/DataTable/core/DataTableContext.tsx +1 -1
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
- package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
- package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
- package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
- package/src/components/DataTable/types.ts +5 -0
- package/src/components/DateTimeField/DateTimeField.tsx +20 -20
- package/src/components/DateTimeField/README.md +5 -2
- package/src/components/Dialog/Dialog.test.tsx +361 -318
- package/src/components/Dialog/Dialog.tsx +1154 -323
- package/src/components/Dialog/index.ts +3 -3
- package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
- package/src/components/FileDisplay/FileDisplay.tsx +28 -22
- package/src/components/Form/Form.test.tsx +9 -10
- package/src/components/Form/Form.tsx +369 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
- package/src/components/LoginForm/LoginForm.tsx +2 -2
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
- package/src/components/PaceAppLayout/README.md +10 -9
- package/src/components/PaceAppLayout/test-setup.tsx +40 -31
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
- package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
- package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
- package/src/components/Select/Select.tsx +23 -21
- package/src/components/Select/types.ts +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +38 -6
- package/src/components/UserMenu/UserMenu.tsx +39 -34
- package/src/components/index.ts +3 -4
- package/src/eslint-rules/index.cjs +22 -0
- package/src/eslint-rules/rules/compliance.cjs +348 -0
- package/src/eslint-rules/rules/components.cjs +113 -0
- package/src/eslint-rules/rules/imports.cjs +102 -0
- package/src/eslint-rules/rules/rbac.cjs +790 -0
- package/src/eslint-rules/utils/helpers.cjs +42 -0
- package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
- package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
- package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
- package/src/hooks/public/usePublicEvent.ts +62 -190
- package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
- package/src/hooks/public/usePublicEventLogo.ts +19 -9
- package/src/hooks/useAppConfig.ts +26 -24
- package/src/hooks/useEventTheme.test.ts +211 -233
- package/src/hooks/useEventTheme.ts +19 -28
- package/src/hooks/useEvents.ts +11 -7
- package/src/hooks/useKeyboardShortcuts.ts +1 -1
- package/src/hooks/useOrganisationPermissions.ts +9 -11
- package/src/hooks/useOrganisations.ts +13 -7
- package/src/hooks/useQueryCache.ts +0 -1
- package/src/hooks/useSessionDraft.ts +380 -0
- package/src/hooks/useSessionRestoration.ts +3 -1
- package/src/icons/index.ts +27 -0
- package/src/index.ts +16 -1
- package/src/providers/OrganisationProvider.tsx +23 -14
- package/src/providers/services/EventServiceProvider.tsx +1 -24
- package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
- package/src/rbac/README.md +20 -20
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
- package/src/rbac/adapters.tsx +7 -295
- package/src/rbac/api.test.ts +44 -56
- package/src/rbac/api.ts +10 -17
- package/src/rbac/cache-invalidation.ts +0 -1
- package/src/rbac/compliance/index.ts +10 -0
- package/src/rbac/compliance/pattern-detector.ts +553 -0
- package/src/rbac/compliance/runtime-compliance.ts +22 -0
- package/src/rbac/components/AccessDenied.tsx +150 -0
- package/src/rbac/components/NavigationGuard.tsx +12 -20
- package/src/rbac/components/PagePermissionGuard.tsx +4 -24
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
- package/src/rbac/components/index.ts +3 -41
- package/src/rbac/eslint-rules.js +1 -1
- package/src/rbac/hooks/index.ts +0 -3
- package/src/rbac/hooks/permissions/index.ts +0 -3
- package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
- package/src/rbac/hooks/usePermissions.ts +0 -3
- package/src/rbac/hooks/useRBAC.test.ts +21 -3
- package/src/rbac/hooks/useRBAC.ts +4 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
- package/src/rbac/hooks/useResolvedScope.ts +58 -140
- package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
- package/src/rbac/hooks/useResourcePermissions.ts +182 -63
- package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
- package/src/rbac/hooks/useRoleManagement.ts +147 -19
- package/src/rbac/hooks/useSecureSupabase.ts +4 -8
- package/src/rbac/index.ts +7 -9
- package/src/rbac/permissions.ts +17 -17
- package/src/rbac/utils/contextValidator.ts +45 -7
- package/src/services/AuthService.ts +132 -23
- package/src/services/EventService.ts +4 -97
- package/src/services/InactivityService.ts +155 -58
- package/src/services/OrganisationService.ts +7 -44
- package/src/services/__tests__/OrganisationService.test.ts +26 -8
- package/src/services/base/BaseService.ts +0 -3
- package/src/styles/core.css +4 -0
- package/src/types/database.generated.ts +4733 -3809
- package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
- package/src/utils/context/organisationContext.test.ts +13 -28
- package/src/utils/context/organisationContext.ts +21 -52
- package/src/utils/dynamic/dynamicUtils.ts +1 -1
- package/src/utils/file-reference/index.ts +39 -15
- package/src/utils/formatting/formatDateTime.test.ts +3 -2
- package/src/utils/formatting/formatTime.test.ts +3 -2
- package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
- package/src/utils/index.ts +4 -1
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
- package/src/utils/persistence/keyDerivation.ts +304 -0
- package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
- package/src/utils/security/secureStorage.ts +5 -5
- package/src/utils/storage/helpers.ts +3 -3
- package/src/utils/supabase/createBaseClient.ts +147 -0
- package/src/utils/timezone/timezone.test.ts +1 -2
- package/src/utils/timezone/timezone.ts +1 -1
- package/src/utils/validation/csrf.ts +4 -4
- package/cursor-rules/CHANGELOG.md +0 -119
- package/cursor-rules/README.md +0 -192
- package/dist/DataTable-E7YQZD7D.js +0 -175
- package/dist/DataTable-E7YQZD7D.js.map +0 -1
- package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
- package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
- package/dist/api-6LVZTHDS.js +0 -52
- package/dist/api-6LVZTHDS.js.map +0 -1
- package/dist/audit-V53FV5AG.js +0 -17
- package/dist/audit-V53FV5AG.js.map +0 -1
- package/dist/chunk-36LVWXB2.js +0 -227
- package/dist/chunk-36LVWXB2.js.map +0 -1
- package/dist/chunk-3LPHPB62.js.map +0 -1
- package/dist/chunk-5DRSZLL2.js.map +0 -1
- package/dist/chunk-5EC5MEWX.js.map +0 -1
- package/dist/chunk-63FOKYGO.js.map +0 -1
- package/dist/chunk-6SOIHG6Z.js.map +0 -1
- package/dist/chunk-7JPAB3T5.js.map +0 -1
- package/dist/chunk-ATKZM7RX.js +0 -2053
- package/dist/chunk-ATKZM7RX.js.map +0 -1
- package/dist/chunk-AVMLPIM7.js.map +0 -1
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-E66EQZE6.js.map +0 -1
- package/dist/chunk-FFQEQTNW.js.map +0 -1
- package/dist/chunk-FMUCXFII.js.map +0 -1
- package/dist/chunk-G37KK66H.js.map +0 -1
- package/dist/chunk-I6DAQMWX.js.map +0 -1
- package/dist/chunk-J36DSWQK.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js +0 -1
- package/dist/chunk-KQCRWDSA.js.map +0 -1
- package/dist/chunk-L4OXEN46.js.map +0 -1
- package/dist/chunk-LMC26NLJ.js +0 -84
- package/dist/chunk-LMC26NLJ.js.map +0 -1
- package/dist/chunk-M43Y4SSO.js.map +0 -1
- package/dist/chunk-M7MPQISP.js.map +0 -1
- package/dist/chunk-NN6WWZ5U.js.map +0 -1
- package/dist/chunk-OEWDTMG7.js.map +0 -1
- package/dist/chunk-PWLANIRT.js.map +0 -1
- package/dist/chunk-QXHPKYJV.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js.map +0 -1
- package/dist/chunk-YKRAFF5K.js.map +0 -1
- package/dist/chunk-ZSAAAMVR.js.map +0 -1
- package/dist/components.js.map +0 -1
- package/dist/contextValidator-OOPCLPZW.js +0 -9
- package/dist/contextValidator-OOPCLPZW.js.map +0 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
- package/dist/hooks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers.js.map +0 -1
- package/dist/rbac/eslint-rules.js.map +0 -1
- package/dist/rbac/index.js.map +0 -1
- package/dist/styles/index.js.map +0 -1
- package/dist/theming/runtime.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/docs/standards/01-architecture-standard.md +0 -44
- package/docs/standards/02-api-and-rpc-standard.md +0 -39
- package/docs/standards/03-component-standard.md +0 -32
- package/docs/standards/05-security-standard.md +0 -44
- package/docs/standards/06-testing-and-docs-standard.md +0 -29
- package/docs/standards/pace-core-compliance.md +0 -432
- package/scripts/audit/core/checks/accessibility.cjs +0 -197
- package/scripts/audit/core/checks/api-usage.cjs +0 -191
- package/scripts/audit/core/checks/bundle.cjs +0 -142
- package/scripts/audit/core/checks/compliance.cjs +0 -2706
- package/scripts/audit/core/checks/config.cjs +0 -54
- package/scripts/audit/core/checks/coverage.cjs +0 -84
- package/scripts/audit/core/checks/dependencies.cjs +0 -994
- package/scripts/audit/core/checks/documentation.cjs +0 -268
- package/scripts/audit/core/checks/environment.cjs +0 -116
- package/scripts/audit/core/checks/error-handling.cjs +0 -340
- package/scripts/audit/core/checks/forms.cjs +0 -172
- package/scripts/audit/core/checks/heuristics.cjs +0 -68
- package/scripts/audit/core/checks/hooks.cjs +0 -334
- package/scripts/audit/core/checks/imports.cjs +0 -244
- package/scripts/audit/core/checks/performance.cjs +0 -325
- package/scripts/audit/core/checks/routes.cjs +0 -117
- package/scripts/audit/core/checks/state.cjs +0 -130
- package/scripts/audit/core/checks/structure.cjs +0 -65
- package/scripts/audit/core/checks/style.cjs +0 -584
- package/scripts/audit/core/checks/testing.cjs +0 -122
- package/scripts/audit/core/checks/typescript.cjs +0 -61
- package/scripts/audit/core/scanner.cjs +0 -199
- package/scripts/audit/core/utils.cjs +0 -137
- package/scripts/audit/reporters/console.cjs +0 -151
- package/scripts/audit/reporters/json.cjs +0 -54
- package/scripts/audit/reporters/markdown.cjs +0 -124
- package/scripts/audit-consuming-app.cjs +0 -86
- package/src/eslint-rules/pace-core-compliance.cjs +0 -510
- package/src/eslint-rules/pace-core-compliance.js +0 -638
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
- package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
- package/src/rbac/components/NavigationProvider.test.tsx +0 -481
- package/src/rbac/components/NavigationProvider.tsx +0 -345
- package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
- package/src/rbac/components/PagePermissionProvider.tsx +0 -279
- package/src/rbac/components/PermissionEnforcer.tsx +0 -312
- package/src/rbac/components/RoleBasedRouter.tsx +0 -440
- package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
- package/src/rbac/components/SecureDataProvider.tsx +0 -339
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# Error Handling Patterns
|
|
2
|
+
|
|
3
|
+
**🤖 Cursor Rule**: See [10-error-handling-patterns.mdc](../../cursor-rules/10-error-handling-patterns.mdc) for AI-optimized directives that automatically enforce error handling patterns.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
This standard defines consistent error handling patterns across pace-core and consuming apps to ensure:
|
|
8
|
+
- **User-friendly error messages** that don't expose internal details
|
|
9
|
+
- **Type-safe error handling** with proper TypeScript types
|
|
10
|
+
- **Consistent error recovery** strategies
|
|
11
|
+
- **Proper error logging** without exposing sensitive data
|
|
12
|
+
- **Graceful degradation** when errors occur
|
|
13
|
+
|
|
14
|
+
## Principles
|
|
15
|
+
|
|
16
|
+
1. **Never expose internal details** in user-facing error messages
|
|
17
|
+
2. **Always use type-safe error handling** (no `any` types)
|
|
18
|
+
3. **Log errors appropriately** (with context, without sensitive data)
|
|
19
|
+
4. **Provide recovery paths** when possible
|
|
20
|
+
5. **Use consistent error shapes** across the application
|
|
21
|
+
|
|
22
|
+
## Error Types
|
|
23
|
+
|
|
24
|
+
### API Errors
|
|
25
|
+
|
|
26
|
+
**Shape:**
|
|
27
|
+
```typescript
|
|
28
|
+
type ApiError = {
|
|
29
|
+
ok: false;
|
|
30
|
+
error: {
|
|
31
|
+
code: string; // Machine-readable error code
|
|
32
|
+
message: string; // User-friendly message
|
|
33
|
+
details?: object; // Optional additional context (non-sensitive)
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Example:**
|
|
39
|
+
```typescript
|
|
40
|
+
// ✅ CORRECT
|
|
41
|
+
const result = await apiCall();
|
|
42
|
+
if (!result.ok) {
|
|
43
|
+
// result.error.message is user-friendly
|
|
44
|
+
toast.error(result.error.message);
|
|
45
|
+
logger.error('API call failed', { code: result.error.code, details: result.error.details });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ❌ WRONG - Exposing internal details
|
|
49
|
+
if (error.message.includes('SQL')) {
|
|
50
|
+
toast.error(error.message); // Exposes database internals
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Validation Errors
|
|
55
|
+
|
|
56
|
+
**Shape:**
|
|
57
|
+
```typescript
|
|
58
|
+
type ValidationError = {
|
|
59
|
+
field: string;
|
|
60
|
+
message: string;
|
|
61
|
+
code?: string;
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Example:**
|
|
66
|
+
```typescript
|
|
67
|
+
// ✅ CORRECT - Using Zod validation
|
|
68
|
+
const schema = z.object({
|
|
69
|
+
email: z.string().email('Please enter a valid email address'),
|
|
70
|
+
name: z.string().min(1, 'Name is required'),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const data = schema.parse(formData);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (error instanceof z.ZodError) {
|
|
77
|
+
// User-friendly validation messages
|
|
78
|
+
error.errors.forEach(err => {
|
|
79
|
+
toast.error(err.message);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Network Errors
|
|
86
|
+
|
|
87
|
+
**Pattern:**
|
|
88
|
+
```typescript
|
|
89
|
+
// ✅ CORRECT - Handle network errors gracefully
|
|
90
|
+
try {
|
|
91
|
+
const data = await fetchData();
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error instanceof TypeError && error.message.includes('fetch')) {
|
|
94
|
+
toast.error('Unable to connect. Please check your internet connection.');
|
|
95
|
+
logger.error('Network error', { error: error.message });
|
|
96
|
+
} else {
|
|
97
|
+
toast.error('An unexpected error occurred. Please try again.');
|
|
98
|
+
logger.error('Unexpected error', { error });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Error Handling Patterns
|
|
104
|
+
|
|
105
|
+
### Pattern 1: Try-Catch with Type Guards
|
|
106
|
+
|
|
107
|
+
**Use for:** Known error types that need different handling
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// ✅ CORRECT
|
|
111
|
+
function isApiError(error: unknown): error is ApiError {
|
|
112
|
+
return (
|
|
113
|
+
typeof error === 'object' &&
|
|
114
|
+
error !== null &&
|
|
115
|
+
'ok' in error &&
|
|
116
|
+
(error as ApiError).ok === false &&
|
|
117
|
+
'error' in error
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const result = await apiCall();
|
|
123
|
+
if (!result.ok) {
|
|
124
|
+
handleApiError(result.error);
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (isApiError(error)) {
|
|
128
|
+
handleApiError(error.error);
|
|
129
|
+
} else {
|
|
130
|
+
handleUnknownError(error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Pattern 2: Result Types
|
|
136
|
+
|
|
137
|
+
**Use for:** Functions that can fail (preferred pattern)
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// ✅ CORRECT - Using Result type
|
|
141
|
+
type Result<T, E = ApiError> =
|
|
142
|
+
| { ok: true; data: T }
|
|
143
|
+
| { ok: false; error: E };
|
|
144
|
+
|
|
145
|
+
async function fetchUser(id: string): Promise<Result<User>> {
|
|
146
|
+
try {
|
|
147
|
+
const { data, error } = await supabase.from('users').select('*').eq('id', id).single();
|
|
148
|
+
if (error) {
|
|
149
|
+
return { ok: false, error: { code: 'USER_NOT_FOUND', message: 'User not found' } };
|
|
150
|
+
}
|
|
151
|
+
return { ok: true, data };
|
|
152
|
+
} catch (error) {
|
|
153
|
+
return {
|
|
154
|
+
ok: false,
|
|
155
|
+
error: { code: 'UNKNOWN_ERROR', message: 'An unexpected error occurred' }
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Usage
|
|
161
|
+
const result = await fetchUser(userId);
|
|
162
|
+
if (result.ok) {
|
|
163
|
+
// TypeScript knows result.data exists
|
|
164
|
+
setUser(result.data);
|
|
165
|
+
} else {
|
|
166
|
+
// TypeScript knows result.error exists
|
|
167
|
+
toast.error(result.error.message);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Pattern 3: Error Boundaries (React)
|
|
172
|
+
|
|
173
|
+
**Use for:** Catching React component errors
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
// ✅ CORRECT - Error boundary component
|
|
177
|
+
import { ErrorBoundary } from '@jmruthers/pace-core';
|
|
178
|
+
|
|
179
|
+
function App() {
|
|
180
|
+
return (
|
|
181
|
+
<ErrorBoundary
|
|
182
|
+
fallback={<ErrorFallback />}
|
|
183
|
+
onError={(error, errorInfo) => {
|
|
184
|
+
logger.error('React error boundary caught error', { error, errorInfo });
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
<YourApp />
|
|
188
|
+
</ErrorBoundary>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Pattern 4: Async Error Handling
|
|
194
|
+
|
|
195
|
+
**Use for:** Async operations with proper error handling
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// ✅ CORRECT - Async with error handling
|
|
199
|
+
async function loadData() {
|
|
200
|
+
try {
|
|
201
|
+
setIsLoading(true);
|
|
202
|
+
const result = await fetchData();
|
|
203
|
+
if (!result.ok) {
|
|
204
|
+
throw new Error(result.error.message);
|
|
205
|
+
}
|
|
206
|
+
setData(result.data);
|
|
207
|
+
} catch (error) {
|
|
208
|
+
handleError(error);
|
|
209
|
+
} finally {
|
|
210
|
+
setIsLoading(false);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Error Messages
|
|
216
|
+
|
|
217
|
+
### User-Facing Messages
|
|
218
|
+
|
|
219
|
+
**MUST:**
|
|
220
|
+
- Be user-friendly and actionable
|
|
221
|
+
- Not expose internal details (SQL, stack traces, file paths)
|
|
222
|
+
- Provide context when helpful
|
|
223
|
+
- Be consistent in tone and style
|
|
224
|
+
|
|
225
|
+
**Examples:**
|
|
226
|
+
```typescript
|
|
227
|
+
// ✅ CORRECT - User-friendly
|
|
228
|
+
'Unable to save changes. Please try again.'
|
|
229
|
+
'This field is required.'
|
|
230
|
+
'Invalid email address format.'
|
|
231
|
+
|
|
232
|
+
// ❌ WRONG - Exposes internals
|
|
233
|
+
'SQLSTATE[23000]: Integrity constraint violation'
|
|
234
|
+
'Cannot read property "data" of undefined'
|
|
235
|
+
'/app/src/services/api.ts:123:45'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Logging Messages
|
|
239
|
+
|
|
240
|
+
**MUST:**
|
|
241
|
+
- Include error context (user ID, operation, etc.)
|
|
242
|
+
- Not log sensitive data (passwords, tokens, PII)
|
|
243
|
+
- Use structured logging when possible
|
|
244
|
+
- Include error codes for correlation
|
|
245
|
+
|
|
246
|
+
**Examples:**
|
|
247
|
+
```typescript
|
|
248
|
+
// ✅ CORRECT - Structured logging
|
|
249
|
+
logger.error('Failed to save user', {
|
|
250
|
+
userId: user.id,
|
|
251
|
+
operation: 'updateUser',
|
|
252
|
+
errorCode: error.code,
|
|
253
|
+
timestamp: new Date().toISOString(),
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// ❌ WRONG - Logs sensitive data
|
|
257
|
+
logger.error('Failed to save user', {
|
|
258
|
+
password: user.password, // NEVER log passwords
|
|
259
|
+
token: authToken, // NEVER log tokens
|
|
260
|
+
ssn: user.ssn, // NEVER log PII
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Error Recovery
|
|
265
|
+
|
|
266
|
+
### Retry Logic
|
|
267
|
+
|
|
268
|
+
**Use for:** Transient errors (network, timeouts)
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
// ✅ CORRECT - Retry with exponential backoff
|
|
272
|
+
async function fetchWithRetry<T>(
|
|
273
|
+
fn: () => Promise<Result<T>>,
|
|
274
|
+
maxRetries = 3
|
|
275
|
+
): Promise<Result<T>> {
|
|
276
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
277
|
+
const result = await fn();
|
|
278
|
+
if (result.ok) {
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Don't retry on client errors (4xx)
|
|
283
|
+
if (result.error.code?.startsWith('4')) {
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Exponential backoff
|
|
288
|
+
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return { ok: false, error: { code: 'MAX_RETRIES', message: 'Operation failed after retries' } };
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Fallback Values
|
|
296
|
+
|
|
297
|
+
**Use for:** Non-critical data that can have defaults
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// ✅ CORRECT - Fallback to default
|
|
301
|
+
const userPreferences = await fetchUserPreferences().catch(() => ({
|
|
302
|
+
theme: 'light',
|
|
303
|
+
language: 'en',
|
|
304
|
+
}));
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Graceful Degradation
|
|
308
|
+
|
|
309
|
+
**Use for:** Features that can work without optional data
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// ✅ CORRECT - Graceful degradation
|
|
313
|
+
async function loadDashboard() {
|
|
314
|
+
const [events, stats, preferences] = await Promise.allSettled([
|
|
315
|
+
fetchEvents(),
|
|
316
|
+
fetchStats(),
|
|
317
|
+
fetchPreferences(),
|
|
318
|
+
]);
|
|
319
|
+
|
|
320
|
+
// Use data that loaded successfully
|
|
321
|
+
if (events.status === 'fulfilled') {
|
|
322
|
+
setEvents(events.value);
|
|
323
|
+
} else {
|
|
324
|
+
logger.warn('Events failed to load', events.reason);
|
|
325
|
+
setEvents([]); // Fallback to empty array
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Similar for stats and preferences
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Error Handling Checklist
|
|
333
|
+
|
|
334
|
+
Before committing code with error handling, verify:
|
|
335
|
+
|
|
336
|
+
- [ ] User-facing error messages are friendly and actionable
|
|
337
|
+
- [ ] No internal details exposed in user messages
|
|
338
|
+
- [ ] Type-safe error handling (no `any` types)
|
|
339
|
+
- [ ] Errors are logged with context (no sensitive data)
|
|
340
|
+
- [ ] Recovery paths provided when possible
|
|
341
|
+
- [ ] Error shapes are consistent
|
|
342
|
+
- [ ] Error boundaries used for React components
|
|
343
|
+
- [ ] Async operations have proper error handling
|
|
344
|
+
- [ ] Validation errors use Zod or similar
|
|
345
|
+
- [ ] Network errors handled gracefully
|
|
346
|
+
|
|
347
|
+
## Common Mistakes to Avoid
|
|
348
|
+
|
|
349
|
+
### ❌ Don't: Expose Internal Details
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// ❌ WRONG
|
|
353
|
+
toast.error(error.message); // May contain SQL, stack traces, etc.
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### ❌ Don't: Use `any` for Errors
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
// ❌ WRONG
|
|
360
|
+
catch (error: any) {
|
|
361
|
+
console.log(error.message);
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### ❌ Don't: Log Sensitive Data
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// ❌ WRONG
|
|
369
|
+
logger.error('Login failed', { password, token });
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### ❌ Don't: Ignore Errors
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// ❌ WRONG
|
|
376
|
+
try {
|
|
377
|
+
await riskyOperation();
|
|
378
|
+
} catch (error) {
|
|
379
|
+
// Silent failure - user has no idea what happened
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### ❌ Don't: Use Generic Messages
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
// ❌ WRONG
|
|
387
|
+
toast.error('Error occurred'); // Not helpful
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Related Documentation
|
|
391
|
+
|
|
392
|
+
- [Code Quality Standard](./06-code-quality.md) - TypeScript and code style standards
|
|
393
|
+
- [Security Standard](./01-standards-compliance.md#security-standard) - Security requirements
|
|
394
|
+
- [API & RPC Standard](./01-standards-compliance.md#api--rpc-standard) - API error shapes
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
**Last Updated:** 2025-01-28
|
|
399
|
+
**Version:** 1.0.0
|
|
400
|
+
**Applies to:** All pace-core and consuming apps
|
|
401
|
+
|