@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
|
@@ -205,6 +205,14 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
205
205
|
logger.error('InactivityService', 'Error during idle logout:', error);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
// Clear sessionStorage on logout
|
|
209
|
+
try {
|
|
210
|
+
sessionStorage.clear();
|
|
211
|
+
} catch (storageError) {
|
|
212
|
+
// Ignore storage errors (e.g., in private browsing mode)
|
|
213
|
+
logger.warn('InactivityService', 'Failed to clear sessionStorage', { error: storageError });
|
|
214
|
+
}
|
|
215
|
+
|
|
208
216
|
// Call app callback for navigation/redirect
|
|
209
217
|
this.onIdleLogout?.('inactivity');
|
|
210
218
|
this.notify();
|
|
@@ -231,6 +239,14 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
231
239
|
logger.error('InactivityService', 'Error during manual sign out:', error);
|
|
232
240
|
}
|
|
233
241
|
|
|
242
|
+
// Clear sessionStorage on logout
|
|
243
|
+
try {
|
|
244
|
+
sessionStorage.clear();
|
|
245
|
+
} catch (storageError) {
|
|
246
|
+
// Ignore storage errors (e.g., in private browsing mode)
|
|
247
|
+
logger.warn('InactivityService', 'Failed to clear sessionStorage', { error: storageError });
|
|
248
|
+
}
|
|
249
|
+
|
|
234
250
|
// Call app callback for navigation/redirect
|
|
235
251
|
this.onIdleLogout?.('inactivity');
|
|
236
252
|
this.notify();
|
|
@@ -291,10 +307,10 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
291
307
|
private setupEventHandlers(): void {
|
|
292
308
|
if (typeof window === 'undefined') return;
|
|
293
309
|
|
|
294
|
-
let idleTimer: NodeJS.Timeout | null = null;
|
|
295
310
|
let warningTimer: NodeJS.Timeout | null = null;
|
|
311
|
+
let logoutTimer: NodeJS.Timeout | null = null;
|
|
312
|
+
let countdownInterval: NodeJS.Timeout | null = null;
|
|
296
313
|
let lastActivity = Date.now();
|
|
297
|
-
let pollInterval: NodeJS.Timeout | null = null;
|
|
298
314
|
|
|
299
315
|
// Store previous state for comparison
|
|
300
316
|
let prevIsIdle = false;
|
|
@@ -303,19 +319,29 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
303
319
|
let prevInactivityTimeRemaining = 0;
|
|
304
320
|
let prevTimeRemaining = this.idleTimeoutMs;
|
|
305
321
|
|
|
306
|
-
//
|
|
307
|
-
const
|
|
322
|
+
// Calculate time until warning and logout
|
|
323
|
+
const getTimeUntilWarning = () => {
|
|
324
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
325
|
+
return Math.max(0, (this.idleTimeoutMs - this.warnBeforeMs) - timeSinceActivity);
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const getTimeUntilLogout = () => {
|
|
329
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
330
|
+
return Math.max(0, this.idleTimeoutMs - timeSinceActivity);
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// Update state and notify if changed
|
|
334
|
+
const updateState = (forceNotify = false) => {
|
|
308
335
|
const now = Date.now();
|
|
309
336
|
const timeSinceActivity = now - lastActivity;
|
|
310
337
|
const timeUntilIdle = this.idleTimeoutMs - timeSinceActivity;
|
|
311
|
-
const timeUntilWarning = (this.idleTimeoutMs - this.warnBeforeMs) - timeSinceActivity;
|
|
312
338
|
|
|
313
|
-
// Calculate new state values
|
|
314
|
-
const newIsIdle = timeSinceActivity >=
|
|
315
|
-
const newShowWarning =
|
|
339
|
+
// Calculate new state values
|
|
340
|
+
const newIsIdle = timeSinceActivity >= this.idleTimeoutMs;
|
|
341
|
+
const newShowWarning = timeSinceActivity >= (this.idleTimeoutMs - this.warnBeforeMs) && !newIsIdle;
|
|
316
342
|
const newShowInactivityWarning = newShowWarning;
|
|
317
343
|
const newInactivityTimeRemaining = newShowWarning
|
|
318
|
-
? Math.ceil(
|
|
344
|
+
? Math.ceil(timeUntilIdle / 1000)
|
|
319
345
|
: 0;
|
|
320
346
|
const newTimeRemaining = Math.max(0, timeUntilIdle);
|
|
321
347
|
|
|
@@ -324,11 +350,11 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
324
350
|
prevIsIdle !== newIsIdle ||
|
|
325
351
|
prevShowWarning !== newShowWarning ||
|
|
326
352
|
prevShowInactivityWarning !== newShowInactivityWarning ||
|
|
327
|
-
prevInactivityTimeRemaining !== newInactivityTimeRemaining ||
|
|
353
|
+
(newShowWarning && prevInactivityTimeRemaining !== newInactivityTimeRemaining) ||
|
|
328
354
|
prevTimeRemaining !== newTimeRemaining;
|
|
329
355
|
|
|
330
|
-
// Only update and notify if state changed
|
|
331
|
-
if (stateChanged) {
|
|
356
|
+
// Only update and notify if state changed or forced
|
|
357
|
+
if (stateChanged || forceNotify) {
|
|
332
358
|
this._isIdle = newIsIdle;
|
|
333
359
|
this._showWarning = newShowWarning;
|
|
334
360
|
this._showInactivityWarning = newShowInactivityWarning;
|
|
@@ -342,76 +368,147 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
342
368
|
prevInactivityTimeRemaining = newInactivityTimeRemaining;
|
|
343
369
|
prevTimeRemaining = newTimeRemaining;
|
|
344
370
|
|
|
345
|
-
|
|
371
|
+
if (stateChanged) {
|
|
372
|
+
this.notify();
|
|
373
|
+
}
|
|
346
374
|
|
|
347
375
|
// Handle idle logout if needed
|
|
348
|
-
if (newIsIdle
|
|
376
|
+
if (newIsIdle) {
|
|
349
377
|
this.handleIdleLogout();
|
|
350
378
|
}
|
|
351
379
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// Schedule next state check based on current state
|
|
383
|
+
const scheduleNextCheck = () => {
|
|
384
|
+
// Clear existing timers
|
|
359
385
|
if (warningTimer) {
|
|
360
386
|
clearTimeout(warningTimer);
|
|
361
387
|
warningTimer = null;
|
|
362
388
|
}
|
|
363
389
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
pollInactivityState();
|
|
368
|
-
}, Math.min(10000, timeUntilIdle));
|
|
390
|
+
if (logoutTimer) {
|
|
391
|
+
clearTimeout(logoutTimer);
|
|
392
|
+
logoutTimer = null;
|
|
369
393
|
}
|
|
370
394
|
|
|
371
|
-
if (
|
|
372
|
-
|
|
395
|
+
if (countdownInterval) {
|
|
396
|
+
clearInterval(countdownInterval);
|
|
397
|
+
countdownInterval = null;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const timeUntilWarning = getTimeUntilWarning();
|
|
401
|
+
const timeUntilLogout = getTimeUntilLogout();
|
|
402
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
403
|
+
|
|
404
|
+
// If already idle, nothing to schedule
|
|
405
|
+
if (timeSinceActivity >= this.idleTimeoutMs) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// If warning should be shown, start countdown interval
|
|
410
|
+
if (timeSinceActivity >= (this.idleTimeoutMs - this.warnBeforeMs)) {
|
|
411
|
+
// Update state to show warning
|
|
412
|
+
updateState();
|
|
413
|
+
|
|
414
|
+
// Start countdown interval to update remaining time every second
|
|
415
|
+
countdownInterval = setInterval(() => {
|
|
416
|
+
updateState();
|
|
417
|
+
|
|
418
|
+
// Check if we've reached logout time
|
|
419
|
+
if (Date.now() - lastActivity >= this.idleTimeoutMs) {
|
|
420
|
+
if (countdownInterval) {
|
|
421
|
+
clearInterval(countdownInterval);
|
|
422
|
+
countdownInterval = null;
|
|
423
|
+
}
|
|
424
|
+
this.handleIdleLogout();
|
|
425
|
+
}
|
|
426
|
+
}, 1000); // Update every second during warning period
|
|
427
|
+
|
|
428
|
+
// Schedule logout
|
|
429
|
+
logoutTimer = setTimeout(() => {
|
|
430
|
+
if (countdownInterval) {
|
|
431
|
+
clearInterval(countdownInterval);
|
|
432
|
+
countdownInterval = null;
|
|
433
|
+
}
|
|
373
434
|
this.handleIdleLogout();
|
|
374
|
-
},
|
|
435
|
+
}, timeUntilLogout);
|
|
436
|
+
} else {
|
|
437
|
+
// User is still active - schedule warning timer
|
|
438
|
+
// Use adaptive interval: check more frequently as we approach warning time
|
|
439
|
+
// Check every 60 seconds when far from warning, every 10 seconds when close
|
|
440
|
+
const timeUntilWarningMs = timeUntilWarning;
|
|
441
|
+
const adaptiveInterval = timeUntilWarningMs > 5 * 60 * 1000
|
|
442
|
+
? 60 * 1000 // Check every 60 seconds when > 5 minutes away
|
|
443
|
+
: timeUntilWarningMs > 60 * 1000
|
|
444
|
+
? 10 * 1000 // Check every 10 seconds when < 5 minutes but > 1 minute away
|
|
445
|
+
: 1000; // Check every second when < 1 minute away
|
|
446
|
+
|
|
447
|
+
warningTimer = setTimeout(() => {
|
|
448
|
+
updateState();
|
|
449
|
+
scheduleNextCheck(); // Reschedule for next check
|
|
450
|
+
}, Math.min(adaptiveInterval, timeUntilWarningMs));
|
|
375
451
|
}
|
|
376
452
|
};
|
|
377
453
|
|
|
378
454
|
const resetTimers = () => {
|
|
379
|
-
//
|
|
455
|
+
// Update last activity time
|
|
380
456
|
lastActivity = Date.now();
|
|
381
457
|
|
|
382
|
-
// Clear timers
|
|
383
|
-
if (idleTimer) {
|
|
384
|
-
clearTimeout(idleTimer);
|
|
385
|
-
idleTimer = null;
|
|
386
|
-
}
|
|
387
|
-
|
|
458
|
+
// Clear all timers
|
|
388
459
|
if (warningTimer) {
|
|
389
460
|
clearTimeout(warningTimer);
|
|
390
461
|
warningTimer = null;
|
|
391
462
|
}
|
|
392
463
|
|
|
393
|
-
|
|
464
|
+
if (logoutTimer) {
|
|
465
|
+
clearTimeout(logoutTimer);
|
|
466
|
+
logoutTimer = null;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (countdownInterval) {
|
|
470
|
+
clearInterval(countdownInterval);
|
|
471
|
+
countdownInterval = null;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Reset state values
|
|
475
|
+
const hadWarning = this._showWarning || this._showInactivityWarning;
|
|
394
476
|
this._showInactivityWarning = false;
|
|
395
477
|
this._inactivityTimeRemaining = 0;
|
|
396
478
|
this._isIdle = false;
|
|
397
479
|
this._showWarning = false;
|
|
480
|
+
this._timeRemaining = this.idleTimeoutMs;
|
|
398
481
|
|
|
399
|
-
// Update previous state
|
|
482
|
+
// Update previous state
|
|
400
483
|
prevIsIdle = false;
|
|
401
484
|
prevShowWarning = false;
|
|
402
485
|
prevShowInactivityWarning = false;
|
|
403
486
|
prevInactivityTimeRemaining = 0;
|
|
404
487
|
prevTimeRemaining = this.idleTimeoutMs;
|
|
405
488
|
|
|
406
|
-
//
|
|
489
|
+
// Notify if we were showing a warning (state changed)
|
|
490
|
+
if (hadWarning) {
|
|
491
|
+
this.notify();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Reschedule next check
|
|
495
|
+
scheduleNextCheck();
|
|
407
496
|
};
|
|
408
497
|
|
|
409
|
-
// Activity detection -
|
|
498
|
+
// Activity detection - throttled to avoid excessive calls
|
|
410
499
|
const activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];
|
|
500
|
+
let activityThrottleTimer: NodeJS.Timeout | null = null;
|
|
411
501
|
|
|
412
502
|
const handleActivity = () => {
|
|
413
|
-
|
|
414
|
-
|
|
503
|
+
// Throttle activity detection to once per second max
|
|
504
|
+
if (activityThrottleTimer) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
activityThrottleTimer = setTimeout(() => {
|
|
509
|
+
activityThrottleTimer = null;
|
|
510
|
+
resetTimers();
|
|
511
|
+
}, 1000);
|
|
415
512
|
};
|
|
416
513
|
|
|
417
514
|
// Add event listeners
|
|
@@ -419,29 +516,30 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
419
516
|
document.addEventListener(event, handleActivity, true);
|
|
420
517
|
});
|
|
421
518
|
|
|
422
|
-
//
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}, 10000); // 10 seconds
|
|
426
|
-
|
|
427
|
-
// Initial poll
|
|
428
|
-
pollInactivityState();
|
|
519
|
+
// Initial state update and schedule first check
|
|
520
|
+
updateState(true); // Force initial notification
|
|
521
|
+
scheduleNextCheck();
|
|
429
522
|
|
|
430
523
|
// Store cleanup function
|
|
431
524
|
this.cleanupHandlers = () => {
|
|
432
|
-
if (idleTimer) {
|
|
433
|
-
clearTimeout(idleTimer);
|
|
434
|
-
idleTimer = null;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
525
|
if (warningTimer) {
|
|
438
526
|
clearTimeout(warningTimer);
|
|
439
527
|
warningTimer = null;
|
|
440
528
|
}
|
|
441
529
|
|
|
442
|
-
if (
|
|
443
|
-
|
|
444
|
-
|
|
530
|
+
if (logoutTimer) {
|
|
531
|
+
clearTimeout(logoutTimer);
|
|
532
|
+
logoutTimer = null;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (countdownInterval) {
|
|
536
|
+
clearInterval(countdownInterval);
|
|
537
|
+
countdownInterval = null;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (activityThrottleTimer) {
|
|
541
|
+
clearTimeout(activityThrottleTimer);
|
|
542
|
+
activityThrottleTimer = null;
|
|
445
543
|
}
|
|
446
544
|
|
|
447
545
|
activityEvents.forEach(event => {
|
|
@@ -457,6 +555,5 @@ export class InactivityService extends BaseService implements IInactivityService
|
|
|
457
555
|
};
|
|
458
556
|
|
|
459
557
|
this._isTracking = true;
|
|
460
|
-
this.notify(); // Initial notification only
|
|
461
558
|
}
|
|
462
559
|
}
|
|
@@ -70,10 +70,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
70
70
|
this.supabaseClient = supabaseClient;
|
|
71
71
|
this.user = user;
|
|
72
72
|
this.session = session;
|
|
73
|
-
logger.debug('OrganisationService', `Instance created [ID:${this.instanceId}]`, {
|
|
74
|
-
hasUser: !!user,
|
|
75
|
-
userId: user?.id
|
|
76
|
-
});
|
|
77
73
|
}
|
|
78
74
|
|
|
79
75
|
getInstanceId(): number {
|
|
@@ -164,10 +160,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
164
160
|
|
|
165
161
|
if (userChanged || needsRetry || isEmpty) {
|
|
166
162
|
if (userChanged) {
|
|
167
|
-
logger.debug('OrganisationService', `User changed [ID:${this.instanceId}], resetting initialization`, {
|
|
168
|
-
previousUserId,
|
|
169
|
-
newUserId
|
|
170
|
-
});
|
|
171
163
|
} else if (needsRetry) {
|
|
172
164
|
logger.debug('OrganisationService', `Previous error detected [ID:${this.instanceId}], retrying initialization`);
|
|
173
165
|
} else if (isEmpty) {
|
|
@@ -293,7 +285,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
293
285
|
// SECURITY: Only initialize if we have an authenticated user
|
|
294
286
|
// This prevents premature initialization during early auth states
|
|
295
287
|
if (!this.user) {
|
|
296
|
-
logger.debug('OrganisationService', 'Skipping initialization - no user');
|
|
297
288
|
return;
|
|
298
289
|
}
|
|
299
290
|
|
|
@@ -337,34 +328,13 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
337
328
|
}
|
|
338
329
|
|
|
339
330
|
private async setDatabaseOrganisationContext(organisation: Organisation): Promise<void> {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
try {
|
|
348
|
-
// Add timeout to prevent hanging
|
|
349
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
350
|
-
setTimeout(() => reject(new Error('Context setting timeout after 5 seconds')), 5000);
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);
|
|
354
|
-
|
|
355
|
-
await Promise.race([contextPromise, timeoutPromise]);
|
|
356
|
-
|
|
357
|
-
// Database organisation context set successfully
|
|
358
|
-
this._isContextReady = true;
|
|
359
|
-
this.notify();
|
|
360
|
-
} catch (error) {
|
|
361
|
-
logger.error('OrganisationService', 'Failed to set database organisation context:', error);
|
|
362
|
-
// Set context ready to true anyway - this is a non-critical operation
|
|
363
|
-
// The app should still work without database context
|
|
364
|
-
this._isContextReady = true;
|
|
365
|
-
this.notify();
|
|
366
|
-
// Don't throw - this is a non-critical operation
|
|
367
|
-
}
|
|
331
|
+
// Organisation context is now handled via secure client and explicit parameters
|
|
332
|
+
// This function is kept for backward compatibility but is effectively a no-op
|
|
333
|
+
// The setOrganisationContext function has been deprecated and no longer sets database context
|
|
334
|
+
|
|
335
|
+
// Mark context as ready immediately since context is handled elsewhere
|
|
336
|
+
this._isContextReady = true;
|
|
337
|
+
this.notify();
|
|
368
338
|
}
|
|
369
339
|
|
|
370
340
|
private async loadUserOrganisations(): Promise<void> {
|
|
@@ -416,9 +386,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
416
386
|
this._error = null;
|
|
417
387
|
this.notify();
|
|
418
388
|
|
|
419
|
-
logger.debug('OrganisationService', 'Loading organisations for user', {
|
|
420
|
-
userId: this.user.id
|
|
421
|
-
});
|
|
422
389
|
|
|
423
390
|
try {
|
|
424
391
|
// Get user's organisation roles directly from rbac_organisation_roles table
|
|
@@ -500,10 +467,6 @@ export class OrganisationService extends BaseService implements IOrganisationSer
|
|
|
500
467
|
|
|
501
468
|
organisations = Array.from(organisationsMap.values());
|
|
502
469
|
|
|
503
|
-
logger.debug('OrganisationService', 'Query results', {
|
|
504
|
-
membershipsCount: memberships.length,
|
|
505
|
-
organisationsCount: organisations.length
|
|
506
|
-
});
|
|
507
470
|
|
|
508
471
|
// Extract organisations from join results
|
|
509
472
|
} catch (queryError) {
|
|
@@ -866,10 +866,19 @@ describe('OrganisationService', () => {
|
|
|
866
866
|
mockSession
|
|
867
867
|
);
|
|
868
868
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
869
|
+
// Initially context is not ready
|
|
870
|
+
expect(serviceWithoutClient.isContextReady()).toBe(false);
|
|
871
|
+
|
|
872
|
+
// setSelectedOrganisation requires a valid organisation in the organisations list
|
|
873
|
+
// Since we don't have a client, we can't load organisations, so this will throw
|
|
874
|
+
// or the organisation won't be in the list. The context ready state should remain false.
|
|
875
|
+
try {
|
|
876
|
+
await serviceWithoutClient.switchOrganisation(mockOrganisation.id);
|
|
877
|
+
} catch {
|
|
878
|
+
// Expected to fail
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Context should still be false since organisation switch failed
|
|
873
882
|
expect(serviceWithoutClient.isContextReady()).toBe(false);
|
|
874
883
|
});
|
|
875
884
|
|
|
@@ -880,10 +889,19 @@ describe('OrganisationService', () => {
|
|
|
880
889
|
null
|
|
881
890
|
);
|
|
882
891
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
892
|
+
// Initially context is not ready
|
|
893
|
+
expect(serviceWithoutSession.isContextReady()).toBe(false);
|
|
894
|
+
|
|
895
|
+
// Without a session, loadUserOrganisations will return early and not load organisations
|
|
896
|
+
// So setSelectedOrganisation will fail because the organisation isn't in the list
|
|
897
|
+
// The context ready state should remain false
|
|
898
|
+
try {
|
|
899
|
+
await serviceWithoutSession.switchOrganisation(mockOrganisation.id);
|
|
900
|
+
} catch {
|
|
901
|
+
// Expected to fail
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// Context should still be false since organisation switch failed
|
|
887
905
|
expect(serviceWithoutSession.isContextReady()).toBe(false);
|
|
888
906
|
});
|
|
889
907
|
});
|
|
@@ -38,9 +38,6 @@ export abstract class BaseService {
|
|
|
38
38
|
* This triggers React re-renders
|
|
39
39
|
*/
|
|
40
40
|
protected notify(): void {
|
|
41
|
-
const serviceName = this.constructor.name;
|
|
42
|
-
const instanceId = (this as any).instanceId || 'unknown';
|
|
43
|
-
logger.debug('BaseService', `[${serviceName} ID:${instanceId}] Notifying ${this.subscribers.length} subscribers`);
|
|
44
41
|
this.subscribers.forEach(callback => {
|
|
45
42
|
try {
|
|
46
43
|
callback();
|
package/src/styles/core.css
CHANGED
|
@@ -202,6 +202,10 @@
|
|
|
202
202
|
font-size: 0.875em;
|
|
203
203
|
color: var(--color-main-600);
|
|
204
204
|
}
|
|
205
|
+
|
|
206
|
+
dialog::backdrop {
|
|
207
|
+
background-color: oklch(from var(--color-main-700) l c h / 0.5);
|
|
208
|
+
}
|
|
205
209
|
|
|
206
210
|
.appGradient {
|
|
207
211
|
background: linear-gradient(145deg, var(--color-main-100) 10%, var(--color-main-200) 30%, var(--color-main-200) 70%, var(--color-main-300) 90%);
|