@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
|
@@ -127,9 +127,9 @@ export function useRoleManagement() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
* Revoke an event app role using the
|
|
130
|
+
* Revoke an event app role using the unified RPC function
|
|
131
131
|
*
|
|
132
|
-
* This function uses the `
|
|
132
|
+
* This function uses the `rbac_role_revoke` RPC which:
|
|
133
133
|
* - Runs with SECURITY DEFINER privileges
|
|
134
134
|
* - Includes proper permission checks
|
|
135
135
|
* - Automatically populates audit fields (revoked_by, timestamps)
|
|
@@ -145,26 +145,114 @@ export function useRoleManagement() {
|
|
|
145
145
|
setError(null);
|
|
146
146
|
|
|
147
147
|
try {
|
|
148
|
-
|
|
148
|
+
// Build context ID from event_id and app_id
|
|
149
|
+
const contextId = `${params.event_id}:${params.app_id}`;
|
|
150
|
+
|
|
151
|
+
const rpcParams = {
|
|
149
152
|
p_user_id: params.user_id,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
p_role: params.role,
|
|
153
|
+
p_role_type: 'event_app' as const,
|
|
154
|
+
p_role_name: params.role,
|
|
155
|
+
p_context_id: contextId,
|
|
154
156
|
p_revoked_by: params.revoked_by || user?.id || undefined
|
|
155
|
-
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Log in development for debugging
|
|
160
|
+
if (import.meta.env.MODE === 'development') {
|
|
161
|
+
console.log('[useRoleManagement] revokeEventAppRole called with:', rpcParams);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const { data, error: rpcError } = await supabase.rpc('rbac_role_revoke', rpcParams);
|
|
156
165
|
|
|
157
166
|
if (rpcError) {
|
|
158
|
-
|
|
167
|
+
// Log full error details in development
|
|
168
|
+
if (import.meta.env.MODE === 'development') {
|
|
169
|
+
console.error('[useRoleManagement] RPC error:', {
|
|
170
|
+
message: rpcError.message,
|
|
171
|
+
details: rpcError.details,
|
|
172
|
+
hint: rpcError.hint,
|
|
173
|
+
code: rpcError.code,
|
|
174
|
+
fullError: rpcError
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// Use just the message for the error (tests expect plain message)
|
|
178
|
+
const errorMessage = rpcError.message || 'Failed to revoke role - unknown RPC error';
|
|
179
|
+
throw new Error(errorMessage);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Log response in development - ALWAYS log, even on failure
|
|
183
|
+
if (import.meta.env.MODE === 'development') {
|
|
184
|
+
console.log('[useRoleManagement] RPC response:', {
|
|
185
|
+
data,
|
|
186
|
+
error: rpcError,
|
|
187
|
+
dataType: Array.isArray(data) ? 'array' : typeof data,
|
|
188
|
+
dataLength: Array.isArray(data) ? data.length : 'N/A'
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// rbac_role_revoke returns a table with success, message, revoked_count, error_code
|
|
193
|
+
// It should always return at least one row
|
|
194
|
+
if (!data || !Array.isArray(data) || data.length === 0) {
|
|
195
|
+
const errorMsg = 'No response from database - role revocation may have failed';
|
|
196
|
+
if (import.meta.env.MODE === 'development') {
|
|
197
|
+
console.error('[useRoleManagement] Empty or null data response:', {
|
|
198
|
+
data,
|
|
199
|
+
dataType: typeof data,
|
|
200
|
+
isArray: Array.isArray(data),
|
|
201
|
+
length: Array.isArray(data) ? data.length : 'N/A'
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
throw new Error(errorMsg);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const result = data[0];
|
|
208
|
+
|
|
209
|
+
// ALWAYS log the result in development, even on failure
|
|
210
|
+
if (import.meta.env.MODE === 'development') {
|
|
211
|
+
console.log('[useRoleManagement] RPC result:', {
|
|
212
|
+
success: result?.success,
|
|
213
|
+
message: result?.message,
|
|
214
|
+
error_code: result?.error_code,
|
|
215
|
+
revoked_count: result?.revoked_count,
|
|
216
|
+
fullResult: result
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (!result || result.success !== true) {
|
|
221
|
+
// Use message if available, otherwise fall back to error_code, otherwise default message
|
|
222
|
+
const errorMessage = result?.message || result?.error_code || 'Role revocation failed';
|
|
223
|
+
|
|
224
|
+
if (import.meta.env.MODE === 'development') {
|
|
225
|
+
console.error('[useRoleManagement] Role revocation failed:', {
|
|
226
|
+
result,
|
|
227
|
+
errorMessage,
|
|
228
|
+
fullData: data,
|
|
229
|
+
rpcParams
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
success: false,
|
|
235
|
+
message: result?.message || undefined,
|
|
236
|
+
error: errorMessage
|
|
237
|
+
};
|
|
159
238
|
}
|
|
160
239
|
|
|
161
240
|
return {
|
|
162
|
-
success:
|
|
163
|
-
message:
|
|
164
|
-
error:
|
|
241
|
+
success: true,
|
|
242
|
+
message: result.message || 'Role revoked successfully',
|
|
243
|
+
error: undefined
|
|
165
244
|
};
|
|
166
245
|
} catch (err) {
|
|
167
246
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
247
|
+
|
|
248
|
+
if (import.meta.env.MODE === 'development') {
|
|
249
|
+
console.error('[useRoleManagement] Exception in revokeEventAppRole:', {
|
|
250
|
+
error: err,
|
|
251
|
+
errorMessage,
|
|
252
|
+
params
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
168
256
|
setError(err instanceof Error ? err : new Error(errorMessage));
|
|
169
257
|
return {
|
|
170
258
|
success: false,
|
|
@@ -173,7 +261,7 @@ export function useRoleManagement() {
|
|
|
173
261
|
} finally {
|
|
174
262
|
setIsLoading(false);
|
|
175
263
|
}
|
|
176
|
-
}, [user?.id]);
|
|
264
|
+
}, [user?.id, supabase]);
|
|
177
265
|
|
|
178
266
|
/**
|
|
179
267
|
* Grant an event app role using the secure RPC function
|
|
@@ -273,16 +361,36 @@ export function useRoleManagement() {
|
|
|
273
361
|
});
|
|
274
362
|
|
|
275
363
|
if (rpcError) {
|
|
276
|
-
|
|
364
|
+
// Use just the message for the error (tests expect plain message)
|
|
365
|
+
const errorMessage = rpcError.message || 'Failed to revoke role - unknown RPC error';
|
|
366
|
+
throw new Error(errorMessage);
|
|
277
367
|
}
|
|
278
368
|
|
|
279
369
|
// rbac_role_revoke returns a table with success, message, revoked_count, error_code
|
|
280
370
|
const result = Array.isArray(data) && data.length > 0 ? data[0] : null;
|
|
281
371
|
|
|
372
|
+
// When data is empty array or null, return error as undefined (tests expect this)
|
|
373
|
+
if (!result) {
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
error: undefined
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (result.success === false) {
|
|
381
|
+
// Use message if available, otherwise fall back to error_code, otherwise default message
|
|
382
|
+
const errorMessage = result.message || result.error_code || 'Role revocation failed';
|
|
383
|
+
return {
|
|
384
|
+
success: false,
|
|
385
|
+
message: result.message || undefined,
|
|
386
|
+
error: errorMessage
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
282
390
|
return {
|
|
283
|
-
success:
|
|
284
|
-
message: result
|
|
285
|
-
error:
|
|
391
|
+
success: true,
|
|
392
|
+
message: result.message || 'Role revoked successfully',
|
|
393
|
+
error: undefined
|
|
286
394
|
};
|
|
287
395
|
} catch (err) {
|
|
288
396
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
@@ -383,7 +491,17 @@ export function useRoleManagement() {
|
|
|
383
491
|
});
|
|
384
492
|
|
|
385
493
|
if (rpcError) {
|
|
386
|
-
|
|
494
|
+
// Include all available error information in the message
|
|
495
|
+
const errorParts = [
|
|
496
|
+
rpcError.message,
|
|
497
|
+
rpcError.details,
|
|
498
|
+
rpcError.hint,
|
|
499
|
+
rpcError.code ? `Error code: ${rpcError.code}` : null
|
|
500
|
+
].filter(Boolean);
|
|
501
|
+
const errorMessage = errorParts.length > 0
|
|
502
|
+
? errorParts.join(' | ')
|
|
503
|
+
: 'Failed to revoke role - unknown RPC error';
|
|
504
|
+
throw new Error(errorMessage);
|
|
387
505
|
}
|
|
388
506
|
|
|
389
507
|
// rbac_role_revoke returns a table with success, message, revoked_count, error_code
|
|
@@ -493,7 +611,17 @@ export function useRoleManagement() {
|
|
|
493
611
|
});
|
|
494
612
|
|
|
495
613
|
if (rpcError) {
|
|
496
|
-
|
|
614
|
+
// Include all available error information in the message
|
|
615
|
+
const errorParts = [
|
|
616
|
+
rpcError.message,
|
|
617
|
+
rpcError.details,
|
|
618
|
+
rpcError.hint,
|
|
619
|
+
rpcError.code ? `Error code: ${rpcError.code}` : null
|
|
620
|
+
].filter(Boolean);
|
|
621
|
+
const errorMessage = errorParts.length > 0
|
|
622
|
+
? errorParts.join(' | ')
|
|
623
|
+
: 'Failed to revoke role - unknown RPC error';
|
|
624
|
+
throw new Error(errorMessage);
|
|
497
625
|
}
|
|
498
626
|
|
|
499
627
|
// rbac_role_revoke returns a table with success, message, revoked_count, error_code
|
|
@@ -223,7 +223,8 @@ export function useSecureSupabase(
|
|
|
223
223
|
const { resolvedScope } = useResolvedScope({
|
|
224
224
|
supabase: authSupabase || null,
|
|
225
225
|
selectedOrganisationId: selectedOrganisation?.id || null,
|
|
226
|
-
selectedEventId: selectedEvent?.event_id || null
|
|
226
|
+
selectedEventId: selectedEvent?.event_id || null,
|
|
227
|
+
selectedEventOrganisationId: selectedEvent?.organisation_id || null
|
|
227
228
|
});
|
|
228
229
|
|
|
229
230
|
// Track previous context to detect changes
|
|
@@ -238,13 +239,8 @@ export function useSecureSupabase(
|
|
|
238
239
|
});
|
|
239
240
|
|
|
240
241
|
return useMemo(() => {
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
return baseClient || authSupabase || null;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Use resolved scope to get organisationId (derived from event if needed)
|
|
247
|
-
// For event-required apps, resolvedScope.organisationId is derived from event
|
|
242
|
+
// Use resolved scope to get organisationId (now available immediately)
|
|
243
|
+
// For event-required apps, resolvedScope.organisationId comes from selectedEvent.organisation_id
|
|
248
244
|
// For org-required apps, resolvedScope.organisationId comes from selectedOrganisation
|
|
249
245
|
const organisationId = resolvedScope?.organisationId;
|
|
250
246
|
const eventId = resolvedScope?.eventId || selectedEvent?.event_id;
|
package/src/rbac/index.ts
CHANGED
|
@@ -45,7 +45,8 @@ export {
|
|
|
45
45
|
isDevelopmentMode,
|
|
46
46
|
} from './config';
|
|
47
47
|
|
|
48
|
-
// Secure client
|
|
48
|
+
// Secure client (internal - use useSecureSupabase hook instead)
|
|
49
|
+
// @internal - These are implementation details. Use useSecureSupabase hook for secure client access.
|
|
49
50
|
export {
|
|
50
51
|
SecureSupabaseClient,
|
|
51
52
|
createSecureClient,
|
|
@@ -59,7 +60,8 @@ export {
|
|
|
59
60
|
SECURE_CLIENT_SYMBOL,
|
|
60
61
|
} from './utils/clientSecurity';
|
|
61
62
|
|
|
62
|
-
// Cache
|
|
63
|
+
// Cache (internal - caching is automatic in hooks and API functions)
|
|
64
|
+
// @internal - These are implementation details. Caching is handled automatically.
|
|
63
65
|
export {
|
|
64
66
|
RBACCache,
|
|
65
67
|
rbacCache,
|
|
@@ -94,7 +96,8 @@ export {
|
|
|
94
96
|
emitAuditEvent,
|
|
95
97
|
} from './audit';
|
|
96
98
|
|
|
97
|
-
// Engine
|
|
99
|
+
// Engine (internal - use isPermitted API instead)
|
|
100
|
+
// @internal - These are implementation details. Use isPermitted API for permission checks.
|
|
98
101
|
export {
|
|
99
102
|
RBACEngine,
|
|
100
103
|
createRBACEngine,
|
|
@@ -110,17 +113,13 @@ export * from './hooks';
|
|
|
110
113
|
// Users should now use useRBAC() hook directly without a provider wrapper
|
|
111
114
|
// export * from './providers';
|
|
112
115
|
|
|
113
|
-
// Adapters
|
|
116
|
+
// Adapters (Server-side only - React components removed)
|
|
114
117
|
export {
|
|
115
118
|
withPermissionGuard,
|
|
116
119
|
withAccessLevelGuard,
|
|
117
120
|
withRoleGuard,
|
|
118
|
-
PermissionGuard,
|
|
119
|
-
AccessLevelGuard,
|
|
120
121
|
createRBACMiddleware,
|
|
121
122
|
createRBACExpressMiddleware,
|
|
122
|
-
hasPermissionCached,
|
|
123
|
-
hasAnyPermissionCached,
|
|
124
123
|
} from './adapters';
|
|
125
124
|
|
|
126
125
|
// Main API functions
|
|
@@ -131,7 +130,6 @@ export {
|
|
|
131
130
|
getRoleContext,
|
|
132
131
|
isPermitted,
|
|
133
132
|
isPermittedCached,
|
|
134
|
-
hasPermission,
|
|
135
133
|
hasAnyPermission,
|
|
136
134
|
hasAllPermissions,
|
|
137
135
|
setupRBAC,
|
package/src/rbac/permissions.ts
CHANGED
|
@@ -106,35 +106,35 @@ export const EVENT_APP_PERMISSIONS = {
|
|
|
106
106
|
// ============================================================================
|
|
107
107
|
|
|
108
108
|
export const PAGE_PERMISSIONS = {
|
|
109
|
-
// General page access
|
|
109
|
+
// General page access (generic - used for wildcard checks)
|
|
110
110
|
READ_PAGE: 'read:page' as Permission,
|
|
111
111
|
CREATE_PAGE: 'create:page' as Permission,
|
|
112
112
|
UPDATE_PAGE: 'update:page' as Permission,
|
|
113
113
|
DELETE_PAGE: 'delete:page' as Permission,
|
|
114
114
|
|
|
115
115
|
// Admin pages
|
|
116
|
-
READ_ADMIN: 'read:admin' as Permission,
|
|
117
|
-
CREATE_ADMIN: 'create:admin' as Permission,
|
|
118
|
-
UPDATE_ADMIN: 'update:admin' as Permission,
|
|
119
|
-
DELETE_ADMIN: 'delete:admin' as Permission,
|
|
116
|
+
READ_ADMIN: 'read:page.admin' as Permission,
|
|
117
|
+
CREATE_ADMIN: 'create:page.admin' as Permission,
|
|
118
|
+
UPDATE_ADMIN: 'update:page.admin' as Permission,
|
|
119
|
+
DELETE_ADMIN: 'delete:page.admin' as Permission,
|
|
120
120
|
|
|
121
121
|
// Dashboard pages
|
|
122
|
-
READ_DASHBOARD: 'read:dashboard' as Permission,
|
|
123
|
-
CREATE_DASHBOARD: 'create:dashboard' as Permission,
|
|
124
|
-
UPDATE_DASHBOARD: 'update:dashboard' as Permission,
|
|
125
|
-
DELETE_DASHBOARD: 'delete:dashboard' as Permission,
|
|
122
|
+
READ_DASHBOARD: 'read:page.dashboard' as Permission,
|
|
123
|
+
CREATE_DASHBOARD: 'create:page.dashboard' as Permission,
|
|
124
|
+
UPDATE_DASHBOARD: 'update:page.dashboard' as Permission,
|
|
125
|
+
DELETE_DASHBOARD: 'delete:page.dashboard' as Permission,
|
|
126
126
|
|
|
127
127
|
// Settings pages
|
|
128
|
-
READ_SETTINGS: 'read:settings' as Permission,
|
|
129
|
-
CREATE_SETTINGS: 'create:settings' as Permission,
|
|
130
|
-
UPDATE_SETTINGS: 'update:settings' as Permission,
|
|
131
|
-
DELETE_SETTINGS: 'delete:settings' as Permission,
|
|
128
|
+
READ_SETTINGS: 'read:page.settings' as Permission,
|
|
129
|
+
CREATE_SETTINGS: 'create:page.settings' as Permission,
|
|
130
|
+
UPDATE_SETTINGS: 'update:page.settings' as Permission,
|
|
131
|
+
DELETE_SETTINGS: 'delete:page.settings' as Permission,
|
|
132
132
|
|
|
133
133
|
// Reports pages
|
|
134
|
-
READ_REPORTS: 'read:reports' as Permission,
|
|
135
|
-
CREATE_REPORTS: 'create:reports' as Permission,
|
|
136
|
-
UPDATE_REPORTS: 'update:reports' as Permission,
|
|
137
|
-
DELETE_REPORTS: 'delete:reports' as Permission,
|
|
134
|
+
READ_REPORTS: 'read:page.reports' as Permission,
|
|
135
|
+
CREATE_REPORTS: 'create:page.reports' as Permission,
|
|
136
|
+
UPDATE_REPORTS: 'update:page.reports' as Permission,
|
|
137
|
+
DELETE_REPORTS: 'delete:page.reports' as Permission,
|
|
138
138
|
} as const;
|
|
139
139
|
|
|
140
140
|
// ============================================================================
|
|
@@ -68,19 +68,21 @@ export class ContextValidator {
|
|
|
68
68
|
* Resolve scope based on page-level scope_type
|
|
69
69
|
*
|
|
70
70
|
* This method handles page-level scoping. All pages have explicit scope_type set.
|
|
71
|
-
* Used for hybrid apps
|
|
71
|
+
* Used for hybrid apps that have both event and organisation pages.
|
|
72
72
|
*
|
|
73
73
|
* @param scope - Current scope
|
|
74
74
|
* @param pageScopeType - Page scope type ('event', 'organisation', or 'both')
|
|
75
75
|
* @param appName - App name (for PORTAL/ADMIN special case)
|
|
76
|
-
* @param supabase - Supabase client (for deriving org from event)
|
|
76
|
+
* @param supabase - Supabase client (for deriving org from event, only if not already provided)
|
|
77
|
+
* @param immediateOrganisationId - Optional immediate organisation ID (from selectedEvent.organisation_id) - avoids querying
|
|
77
78
|
* @returns Resolved scope with all required context
|
|
78
79
|
*/
|
|
79
80
|
static async resolveScopeForPage(
|
|
80
81
|
scope: Scope,
|
|
81
82
|
pageScopeType: PageScopeType,
|
|
82
83
|
appName?: string,
|
|
83
|
-
supabase?: SupabaseClient<Database> | null
|
|
84
|
+
supabase?: SupabaseClient<Database> | null,
|
|
85
|
+
immediateOrganisationId?: string | null
|
|
84
86
|
): Promise<ContextValidationResult> {
|
|
85
87
|
// Use page-level scope (single source of truth)
|
|
86
88
|
const effectiveScopeType = pageScopeType;
|
|
@@ -89,7 +91,19 @@ export class ContextValidator {
|
|
|
89
91
|
if (effectiveScopeType === 'both') {
|
|
90
92
|
// For 'both' pages, we need at least one context (org or event)
|
|
91
93
|
// Both will be checked during permission evaluation
|
|
94
|
+
// For PORTAL/ADMIN apps, both contexts are optional
|
|
92
95
|
if (!scope.organisationId && !scope.eventId) {
|
|
96
|
+
if (allowsOptionalContexts(appName)) {
|
|
97
|
+
return {
|
|
98
|
+
isValid: true,
|
|
99
|
+
resolvedScope: {
|
|
100
|
+
organisationId: undefined,
|
|
101
|
+
eventId: undefined,
|
|
102
|
+
appId: scope.appId
|
|
103
|
+
},
|
|
104
|
+
error: null
|
|
105
|
+
};
|
|
106
|
+
}
|
|
93
107
|
return {
|
|
94
108
|
isValid: false,
|
|
95
109
|
resolvedScope: null,
|
|
@@ -97,8 +111,8 @@ export class ContextValidator {
|
|
|
97
111
|
};
|
|
98
112
|
}
|
|
99
113
|
|
|
100
|
-
//
|
|
101
|
-
let organisationId = scope.organisationId;
|
|
114
|
+
// Use immediate orgId if provided, otherwise derive from event
|
|
115
|
+
let organisationId = scope.organisationId || immediateOrganisationId || undefined;
|
|
102
116
|
if (!organisationId && scope.eventId && supabase) {
|
|
103
117
|
try {
|
|
104
118
|
const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
|
|
@@ -123,6 +137,18 @@ export class ContextValidator {
|
|
|
123
137
|
// Handle 'event' scope - requires event context
|
|
124
138
|
if (effectiveScopeType === 'event') {
|
|
125
139
|
if (!scope.eventId) {
|
|
140
|
+
// For PORTAL/ADMIN apps, event context is optional
|
|
141
|
+
if (allowsOptionalContexts(appName)) {
|
|
142
|
+
return {
|
|
143
|
+
isValid: true,
|
|
144
|
+
resolvedScope: {
|
|
145
|
+
organisationId: scope.organisationId,
|
|
146
|
+
eventId: undefined,
|
|
147
|
+
appId: scope.appId
|
|
148
|
+
},
|
|
149
|
+
error: null
|
|
150
|
+
};
|
|
151
|
+
}
|
|
126
152
|
return {
|
|
127
153
|
isValid: false,
|
|
128
154
|
resolvedScope: null,
|
|
@@ -130,8 +156,8 @@ export class ContextValidator {
|
|
|
130
156
|
};
|
|
131
157
|
}
|
|
132
158
|
|
|
133
|
-
//
|
|
134
|
-
let organisationId: UUID | undefined = scope.organisationId;
|
|
159
|
+
// Use immediate orgId if provided, otherwise derive from event
|
|
160
|
+
let organisationId: UUID | undefined = scope.organisationId || immediateOrganisationId || undefined;
|
|
135
161
|
if (!organisationId && supabase && scope.eventId) {
|
|
136
162
|
try {
|
|
137
163
|
const derivedOrgId = await this.deriveOrgFromEvent(supabase, scope.eventId);
|
|
@@ -167,6 +193,18 @@ export class ContextValidator {
|
|
|
167
193
|
// Handle 'organisation' scope - requires organisation context
|
|
168
194
|
if (effectiveScopeType === 'organisation') {
|
|
169
195
|
if (!scope.organisationId) {
|
|
196
|
+
// For PORTAL/ADMIN apps, organisation context is optional
|
|
197
|
+
if (allowsOptionalContexts(appName)) {
|
|
198
|
+
return {
|
|
199
|
+
isValid: true,
|
|
200
|
+
resolvedScope: {
|
|
201
|
+
organisationId: undefined,
|
|
202
|
+
eventId: scope.eventId,
|
|
203
|
+
appId: scope.appId
|
|
204
|
+
},
|
|
205
|
+
error: null
|
|
206
|
+
};
|
|
207
|
+
}
|
|
170
208
|
return {
|
|
171
209
|
isValid: false,
|
|
172
210
|
resolvedScope: null,
|