@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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
lastUpdated: 2025-01-
|
|
2
|
+
lastUpdated: 2025-01-28T00:00:00+11:00
|
|
3
3
|
version: 0.5.182
|
|
4
4
|
reviewedBy: rls-audit-and-fixes
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# RBAC and RLS Standard
|
|
8
8
|
|
|
9
|
+
**🤖 Cursor Rule**: See [09-rbac-compliance.mdc](../../cursor-rules/09-rbac-compliance.mdc) for AI-optimized directives that automatically enforce RBAC contract compliance (ESLint-enforced).
|
|
10
|
+
|
|
9
11
|
## Purpose
|
|
10
12
|
|
|
11
13
|
Define standards for Row-Level Security (RLS) policies and Role-Based Access Control (RBAC) integration to ensure security, performance, and maintainability.
|
|
@@ -101,16 +103,36 @@ FOR SELECT USING (
|
|
|
101
103
|
);
|
|
102
104
|
```
|
|
103
105
|
|
|
106
|
+
## Helper Selection Quick Guide
|
|
107
|
+
|
|
108
|
+
| Scenario | Helper(s) to use | Notes |
|
|
109
|
+
|----------|------------------|-------|
|
|
110
|
+
| Organisation-scoped rows | `check_user_organisation_access(organisation_id)` | Always check `organisation_id IS NOT NULL` first. |
|
|
111
|
+
| Page-permission checks | `check_rbac_permission_with_context(..., get_app_id('APP'))` | Use the wrapper instead of inline `rbac_check_permission_simplified` + `auth.uid()`. |
|
|
112
|
+
| Event-scoped rows | `check_user_event_access(event_id)` | Combine with permission wrapper when pages require it. |
|
|
113
|
+
| Public rows | `check_public_event_access(event_id)` or `is_public = true` | Keep anonymous and authenticated policies separate. |
|
|
114
|
+
| User-owned rows | `get_effective_user_id() = user_id` | Use when `organisation_id IS NULL`. |
|
|
115
|
+
| Service role bypass | `is_service_role()` | Put first in OR chains; use sparingly. |
|
|
116
|
+
|
|
117
|
+
## RLS Helper Requirements (enforced)
|
|
118
|
+
|
|
119
|
+
- Helper functions **must** be `STABLE`, `SECURITY DEFINER`, and `SET search_path TO public`.
|
|
120
|
+
- **Never** inline `auth.uid()`, `auth.role()`, or `current_setting()` inside policies.
|
|
121
|
+
- Use `get_app_id()` for app UUIDs (do not hardcode UUIDs or call legacy getters).
|
|
122
|
+
- Avoid subqueries inside policies; move lookups into helpers.
|
|
123
|
+
|
|
104
124
|
## Standard Helper Functions
|
|
105
125
|
|
|
106
126
|
### Core Helper Functions
|
|
107
127
|
|
|
108
128
|
These functions are available for use in RLS policies:
|
|
109
129
|
|
|
110
|
-
#### `is_super_admin()`
|
|
130
|
+
#### `is_super_admin(p_user_id UUID)`
|
|
111
131
|
- **Returns**: `boolean`
|
|
112
|
-
- **Purpose**: Checks if
|
|
113
|
-
- **Usage**: `is_super_admin()`
|
|
132
|
+
- **Purpose**: Checks if the specified user is a super admin
|
|
133
|
+
- **Usage**: `is_super_admin(safe_get_user_id_for_rls())`
|
|
134
|
+
- **⚠️ CRITICAL**: Always pass an explicit user ID parameter. Never call without parameters.
|
|
135
|
+
- **Security**: This function requires an explicit parameter to prevent fallback strategy vulnerabilities. Use `safe_get_user_id_for_rls()` to get the user ID in RLS policies.
|
|
114
136
|
|
|
115
137
|
#### `check_user_organisation_access(p_organisation_id UUID)`
|
|
116
138
|
- **Returns**: `boolean`
|
|
@@ -212,7 +234,7 @@ FOR SELECT TO authenticated
|
|
|
212
234
|
USING (
|
|
213
235
|
organisation_id IS NOT NULL
|
|
214
236
|
AND (
|
|
215
|
-
is_super_admin()
|
|
237
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
216
238
|
OR check_user_organisation_access(organisation_id)
|
|
217
239
|
)
|
|
218
240
|
);
|
|
@@ -223,6 +245,7 @@ USING (
|
|
|
223
245
|
**Notes:**
|
|
224
246
|
- Always check `organisation_id IS NOT NULL` first
|
|
225
247
|
- Super admin check comes before organisation access check
|
|
248
|
+
- **MUST** use `is_super_admin(safe_get_user_id_for_rls())` with explicit parameter
|
|
226
249
|
- Use `check_user_organisation_access()` for basic membership checks
|
|
227
250
|
|
|
228
251
|
### RBAC Permission-Based Policy
|
|
@@ -236,7 +259,7 @@ FOR SELECT TO authenticated
|
|
|
236
259
|
USING (
|
|
237
260
|
organisation_id IS NOT NULL
|
|
238
261
|
AND (
|
|
239
|
-
is_super_admin()
|
|
262
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
240
263
|
OR check_rbac_permission_with_context(
|
|
241
264
|
'read:page.table_name',
|
|
242
265
|
'table_name',
|
|
@@ -258,7 +281,7 @@ FOR SELECT TO authenticated
|
|
|
258
281
|
USING (
|
|
259
282
|
organisation_id IS NOT NULL
|
|
260
283
|
AND (
|
|
261
|
-
is_super_admin()
|
|
284
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
262
285
|
OR check_rbac_permission_with_context(
|
|
263
286
|
'read:page.table_name',
|
|
264
287
|
'table_name',
|
|
@@ -275,7 +298,7 @@ FOR INSERT TO authenticated
|
|
|
275
298
|
WITH CHECK (
|
|
276
299
|
organisation_id IS NOT NULL
|
|
277
300
|
AND (
|
|
278
|
-
is_super_admin()
|
|
301
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
279
302
|
OR check_rbac_permission_with_context(
|
|
280
303
|
'create:page.table_name',
|
|
281
304
|
'table_name',
|
|
@@ -292,7 +315,7 @@ FOR UPDATE TO authenticated
|
|
|
292
315
|
USING (
|
|
293
316
|
organisation_id IS NOT NULL
|
|
294
317
|
AND (
|
|
295
|
-
is_super_admin()
|
|
318
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
296
319
|
OR check_rbac_permission_with_context(
|
|
297
320
|
'update:page.table_name',
|
|
298
321
|
'table_name',
|
|
@@ -305,7 +328,7 @@ USING (
|
|
|
305
328
|
WITH CHECK (
|
|
306
329
|
organisation_id IS NOT NULL
|
|
307
330
|
AND (
|
|
308
|
-
is_super_admin()
|
|
331
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
309
332
|
OR check_rbac_permission_with_context(
|
|
310
333
|
'update:page.table_name',
|
|
311
334
|
'table_name',
|
|
@@ -322,7 +345,7 @@ FOR DELETE TO authenticated
|
|
|
322
345
|
USING (
|
|
323
346
|
organisation_id IS NOT NULL
|
|
324
347
|
AND (
|
|
325
|
-
is_super_admin()
|
|
348
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
326
349
|
OR check_rbac_permission_with_context(
|
|
327
350
|
'delete:page.table_name',
|
|
328
351
|
'table_name',
|
|
@@ -351,7 +374,7 @@ FOR SELECT TO authenticated
|
|
|
351
374
|
USING (
|
|
352
375
|
organisation_id IS NOT NULL
|
|
353
376
|
AND (
|
|
354
|
-
is_super_admin()
|
|
377
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
355
378
|
OR check_user_event_access(event_id)
|
|
356
379
|
)
|
|
357
380
|
);
|
|
@@ -387,7 +410,7 @@ USING (
|
|
|
387
410
|
organisation_id IS NOT NULL
|
|
388
411
|
AND is_authenticated_user()
|
|
389
412
|
AND (
|
|
390
|
-
is_super_admin()
|
|
413
|
+
is_super_admin(safe_get_user_id_for_rls())
|
|
391
414
|
OR check_user_organisation_access(organisation_id)
|
|
392
415
|
)
|
|
393
416
|
)
|
|
@@ -542,7 +565,7 @@ USING (is_authenticated_user());
|
|
|
542
565
|
```sql
|
|
543
566
|
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
544
567
|
FOR SELECT TO authenticated
|
|
545
|
-
USING (is_super_admin());
|
|
568
|
+
USING (is_super_admin(safe_get_user_id_for_rls()));
|
|
546
569
|
```
|
|
547
570
|
|
|
548
571
|
**Example:** `rbac_global_roles`, `rbac_policy_configs`
|
|
@@ -552,20 +575,20 @@ USING (is_super_admin());
|
|
|
552
575
|
-- All operations restricted to super admin
|
|
553
576
|
CREATE POLICY "rbac_select_table_name" ON table_name
|
|
554
577
|
FOR SELECT TO authenticated
|
|
555
|
-
USING (is_super_admin());
|
|
578
|
+
USING (is_super_admin(safe_get_user_id_for_rls()));
|
|
556
579
|
|
|
557
580
|
CREATE POLICY "rbac_insert_table_name" ON table_name
|
|
558
581
|
FOR INSERT TO authenticated
|
|
559
|
-
WITH CHECK (is_super_admin());
|
|
582
|
+
WITH CHECK (is_super_admin(safe_get_user_id_for_rls()));
|
|
560
583
|
|
|
561
584
|
CREATE POLICY "rbac_update_table_name" ON table_name
|
|
562
585
|
FOR UPDATE TO authenticated
|
|
563
|
-
USING (is_super_admin())
|
|
564
|
-
WITH CHECK (is_super_admin());
|
|
586
|
+
USING (is_super_admin(safe_get_user_id_for_rls()))
|
|
587
|
+
WITH CHECK (is_super_admin(safe_get_user_id_for_rls()));
|
|
565
588
|
|
|
566
589
|
CREATE POLICY "rbac_delete_table_name" ON table_name
|
|
567
590
|
FOR DELETE TO authenticated
|
|
568
|
-
USING (is_super_admin());
|
|
591
|
+
USING (is_super_admin(safe_get_user_id_for_rls()));
|
|
569
592
|
```
|
|
570
593
|
|
|
571
594
|
### Common Patterns Summary
|
|
@@ -579,19 +602,121 @@ USING (is_super_admin());
|
|
|
579
602
|
| Service Role | System operations | `is_service_role()` |
|
|
580
603
|
| Public Access | Anonymous users | `check_public_event_access()` or `is_public` flag |
|
|
581
604
|
| Read-Only Types | Reference tables | `is_authenticated_user()` |
|
|
582
|
-
| Super Admin Only | Admin-only tables | `is_super_admin()` |
|
|
605
|
+
| Super Admin Only | Admin-only tables | `is_super_admin(safe_get_user_id_for_rls())` |
|
|
583
606
|
|
|
584
607
|
### Policy Best Practices
|
|
585
608
|
|
|
586
609
|
1. **Always use helper functions** - Never inline `auth.uid()`, `auth.role()`, or `current_setting()`
|
|
587
610
|
2. **Check NULL first** - Always check `organisation_id IS NOT NULL` before using it
|
|
588
|
-
3. **Super admin first** - Super admin checks should come before other checks in OR conditions
|
|
611
|
+
3. **Super admin first** - Super admin checks should come before other checks in OR conditions. **MUST** use `is_super_admin(safe_get_user_id_for_rls())` with explicit parameter - never call without parameters.
|
|
589
612
|
4. **Service role first** - Service role checks should be the first condition in multi-condition policies
|
|
590
613
|
5. **Consistent naming** - Follow the naming convention: `rbac_{operation}_{table}_{scope}`
|
|
591
614
|
6. **Document exceptions** - If a policy deviates from standard patterns, add a comment explaining why
|
|
592
615
|
7. **Test thoroughly** - Test with different user roles (super_admin, org_admin, member, anon)
|
|
593
616
|
8. **Avoid `true OR ...`** - Never use `true OR ...` conditions as they bypass all security checks
|
|
594
617
|
|
|
618
|
+
## Edge Functions and Serverless Functions
|
|
619
|
+
|
|
620
|
+
**Edge Functions (Deno serverless functions) MUST use pace-core's `isPermitted()` API function.** Edge Functions cannot use React hooks, but pace-core provides programmatic APIs that work outside React.
|
|
621
|
+
|
|
622
|
+
### ✅ CORRECT - Edge Function Pattern
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// supabase/functions/my-function/index.ts
|
|
626
|
+
import { createClient } from 'jsr:@supabase/supabase-js@2';
|
|
627
|
+
import { setupRBAC, isPermitted } from 'npm:@jmruthers/pace-core@^0.6.0/rbac';
|
|
628
|
+
|
|
629
|
+
Deno.serve(async (req: Request) => {
|
|
630
|
+
// 1. Create Supabase client from request headers
|
|
631
|
+
const authHeader = req.headers.get('Authorization');
|
|
632
|
+
if (!authHeader) {
|
|
633
|
+
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const supabase = createClient(
|
|
637
|
+
Deno.env.get('SUPABASE_URL') ?? '',
|
|
638
|
+
Deno.env.get('SUPABASE_ANON_KEY') ?? '',
|
|
639
|
+
{
|
|
640
|
+
global: {
|
|
641
|
+
headers: { Authorization: authHeader },
|
|
642
|
+
},
|
|
643
|
+
}
|
|
644
|
+
);
|
|
645
|
+
|
|
646
|
+
// 2. Get user from session
|
|
647
|
+
const { data: { user } } = await supabase.auth.getUser();
|
|
648
|
+
if (!user) {
|
|
649
|
+
return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 });
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// 3. Setup RBAC (required before using isPermitted)
|
|
653
|
+
setupRBAC(supabase);
|
|
654
|
+
|
|
655
|
+
// 4. Extract organisation context from request
|
|
656
|
+
const organisationId = req.headers.get('x-organisation-id') ||
|
|
657
|
+
(await req.json()).organisationId;
|
|
658
|
+
|
|
659
|
+
if (!organisationId) {
|
|
660
|
+
return new Response(JSON.stringify({ error: 'Organisation context required' }), { status: 400 });
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// 5. Check permission using pace-core API
|
|
664
|
+
const hasPermission = await isPermitted({
|
|
665
|
+
userId: user.id,
|
|
666
|
+
scope: { organisationId },
|
|
667
|
+
permission: 'read:dashboard',
|
|
668
|
+
pageId: 'dashboard'
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
if (!hasPermission) {
|
|
672
|
+
return new Response(JSON.stringify({ error: 'Permission denied' }), { status: 403 });
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// 6. Proceed with function logic
|
|
676
|
+
return new Response(JSON.stringify({ success: true }));
|
|
677
|
+
});
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### ❌ FORBIDDEN - Custom RBAC Helper in Edge Functions
|
|
681
|
+
|
|
682
|
+
**Creating custom RBAC helper functions in Edge Functions is FORBIDDEN.** pace-core provides all necessary APIs.
|
|
683
|
+
|
|
684
|
+
```typescript
|
|
685
|
+
// ❌ FORBIDDEN - Custom RBAC helper
|
|
686
|
+
// supabase/functions/_shared/rbac.ts
|
|
687
|
+
export async function checkPermission(userId: string, permission: string) {
|
|
688
|
+
// Custom logic that bypasses pace-core
|
|
689
|
+
const { data } = await supabase.rpc('rbac_check_permission_simplified', {
|
|
690
|
+
p_user_id: userId,
|
|
691
|
+
p_permission: permission
|
|
692
|
+
});
|
|
693
|
+
return data;
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
### Why No Exceptions
|
|
698
|
+
|
|
699
|
+
- pace-core provides `isPermitted()` API that works outside React
|
|
700
|
+
- `setupRBAC()` initializes the engine with a Supabase client
|
|
701
|
+
- No custom helpers needed - use pace-core APIs directly
|
|
702
|
+
- Custom helpers bypass security validation, caching, and audit logging
|
|
703
|
+
|
|
704
|
+
### Edge Function Requirements
|
|
705
|
+
|
|
706
|
+
1. **MUST** call `setupRBAC(supabase)` before using `isPermitted()`
|
|
707
|
+
2. **MUST** extract `userId` from Supabase auth session
|
|
708
|
+
3. **MUST** extract `organisationId` from request (headers, body, or query params)
|
|
709
|
+
4. **MUST** use `isPermitted()` with complete `PermissionCheck` input
|
|
710
|
+
5. **MUST NOT** create custom RBAC helper functions
|
|
711
|
+
6. **MUST NOT** call `rbac_check_permission_simplified` RPC directly
|
|
712
|
+
|
|
713
|
+
## Security Baseline (aligns with Security Standard)
|
|
714
|
+
- Never bypass RLS; validate all inputs and sanitize logs (no tokens/PII).
|
|
715
|
+
- Use safe, user-friendly error messaging.
|
|
716
|
+
- Prefer pace-core security helpers and secure clients (`useSecureSupabase`, RBAC helpers) over custom implementations.
|
|
717
|
+
- Monitor RLS performance (avoid subqueries/InitPlan); keep helpers `STABLE SECURITY DEFINER` with `SET search_path TO public`.
|
|
718
|
+
- **Edge Functions MUST use pace-core `isPermitted()` API - no exceptions allowed.**
|
|
719
|
+
|
|
595
720
|
### Common Pitfalls to Avoid
|
|
596
721
|
|
|
597
722
|
**❌ DON'T:**
|
|
@@ -648,13 +773,7 @@ Tables are assigned to specific apps for RBAC permission checking:
|
|
|
648
773
|
|
|
649
774
|
### Before Merging RLS Changes
|
|
650
775
|
|
|
651
|
-
1. **Run
|
|
652
|
-
```bash
|
|
653
|
-
npm run audit:rls
|
|
654
|
-
```
|
|
655
|
-
This checks for violations and should pass with zero violations.
|
|
656
|
-
|
|
657
|
-
2. **Run Supabase Advisors**:
|
|
776
|
+
1. **Run Supabase Advisors**:
|
|
658
777
|
```bash
|
|
659
778
|
supabase advisors performance
|
|
660
779
|
supabase advisors security
|
|
@@ -686,32 +805,9 @@ Tables are assigned to specific apps for RBAC permission checking:
|
|
|
686
805
|
|
|
687
806
|
### Ongoing RLS Compliance Monitoring
|
|
688
807
|
|
|
689
|
-
**Run
|
|
808
|
+
**Run Supabase advisors regularly** to catch any rogue policies that violate standards:
|
|
690
809
|
|
|
691
810
|
```bash
|
|
692
|
-
# Quick audit (recommended before merging PRs)
|
|
693
|
-
npm run audit:rls
|
|
694
|
-
|
|
695
|
-
# Or use test database
|
|
696
|
-
npm run audit:rls:test
|
|
697
|
-
|
|
698
|
-
# For CI/CD (fails on violations)
|
|
699
|
-
npm run audit:rls:ci
|
|
700
|
-
```
|
|
701
|
-
|
|
702
|
-
The audit checks for:
|
|
703
|
-
- Tables with RLS enabled but no policies
|
|
704
|
-
- Policies using inline `auth.uid()` calls
|
|
705
|
-
- Policies using `current_setting()` directly
|
|
706
|
-
- Helper functions missing STABLE/SECURITY DEFINER
|
|
707
|
-
|
|
708
|
-
### Weekly Health Checks
|
|
709
|
-
|
|
710
|
-
Run weekly:
|
|
711
|
-
```bash
|
|
712
|
-
# RLS compliance audit
|
|
713
|
-
npm run audit:rls
|
|
714
|
-
|
|
715
811
|
# Performance advisors
|
|
716
812
|
supabase advisors performance
|
|
717
813
|
|
|
@@ -772,8 +868,7 @@ date +"%Y%m%d%H%M%S"
|
|
|
772
868
|
|
|
773
869
|
## Related Documentation
|
|
774
870
|
|
|
775
|
-
-
|
|
871
|
+
- Security baseline (see section above)
|
|
776
872
|
- [RLS Policy Remediation Plan](../troubleshooting/rls-policy-remediation-plan-combined.md)
|
|
777
873
|
- [Database Unhealthiness Diagnosis](../troubleshooting/database-unhealthiness-diagnosis.md)
|
|
778
874
|
- [RBAC-RLS Integration Guide](../rbac/rbac-rls-integration.md)
|
|
779
|
-
|