@wildo-ai/saas-frontend-lib 1.1.5 → 1.1.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/dist/esm/components/actions/action-bar.d.ts +15 -0
- package/dist/esm/components/actions/action-bar.d.ts.map +1 -1
- package/dist/esm/components/actions/action-bar.js +15 -0
- package/dist/esm/components/actions/action-bar.js.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.d.ts +97 -7
- package/dist/esm/components/ai-elements/decision/approval.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.js.map +1 -1
- package/dist/esm/components/app/AppLayout_AuthenticatedRoute.d.ts.map +1 -1
- package/dist/esm/components/app/AppLayout_AuthenticatedRoute.js +8 -3
- package/dist/esm/components/app/AppLayout_AuthenticatedRoute.js.map +1 -1
- package/dist/esm/components/auth/Auth_EnrollmentRequired.d.ts.map +1 -1
- package/dist/esm/components/auth/Auth_EnrollmentRequired.js +5 -1
- package/dist/esm/components/auth/Auth_EnrollmentRequired.js.map +1 -1
- package/dist/esm/components/auth/Auth_Main.d.ts.map +1 -1
- package/dist/esm/components/auth/Auth_Main.js +1 -4
- package/dist/esm/components/auth/Auth_Main.js.map +1 -1
- package/dist/esm/components/auth/Auth_Register.d.ts.map +1 -1
- package/dist/esm/components/auth/Auth_Register.js +1 -3
- package/dist/esm/components/auth/Auth_Register.js.map +1 -1
- package/dist/esm/components/auth/StepUpAuthDialog.d.ts +7 -0
- package/dist/esm/components/auth/StepUpAuthDialog.d.ts.map +1 -1
- package/dist/esm/components/auth/StepUpAuthDialog.js +13 -7
- package/dist/esm/components/auth/StepUpAuthDialog.js.map +1 -1
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.d.ts.map +1 -1
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.js +32 -33
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.js.map +1 -1
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.labels.d.ts.map +1 -1
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.labels.js +18 -20
- package/dist/esm/components/auth/admin-config/AppPage_SecuritySettings.labels.js.map +1 -1
- package/dist/esm/components/auth/methods/ExternalOAuth2AuthMethod.d.ts.map +1 -1
- package/dist/esm/components/auth/methods/ExternalOAuth2AuthMethod.js +2 -3
- package/dist/esm/components/auth/methods/ExternalOAuth2AuthMethod.js.map +1 -1
- package/dist/esm/components/auth/utils/oauth-provider-display-label.frontend.utils.d.ts +13 -16
- package/dist/esm/components/auth/utils/oauth-provider-display-label.frontend.utils.d.ts.map +1 -1
- package/dist/esm/components/auth/utils/oauth-provider-display-label.frontend.utils.js +18 -15
- package/dist/esm/components/auth/utils/oauth-provider-display-label.frontend.utils.js.map +1 -1
- package/dist/esm/components/billing/billing-invoice-history.js +2 -2
- package/dist/esm/components/billing/billing-invoice-history.js.map +1 -1
- package/dist/esm/components/billing/billing-portal-link.js +2 -2
- package/dist/esm/components/billing/billing-portal-link.js.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts +33 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.js +34 -5
- package/dist/esm/components/billing/billing-pricing-table.js.map +1 -1
- package/dist/esm/components/billing/billing-subscription-status.js +2 -2
- package/dist/esm/components/billing/billing-subscription-status.js.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.d.ts +2 -0
- package/dist/esm/components/billing/billing-usage-dashboard.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.js +1 -0
- package/dist/esm/components/billing/billing-usage-dashboard.js.map +1 -1
- package/dist/esm/components/data-display/DisplayField.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayField.js +15 -1
- package/dist/esm/components/data-display/DisplayField.js.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldArray.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldArray.js +11 -0
- package/dist/esm/components/data-display/DisplayFieldArray.js.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldEditable.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldEditable.js +2 -2
- package/dist/esm/components/data-display/DisplayFieldEditable.js.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldEditableArray.d.ts +12 -2
- package/dist/esm/components/data-display/DisplayFieldEditableArray.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldEditableArray.js +3 -2
- package/dist/esm/components/data-display/DisplayFieldEditableArray.js.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldReadOnly.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldReadOnly.js +2 -2
- package/dist/esm/components/data-display/DisplayFieldReadOnly.js.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldReadOnlyArraySection.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayFieldReadOnlyArraySection.js +8 -2
- package/dist/esm/components/data-display/DisplayFieldReadOnlyArraySection.js.map +1 -1
- package/dist/esm/components/data-display/DisplayValueDispatcher.d.ts.map +1 -1
- package/dist/esm/components/data-display/DisplayValueDispatcher.js +18 -4
- package/dist/esm/components/data-display/DisplayValueDispatcher.js.map +1 -1
- package/dist/esm/components/data-display/ResourceAutomaticDisplayer.d.ts.map +1 -1
- package/dist/esm/components/data-display/ResourceAutomaticDisplayer.js +61 -3
- package/dist/esm/components/data-display/ResourceAutomaticDisplayer.js.map +1 -1
- package/dist/esm/components/data-display/ResourceSummaryDisplayer.d.ts +7 -5
- package/dist/esm/components/data-display/ResourceSummaryDisplayer.d.ts.map +1 -1
- package/dist/esm/components/data-display/ResourceSummaryDisplayer.js.map +1 -1
- package/dist/esm/components/data-display/chromes/DisplayFieldChrome.d.ts +11 -1
- package/dist/esm/components/data-display/chromes/DisplayFieldChrome.d.ts.map +1 -1
- package/dist/esm/components/data-display/chromes/DisplayFieldChrome.js +36 -11
- package/dist/esm/components/data-display/chromes/DisplayFieldChrome.js.map +1 -1
- package/dist/esm/components/data-display/display-field-resolved-props.d.ts +6 -0
- package/dist/esm/components/data-display/display-field-resolved-props.d.ts.map +1 -1
- package/dist/esm/components/data-display/display-field-resolved-props.js.map +1 -1
- package/dist/esm/components/data-display/external-data-provenance/DisplayFieldProvenanceNote.d.ts +23 -0
- package/dist/esm/components/data-display/external-data-provenance/DisplayFieldProvenanceNote.d.ts.map +1 -0
- package/dist/esm/components/data-display/external-data-provenance/DisplayFieldProvenanceNote.js +35 -0
- package/dist/esm/components/data-display/external-data-provenance/DisplayFieldProvenanceNote.js.map +1 -0
- package/dist/esm/components/data-display/external-data-provenance/external-data-provenance.frontend.d.ts +47 -0
- package/dist/esm/components/data-display/external-data-provenance/external-data-provenance.frontend.d.ts.map +1 -0
- package/dist/esm/components/data-display/external-data-provenance/external-data-provenance.frontend.js +124 -0
- package/dist/esm/components/data-display/external-data-provenance/external-data-provenance.frontend.js.map +1 -0
- package/dist/esm/components/data-display/external-data-provenance/useExternalDataFieldProvenance.d.ts +8 -0
- package/dist/esm/components/data-display/external-data-provenance/useExternalDataFieldProvenance.d.ts.map +1 -0
- package/dist/esm/components/data-display/external-data-provenance/useExternalDataFieldProvenance.js +46 -0
- package/dist/esm/components/data-display/external-data-provenance/useExternalDataFieldProvenance.js.map +1 -0
- package/dist/esm/components/feedback/resource-empty-state.d.ts +21 -8
- package/dist/esm/components/feedback/resource-empty-state.d.ts.map +1 -1
- package/dist/esm/components/feedback/resource-empty-state.js +56 -26
- package/dist/esm/components/feedback/resource-empty-state.js.map +1 -1
- package/dist/esm/components/flows-actors/approval.d.ts +29 -7
- package/dist/esm/components/flows-actors/approval.d.ts.map +1 -1
- package/dist/esm/components/flows-actors/approval.js +231 -101
- package/dist/esm/components/flows-actors/approval.js.map +1 -1
- package/dist/esm/components/flows-actors/approval.labels.d.ts.map +1 -1
- package/dist/esm/components/flows-actors/approval.labels.js +57 -0
- package/dist/esm/components/flows-actors/approval.labels.js.map +1 -1
- package/dist/esm/components/flows-actors/system-catalog.d.ts.map +1 -1
- package/dist/esm/components/flows-actors/system-catalog.js +4 -4
- package/dist/esm/components/flows-actors/system-catalog.js.map +1 -1
- package/dist/esm/components/flows-actors/system-catalog.labels.d.ts.map +1 -1
- package/dist/esm/components/flows-actors/system-catalog.labels.js +0 -5
- package/dist/esm/components/flows-actors/system-catalog.labels.js.map +1 -1
- package/dist/esm/components/form/Form.d.ts +2 -2
- package/dist/esm/components/form/Form.js +2 -2
- package/dist/esm/components/form/Form.js.map +1 -1
- package/dist/esm/components/form/automated/AutomatedArrayField.d.ts +28 -3
- package/dist/esm/components/form/automated/AutomatedArrayField.d.ts.map +1 -1
- package/dist/esm/components/form/automated/AutomatedArrayField.js +43 -14
- package/dist/esm/components/form/automated/AutomatedArrayField.js.map +1 -1
- package/dist/esm/components/form/automated/FormField.d.ts +3 -0
- package/dist/esm/components/form/automated/FormField.d.ts.map +1 -1
- package/dist/esm/components/form/automated/FormField.js +60 -21
- package/dist/esm/components/form/automated/FormField.js.map +1 -1
- package/dist/esm/components/form/automated/FormFieldArray.d.ts +6 -3
- package/dist/esm/components/form/automated/FormFieldArray.d.ts.map +1 -1
- package/dist/esm/components/form/automated/FormFieldArray.js +3 -2
- package/dist/esm/components/form/automated/FormFieldArray.js.map +1 -1
- package/dist/esm/components/form/automated/ResourceAutomatedForm.d.ts +5 -4
- package/dist/esm/components/form/automated/ResourceAutomatedForm.d.ts.map +1 -1
- package/dist/esm/components/form/automated/ResourceAutomatedForm.js +148 -55
- package/dist/esm/components/form/automated/ResourceAutomatedForm.js.map +1 -1
- package/dist/esm/components/form/automated/ResourceFormActionsContext.d.ts +30 -0
- package/dist/esm/components/form/automated/ResourceFormActionsContext.d.ts.map +1 -1
- package/dist/esm/components/form/automated/ResourceFormActionsContext.js +30 -1
- package/dist/esm/components/form/automated/ResourceFormActionsContext.js.map +1 -1
- package/dist/esm/components/form/automated/TemplatePlacedFieldsContext.d.ts +79 -0
- package/dist/esm/components/form/automated/TemplatePlacedFieldsContext.d.ts.map +1 -0
- package/dist/esm/components/form/automated/TemplatePlacedFieldsContext.js +203 -0
- package/dist/esm/components/form/automated/TemplatePlacedFieldsContext.js.map +1 -0
- package/dist/esm/components/form/automated/automated-form-submit.utils.d.ts +12 -0
- package/dist/esm/components/form/automated/automated-form-submit.utils.d.ts.map +1 -1
- package/dist/esm/components/form/automated/automated-form-submit.utils.js +11 -0
- package/dist/esm/components/form/automated/automated-form-submit.utils.js.map +1 -1
- package/dist/esm/components/form/chromes/FormFieldChrome.d.ts.map +1 -1
- package/dist/esm/components/form/chromes/FormFieldChrome.js +2 -2
- package/dist/esm/components/form/chromes/FormFieldChrome.js.map +1 -1
- package/dist/esm/components/form/combobox.d.ts +7 -0
- package/dist/esm/components/form/combobox.d.ts.map +1 -1
- package/dist/esm/components/form/combobox.js.map +1 -1
- package/dist/esm/components/form/controls/form-field-checkbox-group.d.ts.map +1 -1
- package/dist/esm/components/form/controls/form-field-checkbox-group.js +13 -0
- package/dist/esm/components/form/controls/form-field-checkbox-group.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-address.d.ts +58 -0
- package/dist/esm/components/form/fields/form-field-address.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-address.js +34 -6
- package/dist/esm/components/form/fields/form-field-address.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-address.labels.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-address.labels.js +60 -1
- package/dist/esm/components/form/fields/form-field-address.labels.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-file.d.ts +0 -12
- package/dist/esm/components/form/fields/form-field-file.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-file.js +34 -13
- package/dist/esm/components/form/fields/form-field-file.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-file.labels.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-file.labels.js +46 -0
- package/dist/esm/components/form/fields/form-field-file.labels.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-string-organization-role.d.ts +73 -0
- package/dist/esm/components/form/fields/form-field-string-organization-role.d.ts.map +1 -0
- package/dist/esm/components/form/fields/form-field-string-organization-role.js +64 -0
- package/dist/esm/components/form/fields/form-field-string-organization-role.js.map +1 -0
- package/dist/esm/components/form/fields/form-field-string.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-string.js +8 -1
- package/dist/esm/components/form/fields/form-field-string.js.map +1 -1
- package/dist/esm/components/form/fields/form-field-string.labels.d.ts.map +1 -1
- package/dist/esm/components/form/fields/form-field-string.labels.js +4 -0
- package/dist/esm/components/form/fields/form-field-string.labels.js.map +1 -1
- package/dist/esm/components/form/validation-errors/FormErrorSummary.js +1 -1
- package/dist/esm/components/form/validation-errors/FormErrorSummary.js.map +1 -1
- package/dist/esm/components/form/validation-errors/resolver-error-nesting.d.ts +31 -0
- package/dist/esm/components/form/validation-errors/resolver-error-nesting.d.ts.map +1 -0
- package/dist/esm/components/form/validation-errors/resolver-error-nesting.js +81 -0
- package/dist/esm/components/form/validation-errors/resolver-error-nesting.js.map +1 -0
- package/dist/esm/components/form/validation-errors/resource-error-notification-context.utils.d.ts +14 -1
- package/dist/esm/components/form/validation-errors/resource-error-notification-context.utils.d.ts.map +1 -1
- package/dist/esm/components/form/validation-errors/resource-error-notification-context.utils.js +14 -0
- package/dist/esm/components/form/validation-errors/resource-error-notification-context.utils.js.map +1 -1
- package/dist/esm/components/form/validation-errors/zod-issue-resolver.d.ts +22 -0
- package/dist/esm/components/form/validation-errors/zod-issue-resolver.d.ts.map +1 -1
- package/dist/esm/components/form/validation-errors/zod-issue-resolver.js +1 -22
- package/dist/esm/components/form/validation-errors/zod-issue-resolver.js.map +1 -1
- package/dist/esm/components/layout/resizable.d.ts +11 -0
- package/dist/esm/components/layout/resizable.d.ts.map +1 -1
- package/dist/esm/components/layout/resizable.js.map +1 -1
- package/dist/esm/components/navigation/app-level/ApplicationLevel_NavigationBack.d.ts +11 -1
- package/dist/esm/components/navigation/app-level/ApplicationLevel_NavigationBack.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/ApplicationLevel_NavigationBack.js +15 -3
- package/dist/esm/components/navigation/app-level/ApplicationLevel_NavigationBack.js.map +1 -1
- package/dist/esm/components/navigation/app-level/ApplicationLevel_StatusBar.d.ts +2 -2
- package/dist/esm/components/navigation/app-level/ApplicationLevel_StatusBar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/ApplicationLevel_StatusBar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/HostedComponentInteractionsProvider.d.ts +2 -2
- package/dist/esm/components/navigation/app-level/HostedComponentInteractionsProvider.js +2 -2
- package/dist/esm/components/navigation/app-level/HostedComponentInteractionsProvider.js.map +1 -1
- package/dist/esm/components/navigation/app-level/SidebarResourceBrowser.js +18 -20
- package/dist/esm/components/navigation/app-level/SidebarResourceBrowser.js.map +1 -1
- package/dist/esm/components/navigation/app-level/useCommandMenuBehavior.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/useCommandMenuBehavior.js +7 -1
- package/dist/esm/components/navigation/app-level/useCommandMenuBehavior.js.map +1 -1
- package/dist/esm/components/navigation/app-level/useMenuBarBehavior.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/useMenuBarBehavior.js +4 -1
- package/dist/esm/components/navigation/app-level/useMenuBarBehavior.js.map +1 -1
- package/dist/esm/components/navigation/app-level/useMenuUserOrgBehavior.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/useMenuUserOrgBehavior.js +18 -2
- package/dist/esm/components/navigation/app-level/useMenuUserOrgBehavior.js.map +1 -1
- package/dist/esm/components/navigation/app-level/useSidebarBehavior.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/useSidebarBehavior.js +82 -10
- package/dist/esm/components/navigation/app-level/useSidebarBehavior.js.map +1 -1
- package/dist/esm/components/navigation/app-level/useStatusBarBehavior.d.ts +2 -2
- package/dist/esm/components/navigation/app-level/useStatusBarBehavior.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/useStatusBarBehavior.js.map +1 -1
- package/dist/esm/components/resources/ResourceCollectionQuickFilterTabs.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceCollectionQuickFilterTabs.js +8 -1
- package/dist/esm/components/resources/ResourceCollectionQuickFilterTabs.js.map +1 -1
- package/dist/esm/components/resources/ResourceCollectionToolbar.d.ts +8 -2
- package/dist/esm/components/resources/ResourceCollectionToolbar.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceCollectionToolbar.js +6 -2
- package/dist/esm/components/resources/ResourceCollectionToolbar.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Breadcrumb.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Breadcrumb.js +31 -16
- package/dist/esm/components/resources/ResourceLayout_Breadcrumb.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ContainerDialogs.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ContainerDialogs.js +23 -8
- package/dist/esm/components/resources/ResourceLayout_ContainerDialogs.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ContainerNested.js +2 -2
- package/dist/esm/components/resources/ResourceLayout_ContainerNested.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Header.d.ts +13 -0
- package/dist/esm/components/resources/ResourceLayout_Header.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Header.js +55 -28
- package/dist/esm/components/resources/ResourceLayout_Header.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_List.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_List.js +41 -20
- package/dist/esm/components/resources/ResourceLayout_List.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_List.labels.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_List.labels.js +1 -2
- package/dist/esm/components/resources/ResourceLayout_List.labels.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Read.d.ts +9 -4
- package/dist/esm/components/resources/ResourceLayout_Read.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Read.js +30 -11
- package/dist/esm/components/resources/ResourceLayout_Read.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ReadSummary.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ReadSummary.js +4 -2
- package/dist/esm/components/resources/ResourceLayout_ReadSummary.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ReadSummary_TableRow.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_ReadSummary_TableRow.js +6 -2
- package/dist/esm/components/resources/ResourceLayout_ReadSummary_TableRow.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Search.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Search.js +30 -14
- package/dist/esm/components/resources/ResourceLayout_Search.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_SemanticOperationFallback.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_SemanticOperationFallback.js +14 -198
- package/dist/esm/components/resources/ResourceLayout_SemanticOperationFallback.js.map +1 -1
- package/dist/esm/components/resources/ResourceLayout_Update.d.ts +2 -2
- package/dist/esm/components/resources/ResourceLayout_Update.js +2 -2
- package/dist/esm/components/resources/ResourceLayout_Update.js.map +1 -1
- package/dist/esm/components/resources/ResourceListItemRenderer.d.ts.map +1 -1
- package/dist/esm/components/resources/ResourceListItemRenderer.js +69 -39
- package/dist/esm/components/resources/ResourceListItemRenderer.js.map +1 -1
- package/dist/esm/components/resources/ResourceOperationActionDropdown.d.ts +32 -0
- package/dist/esm/components/resources/ResourceOperationActionDropdown.d.ts.map +1 -0
- package/dist/esm/components/resources/ResourceOperationActionDropdown.js +130 -0
- package/dist/esm/components/resources/ResourceOperationActionDropdown.js.map +1 -0
- package/dist/esm/components/resources/collection-create-placement.utils.d.ts +32 -0
- package/dist/esm/components/resources/collection-create-placement.utils.d.ts.map +1 -0
- package/dist/esm/components/resources/collection-create-placement.utils.js +37 -0
- package/dist/esm/components/resources/collection-create-placement.utils.js.map +1 -0
- package/dist/esm/components/resources/embeds/RelatedResourcePreview.d.ts.map +1 -1
- package/dist/esm/components/resources/embeds/RelatedResourcePreview.js +5 -1
- package/dist/esm/components/resources/embeds/RelatedResourcePreview.js.map +1 -1
- package/dist/esm/components/resources/embeds/RelatedResourceSections.d.ts +8 -1
- package/dist/esm/components/resources/embeds/RelatedResourceSections.d.ts.map +1 -1
- package/dist/esm/components/resources/embeds/RelatedResourceSections.js +49 -2
- package/dist/esm/components/resources/embeds/RelatedResourceSections.js.map +1 -1
- package/dist/esm/components/resources/embeds/ResourceEmbeds.d.ts +22 -0
- package/dist/esm/components/resources/embeds/ResourceEmbeds.d.ts.map +1 -1
- package/dist/esm/components/resources/embeds/ResourceEmbeds.js +85 -2
- package/dist/esm/components/resources/embeds/ResourceEmbeds.js.map +1 -1
- package/dist/esm/components/resources/resourceLayout.utils.d.ts +14 -0
- package/dist/esm/components/resources/resourceLayout.utils.d.ts.map +1 -1
- package/dist/esm/components/resources/resourceLayout.utils.js +22 -0
- package/dist/esm/components/resources/resourceLayout.utils.js.map +1 -1
- package/dist/esm/components/resources/skeleton/ArrayField.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/ArrayField.js +3 -0
- package/dist/esm/components/resources/skeleton/ArrayField.js.map +1 -1
- package/dist/esm/components/resources/skeleton/FormLayout.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/FormLayout.js +33 -1
- package/dist/esm/components/resources/skeleton/FormLayout.js.map +1 -1
- package/dist/esm/components/resources/skeleton/ObjectScope.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/ObjectScope.js +3 -0
- package/dist/esm/components/resources/skeleton/ObjectScope.js.map +1 -1
- package/dist/esm/components/resources/skeleton/Section.d.ts +12 -0
- package/dist/esm/components/resources/skeleton/Section.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/Section.js +28 -2
- package/dist/esm/components/resources/skeleton/Section.js.map +1 -1
- package/dist/esm/components/resources/skeleton/SectionFieldsContext.d.ts +70 -0
- package/dist/esm/components/resources/skeleton/SectionFieldsContext.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/SectionFieldsContext.js +157 -1
- package/dist/esm/components/resources/skeleton/SectionFieldsContext.js.map +1 -1
- package/dist/esm/components/resources/skeleton/WizardLayout.d.ts +6 -0
- package/dist/esm/components/resources/skeleton/WizardLayout.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/WizardLayout.js +13 -2
- package/dist/esm/components/resources/skeleton/WizardLayout.js.map +1 -1
- package/dist/esm/components/resources/skeleton/WizardStep.d.ts.map +1 -1
- package/dist/esm/components/resources/skeleton/WizardStep.js +2 -1
- package/dist/esm/components/resources/skeleton/WizardStep.js.map +1 -1
- package/dist/esm/components/resources-fields/_presets/resource-reference/ResourceFieldDisplayPreset_ResourceReference_Default.d.ts.map +1 -1
- package/dist/esm/components/resources-fields/_presets/resource-reference/ResourceFieldDisplayPreset_ResourceReference_Default.js +61 -15
- package/dist/esm/components/resources-fields/_presets/resource-reference/ResourceFieldDisplayPreset_ResourceReference_Default.js.map +1 -1
- package/dist/esm/components/resources-fields/resource-reference/resource-reference.shared.utils.d.ts +24 -2
- package/dist/esm/components/resources-fields/resource-reference/resource-reference.shared.utils.d.ts.map +1 -1
- package/dist/esm/components/resources-fields/resource-reference/resource-reference.shared.utils.js +69 -1
- package/dist/esm/components/resources-fields/resource-reference/resource-reference.shared.utils.js.map +1 -1
- package/dist/esm/components/resources-fields/resource-reference/useResourceSearch.d.ts.map +1 -1
- package/dist/esm/components/resources-fields/resource-reference/useResourceSearch.js +18 -19
- package/dist/esm/components/resources-fields/resource-reference/useResourceSearch.js.map +1 -1
- package/dist/esm/components/sections/ContentSectionContainer.d.ts.map +1 -1
- package/dist/esm/components/sections/ContentSectionContainer.js +5 -4
- package/dist/esm/components/sections/ContentSectionContainer.js.map +1 -1
- package/dist/esm/components/sections/stepper.d.ts +5 -0
- package/dist/esm/components/sections/stepper.d.ts.map +1 -1
- package/dist/esm/components/sections/stepper.js.map +1 -1
- package/dist/esm/components/sections/surface.d.ts.map +1 -1
- package/dist/esm/components/sections/surface.js +12 -3
- package/dist/esm/components/sections/surface.js.map +1 -1
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.d.ts +43 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.d.ts.map +1 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.js +129 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.js.map +1 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.labels.d.ts +3 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.labels.d.ts.map +1 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.labels.js +34 -0
- package/dist/esm/components/settings/AppPage_AgentWorkOverrideRateSettings.labels.js.map +1 -0
- package/dist/esm/components/settings/AppPage_AppearanceSettings.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_AppearanceSettings.js +9 -11
- package/dist/esm/components/settings/AppPage_AppearanceSettings.js.map +1 -1
- package/dist/esm/components/settings/AppPage_AppearanceSettings.labels.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_AppearanceSettings.labels.js +3 -2
- package/dist/esm/components/settings/AppPage_AppearanceSettings.labels.js.map +1 -1
- package/dist/esm/components/settings/AppPage_BillingSettings.d.ts +4 -2
- package/dist/esm/components/settings/AppPage_BillingSettings.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_BillingSettings.js +21 -3
- package/dist/esm/components/settings/AppPage_BillingSettings.js.map +1 -1
- package/dist/esm/components/settings/AppPage_BillingSettings.labels.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_BillingSettings.labels.js +5 -10
- package/dist/esm/components/settings/AppPage_BillingSettings.labels.js.map +1 -1
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.d.ts +58 -0
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.js +243 -40
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.js.map +1 -1
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.labels.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.labels.js +67 -6
- package/dist/esm/components/settings/AppPage_ConnectedAccountsSettings.labels.js.map +1 -1
- package/dist/esm/components/settings/AppPage_InvitationsSettings.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_InvitationsSettings.js +19 -11
- package/dist/esm/components/settings/AppPage_InvitationsSettings.js.map +1 -1
- package/dist/esm/components/settings/AppPage_InvitationsSettings.labels.d.ts.map +1 -1
- package/dist/esm/components/settings/AppPage_InvitationsSettings.labels.js +4 -2
- package/dist/esm/components/settings/AppPage_InvitationsSettings.labels.js.map +1 -1
- package/dist/esm/components/settings/SettingsHub.d.ts.map +1 -1
- package/dist/esm/components/settings/SettingsHub.js +3 -0
- package/dist/esm/components/settings/SettingsHub.js.map +1 -1
- package/dist/esm/components/settings/SettingsResourceOperationPanel.d.ts.map +1 -1
- package/dist/esm/components/settings/SettingsResourceOperationPanel.js +16 -1
- package/dist/esm/components/settings/SettingsResourceOperationPanel.js.map +1 -1
- package/dist/esm/components/settings/useOwnerProviderConnections.d.ts +59 -0
- package/dist/esm/components/settings/useOwnerProviderConnections.d.ts.map +1 -0
- package/dist/esm/components/settings/useOwnerProviderConnections.js +136 -0
- package/dist/esm/components/settings/useOwnerProviderConnections.js.map +1 -0
- package/dist/esm/components/views/chart-view/chart-view.utils.d.ts +5 -0
- package/dist/esm/components/views/chart-view/chart-view.utils.d.ts.map +1 -1
- package/dist/esm/components/views/chart-view/chart-view.utils.js +5 -0
- package/dist/esm/components/views/chart-view/chart-view.utils.js.map +1 -1
- package/dist/esm/components/views/chart-view/useResourceChartData.d.ts +50 -0
- package/dist/esm/components/views/chart-view/useResourceChartData.d.ts.map +1 -0
- package/dist/esm/components/views/chart-view/useResourceChartData.js +72 -0
- package/dist/esm/components/views/chart-view/useResourceChartData.js.map +1 -0
- package/dist/esm/components/views/composite-view/CompositeLayout.d.ts.map +1 -1
- package/dist/esm/components/views/composite-view/CompositeLayout.js +2 -1
- package/dist/esm/components/views/composite-view/CompositeLayout.js.map +1 -1
- package/dist/esm/core/app-shell/AppShellBuildingBlocks.d.ts +86 -0
- package/dist/esm/core/app-shell/AppShellBuildingBlocks.d.ts.map +1 -0
- package/dist/esm/core/app-shell/AppShellBuildingBlocks.js +187 -0
- package/dist/esm/core/app-shell/AppShellBuildingBlocks.js.map +1 -0
- package/dist/esm/core/app-shell/PortalContainerContext.d.ts +5 -2
- package/dist/esm/core/app-shell/PortalContainerContext.d.ts.map +1 -1
- package/dist/esm/core/app-shell/PortalContainerContext.js +5 -2
- package/dist/esm/core/app-shell/PortalContainerContext.js.map +1 -1
- package/dist/esm/core/app-shell/app-shell.schemas.d.ts +18 -9
- package/dist/esm/core/app-shell/app-shell.schemas.d.ts.map +1 -1
- package/dist/esm/core/app-shell/app-shell.schemas.js +1 -0
- package/dist/esm/core/app-shell/app-shell.schemas.js.map +1 -1
- package/dist/esm/core/app-shell/useAppShellLayout.d.ts +10 -0
- package/dist/esm/core/app-shell/useAppShellLayout.d.ts.map +1 -1
- package/dist/esm/core/app-shell/useAppShellLayout.js +28 -5
- package/dist/esm/core/app-shell/useAppShellLayout.js.map +1 -1
- package/dist/esm/core/app-shell/usePublicShellLayout.d.ts.map +1 -1
- package/dist/esm/core/app-shell/usePublicShellLayout.js +38 -0
- package/dist/esm/core/app-shell/usePublicShellLayout.js.map +1 -1
- package/dist/esm/core/automated-layout/automated-layout.frontend.utils.d.ts +15 -1
- package/dist/esm/core/automated-layout/automated-layout.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/automated-layout/automated-layout.frontend.utils.js +47 -13
- package/dist/esm/core/automated-layout/automated-layout.frontend.utils.js.map +1 -1
- package/dist/esm/core/billing/BillingContext.d.ts +25 -2
- package/dist/esm/core/billing/BillingContext.d.ts.map +1 -1
- package/dist/esm/core/billing/BillingContext.js +16 -25
- package/dist/esm/core/billing/BillingContext.js.map +1 -1
- package/dist/esm/core/billing/billing-provider-display.frontend.utils.d.ts +11 -3
- package/dist/esm/core/billing/billing-provider-display.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/billing/billing-provider-display.frontend.utils.js +14 -8
- package/dist/esm/core/billing/billing-provider-display.frontend.utils.js.map +1 -1
- package/dist/esm/core/billing/useBillingPlanChange.d.ts.map +1 -1
- package/dist/esm/core/billing/useBillingPlanChange.js +2 -0
- package/dist/esm/core/billing/useBillingPlanChange.js.map +1 -1
- package/dist/esm/core/components-registry/assert-registry-completeness.frontend.helper.d.ts.map +1 -1
- package/dist/esm/core/components-registry/assert-registry-completeness.frontend.helper.js +1 -0
- package/dist/esm/core/components-registry/assert-registry-completeness.frontend.helper.js.map +1 -1
- package/dist/esm/core/components-registry/provider-component-registry.frontend.service.d.ts +29 -229
- package/dist/esm/core/components-registry/provider-component-registry.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/components-registry/provider-component-registry.frontend.service.js +29 -327
- package/dist/esm/core/components-registry/provider-component-registry.frontend.service.js.map +1 -1
- package/dist/esm/core/components-registry/useProviderComponent.frontend.hooks.d.ts +17 -27
- package/dist/esm/core/components-registry/useProviderComponent.frontend.hooks.d.ts.map +1 -1
- package/dist/esm/core/components-registry/useProviderComponent.frontend.hooks.js +28 -48
- package/dist/esm/core/components-registry/useProviderComponent.frontend.hooks.js.map +1 -1
- package/dist/esm/core/config/app-configuration-frontend.schemas.d.ts +21 -11
- package/dist/esm/core/config/app-configuration-frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/config/app-configuration-frontend.schemas.js +4 -4
- package/dist/esm/core/config/app-configuration-frontend.schemas.js.map +1 -1
- package/dist/esm/core/config/app-level-components.frontend.schemas.d.ts +17 -0
- package/dist/esm/core/config/app-level-components.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/config/app-level-components.frontend.schemas.js +17 -0
- package/dist/esm/core/config/app-level-components.frontend.schemas.js.map +1 -1
- package/dist/esm/core/config/chart-view.frontend.schemas.d.ts +10 -10
- package/dist/esm/core/config/engine-settings-destinations.d.ts.map +1 -1
- package/dist/esm/core/config/engine-settings-destinations.js +221 -6
- package/dist/esm/core/config/engine-settings-destinations.js.map +1 -1
- package/dist/esm/core/config/launcher-items.frontend.schemas.d.ts +8 -0
- package/dist/esm/core/config/launcher-items.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/config/launcher-items.frontend.schemas.js +1 -0
- package/dist/esm/core/config/launcher-items.frontend.schemas.js.map +1 -1
- package/dist/esm/core/config/settings-hub.frontend.schemas.d.ts +10 -1
- package/dist/esm/core/config/settings-hub.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/config/settings-hub.frontend.schemas.js +9 -0
- package/dist/esm/core/config/settings-hub.frontend.schemas.js.map +1 -1
- package/dist/esm/core/config/verify-launcher-content.d.ts.map +1 -1
- package/dist/esm/core/config/verify-launcher-content.js +30 -19
- package/dist/esm/core/config/verify-launcher-content.js.map +1 -1
- package/dist/esm/core/errors/ErrorContext.d.ts.map +1 -1
- package/dist/esm/core/errors/ErrorContext.js +9 -1
- package/dist/esm/core/errors/ErrorContext.js.map +1 -1
- package/dist/esm/core/errors/GlobalErrorHandler.d.ts.map +1 -1
- package/dist/esm/core/errors/GlobalErrorHandler.js +5 -4
- package/dist/esm/core/errors/GlobalErrorHandler.js.map +1 -1
- package/dist/esm/core/errors/RouterErrorBoundary.js +1 -1
- package/dist/esm/core/errors/RouterErrorBoundary.js.map +1 -1
- package/dist/esm/core/errors/errors-builder.frontend.services.d.ts +2 -2
- package/dist/esm/core/errors/errors-builder.frontend.services.d.ts.map +1 -1
- package/dist/esm/core/errors/errors-builder.frontend.services.js +4 -4
- package/dist/esm/core/errors/errors-builder.frontend.services.js.map +1 -1
- package/dist/esm/core/errors/user-facing-error-message.frontend.utils.js +1 -1
- package/dist/esm/core/errors/user-facing-error-message.frontend.utils.js.map +1 -1
- package/dist/esm/core/events/NotificationContext.d.ts.map +1 -1
- package/dist/esm/core/events/NotificationContext.js +23 -5
- package/dist/esm/core/events/NotificationContext.js.map +1 -1
- package/dist/esm/core/events/events.frontend.schemas.d.ts +110 -43
- package/dist/esm/core/events/events.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/events/events.frontend.schemas.js +89 -15
- package/dist/esm/core/events/events.frontend.schemas.js.map +1 -1
- package/dist/esm/core/execution/useExecutionParticipationRMM.d.ts +2 -0
- package/dist/esm/core/execution/useExecutionParticipationRMM.d.ts.map +1 -1
- package/dist/esm/core/execution/useExecutionParticipationRMM.js +2 -1
- package/dist/esm/core/execution/useExecutionParticipationRMM.js.map +1 -1
- package/dist/esm/core/execution/useExecutionResourceOperationSurface.d.ts +1 -1
- package/dist/esm/core/execution/useExecutionResourceOperationSurface.d.ts.map +1 -1
- package/dist/esm/core/execution/useExecutionResourceOperationSurface.js +5 -2
- package/dist/esm/core/execution/useExecutionResourceOperationSurface.js.map +1 -1
- package/dist/esm/core/external-providers/ConsentBasedProviderSdks.d.ts +63 -0
- package/dist/esm/core/external-providers/ConsentBasedProviderSdks.d.ts.map +1 -0
- package/dist/esm/core/external-providers/ConsentBasedProviderSdks.js +131 -0
- package/dist/esm/core/external-providers/ConsentBasedProviderSdks.js.map +1 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupCombobox.d.ts +61 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupCombobox.d.ts.map +1 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupCombobox.js +178 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupCombobox.js.map +1 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupHost.d.ts +52 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupHost.d.ts.map +1 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupHost.js +144 -0
- package/dist/esm/core/external-providers/ProviderAddressLookupHost.js.map +1 -0
- package/dist/esm/core/external-providers/ProviderFilePickerHost.d.ts +22 -1
- package/dist/esm/core/external-providers/ProviderFilePickerHost.d.ts.map +1 -1
- package/dist/esm/core/external-providers/ProviderFilePickerHost.js +23 -3
- package/dist/esm/core/external-providers/ProviderFilePickerHost.js.map +1 -1
- package/dist/esm/core/external-providers/provider-address-lookup-selection.frontend.utils.d.ts +55 -0
- package/dist/esm/core/external-providers/provider-address-lookup-selection.frontend.utils.d.ts.map +1 -0
- package/dist/esm/core/external-providers/provider-address-lookup-selection.frontend.utils.js +65 -0
- package/dist/esm/core/external-providers/provider-address-lookup-selection.frontend.utils.js.map +1 -0
- package/dist/esm/core/external-providers/provider-scope-reauthorization-offers.frontend.d.ts +63 -0
- package/dist/esm/core/external-providers/provider-scope-reauthorization-offers.frontend.d.ts.map +1 -0
- package/dist/esm/core/external-providers/provider-scope-reauthorization-offers.frontend.js +100 -0
- package/dist/esm/core/external-providers/provider-scope-reauthorization-offers.frontend.js.map +1 -0
- package/dist/esm/core/flows-actors/FlowsActorsContext.d.ts +45 -7
- package/dist/esm/core/flows-actors/FlowsActorsContext.d.ts.map +1 -1
- package/dist/esm/core/flows-actors/FlowsActorsContext.js +112 -28
- package/dist/esm/core/flows-actors/FlowsActorsContext.js.map +1 -1
- package/dist/esm/core/flows-actors/usePendingDecisions.d.ts +32 -0
- package/dist/esm/core/flows-actors/usePendingDecisions.d.ts.map +1 -0
- package/dist/esm/core/flows-actors/usePendingDecisions.js +91 -0
- package/dist/esm/core/flows-actors/usePendingDecisions.js.map +1 -0
- package/dist/esm/core/guidance/GuidanceRenderer.d.ts.map +1 -1
- package/dist/esm/core/guidance/GuidanceRenderer.js +3 -2
- package/dist/esm/core/guidance/GuidanceRenderer.js.map +1 -1
- package/dist/esm/core/i18n/I18nContext.d.ts +22 -8
- package/dist/esm/core/i18n/I18nContext.d.ts.map +1 -1
- package/dist/esm/core/i18n/I18nContext.js +21 -9
- package/dist/esm/core/i18n/I18nContext.js.map +1 -1
- package/dist/esm/core/i18n/component-label-resolution.utils.d.ts +5 -3
- package/dist/esm/core/i18n/component-label-resolution.utils.d.ts.map +1 -1
- package/dist/esm/core/i18n/component-label-resolution.utils.js +5 -3
- package/dist/esm/core/i18n/component-label-resolution.utils.js.map +1 -1
- package/dist/esm/core/i18n/useI18n.d.ts +2 -1
- package/dist/esm/core/i18n/useI18n.d.ts.map +1 -1
- package/dist/esm/core/i18n/useI18n.js +2 -1
- package/dist/esm/core/i18n/useI18n.js.map +1 -1
- package/dist/esm/core/loading/LoadingContext.d.ts.map +1 -1
- package/dist/esm/core/loading/LoadingContext.js +7 -1
- package/dist/esm/core/loading/LoadingContext.js.map +1 -1
- package/dist/esm/core/loading/LoadingGate.d.ts.map +1 -1
- package/dist/esm/core/loading/LoadingGate.js +19 -1
- package/dist/esm/core/loading/LoadingGate.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/AnalyticsContext.d.ts +15 -2
- package/dist/esm/core/monitoring/analytics/AnalyticsContext.d.ts.map +1 -1
- package/dist/esm/core/monitoring/analytics/AnalyticsContext.js +183 -20
- package/dist/esm/core/monitoring/analytics/AnalyticsContext.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/AnalyticsEventBridge.js +2 -2
- package/dist/esm/core/monitoring/analytics/AnalyticsEventBridge.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/analytics-provider-registry.frontend.service.d.ts +7 -15
- package/dist/esm/core/monitoring/analytics/analytics-provider-registry.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/monitoring/analytics/analytics-provider-registry.frontend.service.js +8 -26
- package/dist/esm/core/monitoring/analytics/analytics-provider-registry.frontend.service.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/analytics-provider.frontend.interface.d.ts +12 -3
- package/dist/esm/core/monitoring/analytics/analytics-provider.frontend.interface.d.ts.map +1 -1
- package/dist/esm/core/monitoring/analytics/analytics-provider.frontend.interface.js +3 -2
- package/dist/esm/core/monitoring/analytics/analytics-provider.frontend.interface.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/providers/backend-proxy-analytics.provider.d.ts +42 -0
- package/dist/esm/core/monitoring/analytics/providers/backend-proxy-analytics.provider.d.ts.map +1 -1
- package/dist/esm/core/monitoring/analytics/providers/backend-proxy-analytics.provider.js +89 -5
- package/dist/esm/core/monitoring/analytics/providers/backend-proxy-analytics.provider.js.map +1 -1
- package/dist/esm/core/monitoring/analytics/providers/console-analytics.provider.d.ts +2 -0
- package/dist/esm/core/monitoring/analytics/providers/console-analytics.provider.d.ts.map +1 -1
- package/dist/esm/core/monitoring/analytics/providers/console-analytics.provider.js +2 -0
- package/dist/esm/core/monitoring/analytics/providers/console-analytics.provider.js.map +1 -1
- package/dist/esm/core/navigation/NavigationContentAreas.d.ts +78 -0
- package/dist/esm/core/navigation/NavigationContentAreas.d.ts.map +1 -1
- package/dist/esm/core/navigation/NavigationContentAreas.js +264 -16
- package/dist/esm/core/navigation/NavigationContentAreas.js.map +1 -1
- package/dist/esm/core/navigation/NavigationContext.d.ts +8 -0
- package/dist/esm/core/navigation/NavigationContext.d.ts.map +1 -1
- package/dist/esm/core/navigation/NavigationContext.js +137 -30
- package/dist/esm/core/navigation/NavigationContext.js.map +1 -1
- package/dist/esm/core/navigation/launcher-resolution.d.ts +2 -0
- package/dist/esm/core/navigation/launcher-resolution.d.ts.map +1 -1
- package/dist/esm/core/navigation/launcher-resolution.js +1 -0
- package/dist/esm/core/navigation/launcher-resolution.js.map +1 -1
- package/dist/esm/core/navigation/navigation-cascade.d.ts +46 -0
- package/dist/esm/core/navigation/navigation-cascade.d.ts.map +1 -0
- package/dist/esm/core/navigation/navigation-cascade.js +222 -0
- package/dist/esm/core/navigation/navigation-cascade.js.map +1 -0
- package/dist/esm/core/navigation/navigation-clean-break.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/navigation/navigation-clean-break.frontend.utils.js +21 -2
- package/dist/esm/core/navigation/navigation-clean-break.frontend.utils.js.map +1 -1
- package/dist/esm/core/navigation/navigation-controller-internals.d.ts +71 -0
- package/dist/esm/core/navigation/navigation-controller-internals.d.ts.map +1 -0
- package/dist/esm/core/navigation/navigation-controller-internals.js +84 -0
- package/dist/esm/core/navigation/navigation-controller-internals.js.map +1 -0
- package/dist/esm/core/navigation/navigation-policy-resolver.service.d.ts +86 -2
- package/dist/esm/core/navigation/navigation-policy-resolver.service.d.ts.map +1 -1
- package/dist/esm/core/navigation/navigation-policy-resolver.service.js +242 -124
- package/dist/esm/core/navigation/navigation-policy-resolver.service.js.map +1 -1
- package/dist/esm/core/navigation/navigation.schemas.d.ts +170 -8
- package/dist/esm/core/navigation/navigation.schemas.d.ts.map +1 -1
- package/dist/esm/core/navigation/navigation.schemas.js +121 -2
- package/dist/esm/core/navigation/navigation.schemas.js.map +1 -1
- package/dist/esm/core/navigation/navigation.utils.d.ts +102 -6
- package/dist/esm/core/navigation/navigation.utils.d.ts.map +1 -1
- package/dist/esm/core/navigation/navigation.utils.js +283 -34
- package/dist/esm/core/navigation/navigation.utils.js.map +1 -1
- package/dist/esm/core/navigation/useIsStackEntryActive.d.ts +0 -10
- package/dist/esm/core/navigation/useIsStackEntryActive.d.ts.map +0 -1
- package/dist/esm/core/navigation/useIsStackEntryActive.js.map +0 -1
- package/dist/esm/core/navigation/useNavigationController.d.ts +28 -157
- package/dist/esm/core/navigation/useNavigationController.d.ts.map +1 -1
- package/dist/esm/core/navigation/useNavigationController.js +211 -1189
- package/dist/esm/core/navigation/useNavigationController.js.map +1 -1
- package/dist/esm/core/navigation/useNavigationRouterSync.d.ts +174 -0
- package/dist/esm/core/navigation/useNavigationRouterSync.d.ts.map +1 -0
- package/dist/esm/core/navigation/useNavigationRouterSync.js +977 -0
- package/dist/esm/core/navigation/useNavigationRouterSync.js.map +1 -0
- package/dist/esm/core/navigation/useOverlayTitle.d.ts +13 -1
- package/dist/esm/core/navigation/useOverlayTitle.d.ts.map +1 -1
- package/dist/esm/core/navigation/useOverlayTitle.js +15 -10
- package/dist/esm/core/navigation/useOverlayTitle.js.map +1 -1
- package/dist/esm/core/navigation/useResponsiveZoneMigration.d.ts +43 -0
- package/dist/esm/core/navigation/useResponsiveZoneMigration.d.ts.map +1 -0
- package/dist/esm/core/navigation/useResponsiveZoneMigration.js +44 -0
- package/dist/esm/core/navigation/useResponsiveZoneMigration.js.map +1 -0
- package/dist/esm/core/navigation/zone-collapse-migration.d.ts +83 -0
- package/dist/esm/core/navigation/zone-collapse-migration.d.ts.map +1 -0
- package/dist/esm/core/navigation/zone-collapse-migration.js +116 -0
- package/dist/esm/core/navigation/zone-collapse-migration.js.map +1 -0
- package/dist/esm/core/navigation/zone-collapse.d.ts +51 -0
- package/dist/esm/core/navigation/zone-collapse.d.ts.map +1 -0
- package/dist/esm/core/navigation/zone-collapse.js +59 -0
- package/dist/esm/core/navigation/zone-collapse.js.map +1 -0
- package/dist/esm/core/navigation/zone-emphasis.d.ts +3 -0
- package/dist/esm/core/navigation/zone-emphasis.d.ts.map +1 -1
- package/dist/esm/core/navigation/zone-emphasis.js +26 -4
- package/dist/esm/core/navigation/zone-emphasis.js.map +1 -1
- package/dist/esm/core/navigation/zone-visible-entry.d.ts +22 -0
- package/dist/esm/core/navigation/zone-visible-entry.d.ts.map +1 -1
- package/dist/esm/core/navigation/zone-visible-entry.js +25 -0
- package/dist/esm/core/navigation/zone-visible-entry.js.map +1 -1
- package/dist/esm/core/requests/websockets/WebSocketContext.d.ts.map +1 -1
- package/dist/esm/core/requests/websockets/WebSocketContext.js +53 -18
- package/dist/esm/core/requests/websockets/WebSocketContext.js.map +1 -1
- package/dist/esm/core/requests/websockets/WebSocketEventBridge.d.ts.map +1 -1
- package/dist/esm/core/requests/websockets/WebSocketEventBridge.js +3 -1
- package/dist/esm/core/requests/websockets/WebSocketEventBridge.js.map +1 -1
- package/dist/esm/core/requests/websockets/useNotificationBadges.d.ts +22 -0
- package/dist/esm/core/requests/websockets/useNotificationBadges.d.ts.map +1 -1
- package/dist/esm/core/requests/websockets/useNotificationBadges.js +72 -3
- package/dist/esm/core/requests/websockets/useNotificationBadges.js.map +1 -1
- package/dist/esm/core/requests/websockets/usePublishNotificationBadgeCount.d.ts +28 -0
- package/dist/esm/core/requests/websockets/usePublishNotificationBadgeCount.d.ts.map +1 -0
- package/dist/esm/core/requests/websockets/usePublishNotificationBadgeCount.js +86 -0
- package/dist/esm/core/requests/websockets/usePublishNotificationBadgeCount.js.map +1 -0
- package/dist/esm/core/requests/wildo-http-client-manual-calls.frontend.service.d.ts +38 -3
- package/dist/esm/core/requests/wildo-http-client-manual-calls.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/requests/wildo-http-client-manual-calls.frontend.service.js +57 -2
- package/dist/esm/core/requests/wildo-http-client-manual-calls.frontend.service.js.map +1 -1
- package/dist/esm/core/requests/wildo-http-client-resources.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/requests/wildo-http-client-resources.frontend.service.js +4 -2
- package/dist/esm/core/requests/wildo-http-client-resources.frontend.service.js.map +1 -1
- package/dist/esm/core/requests/wildo-http-client.frontend.service.d.ts +30 -1
- package/dist/esm/core/requests/wildo-http-client.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/requests/wildo-http-client.frontend.service.js +47 -4
- package/dist/esm/core/requests/wildo-http-client.frontend.service.js.map +1 -1
- package/dist/esm/core/resources/ResourceRegistryContext.d.ts.map +1 -1
- package/dist/esm/core/resources/ResourceRegistryContext.js +22 -1
- package/dist/esm/core/resources/ResourceRegistryContext.js.map +1 -1
- package/dist/esm/core/resources/context-resource-identifiers.frontend.utils.js +1 -1
- package/dist/esm/core/resources/context-resource-identifiers.frontend.utils.js.map +1 -1
- package/dist/esm/core/resources/frontend-resource.utils.d.ts +22 -1
- package/dist/esm/core/resources/frontend-resource.utils.d.ts.map +1 -1
- package/dist/esm/core/resources/frontend-resource.utils.js +25 -2
- package/dist/esm/core/resources/frontend-resource.utils.js.map +1 -1
- package/dist/esm/core/resources/operation-semantics.frontend.utils.d.ts +113 -13
- package/dist/esm/core/resources/operation-semantics.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/resources/operation-semantics.frontend.utils.js +173 -20
- package/dist/esm/core/resources/operation-semantics.frontend.utils.js.map +1 -1
- package/dist/esm/core/resources/relationship-surface-runtime.frontend.utils.d.ts +11 -0
- package/dist/esm/core/resources/relationship-surface-runtime.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/resources/relationship-surface-runtime.frontend.utils.js +7 -0
- package/dist/esm/core/resources/relationship-surface-runtime.frontend.utils.js.map +1 -1
- package/dist/esm/core/resources/resource-label-field-paths.frontend.utils.d.ts +3 -2
- package/dist/esm/core/resources/resource-label-field-paths.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/resources/resource-label-field-paths.frontend.utils.js +13 -5
- package/dist/esm/core/resources/resource-label-field-paths.frontend.utils.js.map +1 -1
- package/dist/esm/core/resources/resources-repository.frontend.service.d.ts +6 -0
- package/dist/esm/core/resources/resources-repository.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/resources/resources-repository.frontend.service.js +90 -1
- package/dist/esm/core/resources/resources-repository.frontend.service.js.map +1 -1
- package/dist/esm/core/resources/resources.frontend.schemas.d.ts +139 -16
- package/dist/esm/core/resources/resources.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/resources/resources.frontend.schemas.js +110 -11
- package/dist/esm/core/resources/resources.frontend.schemas.js.map +1 -1
- package/dist/esm/core/resources/rmm/ResourceMutationManager.d.ts.map +1 -1
- package/dist/esm/core/resources/rmm/ResourceMutationManager.js +3 -1
- package/dist/esm/core/resources/rmm/ResourceMutationManager.js.map +1 -1
- package/dist/esm/core/resources/rmm/update-like-mutation-fallback.frontend.d.ts +10 -0
- package/dist/esm/core/resources/rmm/update-like-mutation-fallback.frontend.d.ts.map +1 -1
- package/dist/esm/core/resources/rmm/update-like-mutation-fallback.frontend.js +8 -0
- package/dist/esm/core/resources/rmm/update-like-mutation-fallback.frontend.js.map +1 -1
- package/dist/esm/core/resources/rmm/useResourceRMM.d.ts +7 -0
- package/dist/esm/core/resources/rmm/useResourceRMM.d.ts.map +1 -1
- package/dist/esm/core/resources/rmm/useResourceRMM.js +9 -2
- package/dist/esm/core/resources/rmm/useResourceRMM.js.map +1 -1
- package/dist/esm/core/resources/useOperationDirectExecution.d.ts +59 -0
- package/dist/esm/core/resources/useOperationDirectExecution.d.ts.map +1 -0
- package/dist/esm/core/resources/useOperationDirectExecution.js +278 -0
- package/dist/esm/core/resources/useOperationDirectExecution.js.map +1 -0
- package/dist/esm/core/resources/useResourceOperationActions.d.ts +1 -1
- package/dist/esm/core/resources/useResourceOperationActions.d.ts.map +1 -1
- package/dist/esm/core/resources/useResourceOperationActions.js +69 -22
- package/dist/esm/core/resources/useResourceOperationActions.js.map +1 -1
- package/dist/esm/core/resources/useResourceOperationSurface.d.ts +8 -6
- package/dist/esm/core/resources/useResourceOperationSurface.d.ts.map +1 -1
- package/dist/esm/core/resources/useResourceOperationSurface.js +3 -2
- package/dist/esm/core/resources/useResourceOperationSurface.js.map +1 -1
- package/dist/esm/core/runtime/AppRouter.d.ts.map +1 -1
- package/dist/esm/core/runtime/AppRouter.js +23 -2
- package/dist/esm/core/runtime/AppRouter.js.map +1 -1
- package/dist/esm/core/runtime/ApplicationContext.shared.d.ts +4 -2
- package/dist/esm/core/runtime/ApplicationContext.shared.d.ts.map +1 -1
- package/dist/esm/core/runtime/ApplicationContext.shared.js.map +1 -1
- package/dist/esm/core/runtime/ApplicationMainContext.d.ts +12 -2
- package/dist/esm/core/runtime/ApplicationMainContext.d.ts.map +1 -1
- package/dist/esm/core/runtime/ApplicationMainContext.js +5 -2
- package/dist/esm/core/runtime/ApplicationMainContext.js.map +1 -1
- package/dist/esm/core/runtime/domain-module.frontend.definitions.d.ts +25 -1
- package/dist/esm/core/runtime/domain-module.frontend.definitions.d.ts.map +1 -1
- package/dist/esm/core/runtime/domain-module.frontend.definitions.js +37 -1
- package/dist/esm/core/runtime/domain-module.frontend.definitions.js.map +1 -1
- package/dist/esm/core/runtime/start-application.frontend.service.d.ts +21 -2
- package/dist/esm/core/runtime/start-application.frontend.service.d.ts.map +1 -1
- package/dist/esm/core/runtime/start-application.frontend.service.js +51 -4
- package/dist/esm/core/runtime/start-application.frontend.service.js.map +1 -1
- package/dist/esm/core/security/AuthSessionContext.d.ts +11 -0
- package/dist/esm/core/security/AuthSessionContext.d.ts.map +1 -1
- package/dist/esm/core/security/AuthSessionContext.js +70 -22
- package/dist/esm/core/security/AuthSessionContext.js.map +1 -1
- package/dist/esm/core/security/StepUpAuthContext.d.ts.map +1 -1
- package/dist/esm/core/security/StepUpAuthContext.js +10 -2
- package/dist/esm/core/security/StepUpAuthContext.js.map +1 -1
- package/dist/esm/core/security/UserOrgsContext.d.ts.map +1 -1
- package/dist/esm/core/security/UserOrgsContext.js +72 -8
- package/dist/esm/core/security/UserOrgsContext.js.map +1 -1
- package/dist/esm/core/security/route-organization-access.frontend.utils.d.ts +7 -0
- package/dist/esm/core/security/route-organization-access.frontend.utils.d.ts.map +1 -1
- package/dist/esm/core/security/route-organization-access.frontend.utils.js +8 -2
- package/dist/esm/core/security/route-organization-access.frontend.utils.js.map +1 -1
- package/dist/esm/core/security/useGrantedConsentPurposes.d.ts +30 -0
- package/dist/esm/core/security/useGrantedConsentPurposes.d.ts.map +1 -0
- package/dist/esm/core/security/useGrantedConsentPurposes.js +38 -0
- package/dist/esm/core/security/useGrantedConsentPurposes.js.map +1 -0
- package/dist/esm/core/ui/UIContext.d.ts.map +1 -1
- package/dist/esm/core/ui/UIContext.js +10 -6
- package/dist/esm/core/ui/UIContext.js.map +1 -1
- package/dist/esm/core/ui/color-conversion.utils.d.ts +20 -0
- package/dist/esm/core/ui/color-conversion.utils.d.ts.map +1 -1
- package/dist/esm/core/ui/color-conversion.utils.js +39 -5
- package/dist/esm/core/ui/color-conversion.utils.js.map +1 -1
- package/dist/esm/core/ui/themes/default.theme.d.ts.map +1 -1
- package/dist/esm/core/ui/themes/default.theme.js +22 -2
- package/dist/esm/core/ui/themes/default.theme.js.map +1 -1
- package/dist/esm/core/ui/ui.frontend.schemas.d.ts +6 -6
- package/dist/esm/core/ui/ui.frontend.schemas.d.ts.map +1 -1
- package/dist/esm/core/ui/ui.frontend.schemas.js +3 -3
- package/dist/esm/core/ui/ui.frontend.schemas.js.map +1 -1
- package/dist/esm/index.d.ts +10 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +19 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/testing/app-shell-placement-coverage.d.ts +43 -0
- package/dist/esm/testing/app-shell-placement-coverage.d.ts.map +1 -0
- package/dist/esm/testing/app-shell-placement-coverage.js +114 -0
- package/dist/esm/testing/app-shell-placement-coverage.js.map +1 -0
- package/dist/esm/testing/mock-builders.d.ts.map +1 -1
- package/dist/esm/testing/mock-builders.js +5 -0
- package/dist/esm/testing/mock-builders.js.map +1 -1
- package/dist/esm/testing.d.ts +1 -0
- package/dist/esm/testing.d.ts.map +1 -1
- package/dist/esm/testing.js +1 -0
- package/dist/esm/testing.js.map +1 -1
- package/package.json +9 -7
- package/dist/esm/core/navigation/useIsStackEntryActive.js +0 -15
- package/dist/tsconfig.build.tsbuildinfo +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepUpAuthContext.d.ts","sourceRoot":"","sources":["../../../../../src/core/security/StepUpAuthContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,EAAiB,SAAS,EAAqD,MAAM,OAAO,CAAC;AAC3G,OAAO,EAAc,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"StepUpAuthContext.d.ts","sourceRoot":"","sources":["../../../../../src/core/security/StepUpAuthContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,EAAiB,SAAS,EAAqD,MAAM,OAAO,CAAC;AAC3G,OAAO,EAAc,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAM5E,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,sDAAsD,CAAC;AAG1G,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAA+D,CAAC;AAE/I,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CA+GhE,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,uBAAyD,EAClE,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBlC"}
|
|
@@ -12,6 +12,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
13
13
|
import { AuthMethod, ReAuthenticationPurpose } from '@wildo-ai/saas-models';
|
|
14
14
|
import { getManualCallsHttpClient } from '../../core/requests/wildo-http-client-manual-calls.frontend.service.js';
|
|
15
|
+
import { StepUpRefusalOrigin } from '../../core/requests/wildo-http-client.frontend.service.js';
|
|
15
16
|
import { useResourceRegistry } from '../../core/resources/useResourceRegistry.js';
|
|
16
17
|
import { startAuthentication } from '@simplewebauthn/browser';
|
|
17
18
|
import { StepUpAuthDialog } from '../../components/auth/StepUpAuthDialog.js';
|
|
@@ -26,20 +27,27 @@ export const StepUpAuthProvider = ({ children }) => {
|
|
|
26
27
|
const [isLoading, setIsLoading] = useState(false);
|
|
27
28
|
// Which proof the pending refusal asked for (#1417): it decides what the dialog offers and what is minted.
|
|
28
29
|
const [purpose, setPurpose] = useState(ReAuthenticationPurpose.STEP_UP);
|
|
30
|
+
// Who asked (#1633): a client organization's policy asks a firm's expert for a second factor for that client only.
|
|
31
|
+
const [origin, setOrigin] = useState(StepUpRefusalOrigin.ACCOUNT_OR_OPERATION);
|
|
29
32
|
const pendingResolveRef = useRef(null);
|
|
30
33
|
const pendingRejectRef = useRef(null);
|
|
31
34
|
const stepUpInFlightRef = useRef(null);
|
|
32
35
|
const abortRef = useRef(null);
|
|
33
|
-
const stepUpAuthHandler = useCallback((requestedPurpose) => {
|
|
36
|
+
const stepUpAuthHandler = useCallback((requestedPurpose, requestedOrigin = StepUpRefusalOrigin.ACCOUNT_OR_OPERATION) => {
|
|
34
37
|
// Deduplicate: if a step-up is already in flight, share the same promise. A STEP-UP refusal joining a
|
|
35
38
|
// pending BINDING prompt upgrades it: a step-up proof opens binding doors too, while a binding proof
|
|
36
39
|
// opens no step-up door, so the one shared proof must be the stronger kind (#1417).
|
|
37
40
|
if (stepUpInFlightRef.current) {
|
|
38
41
|
if (requestedPurpose === ReAuthenticationPurpose.STEP_UP)
|
|
39
42
|
setPurpose(ReAuthenticationPurpose.STEP_UP);
|
|
43
|
+
// A client's refusal joining a pending prompt makes the shared proof a second factor: a password would satisfy
|
|
44
|
+
// the account's gate and still be refused by the client's, so the stricter origin wins.
|
|
45
|
+
if (requestedOrigin === StepUpRefusalOrigin.CLIENT_ORGANIZATION)
|
|
46
|
+
setOrigin(StepUpRefusalOrigin.CLIENT_ORGANIZATION);
|
|
40
47
|
return stepUpInFlightRef.current;
|
|
41
48
|
}
|
|
42
49
|
setPurpose(requestedPurpose);
|
|
50
|
+
setOrigin(requestedOrigin);
|
|
43
51
|
const promise = new Promise((resolve, reject) => {
|
|
44
52
|
pendingResolveRef.current = resolve;
|
|
45
53
|
pendingRejectRef.current = reject;
|
|
@@ -102,7 +110,7 @@ export const StepUpAuthProvider = ({ children }) => {
|
|
|
102
110
|
const value = useMemo(() => ({
|
|
103
111
|
isStepUpPending: isDialogOpen,
|
|
104
112
|
}), [isDialogOpen]);
|
|
105
|
-
return (_jsxs(StepUpAuthContext.Provider, { value: value, children: [children, _jsx(StepUpAuthDialog, { open: isDialogOpen, purpose: purpose, onConfirm: handleConfirm, onCancel: handleCancel, failure: failure, isLoading: isLoading })] }));
|
|
113
|
+
return (_jsxs(StepUpAuthContext.Provider, { value: value, children: [children, _jsx(StepUpAuthDialog, { open: isDialogOpen, purpose: purpose, origin: origin, onConfirm: handleConfirm, onCancel: handleCancel, failure: failure, isLoading: isLoading })] }));
|
|
106
114
|
};
|
|
107
115
|
/**
|
|
108
116
|
* Turn what the person supplied into a single-use step-up token.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepUpAuthContext.js","sourceRoot":"","sources":["../../../../../src/core/security/StepUpAuthContext.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * StepUpAuthContext\n *\n * Manages the step-up re-authentication flow triggered by HTTP 403 STEP_UP_REQUIRED responses.\n *\n * The provider registers a handler on both HTTP clients (manual calls + resources).\n * When the backend rejects a request because the user's last authentication is stale,\n * the HTTP interceptor calls the handler, which opens a dialog for re-authentication.\n * On success, the interceptor retries the original request with the new X-Reauth-Token header.\n */\n\nimport React, { createContext, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AuthMethod, ReAuthenticationPurpose } from '@wildo-ai/saas-models';\nimport { getManualCallsHttpClient } from '~wildo-frontend-lib/core/requests/wildo-http-client-manual-calls.frontend.service';\nimport { useResourceRegistry } from '~wildo-frontend-lib/core/resources/useResourceRegistry';\nimport { startAuthentication } from '@simplewebauthn/browser';\nimport type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\nimport { StepUpAuthDialog, type StepUpProof } from '~wildo-frontend-lib/components/auth/StepUpAuthDialog';\nimport { obtainFederatedReAuthenticationToken } from '~wildo-frontend-lib/core/security/federated-reauthentication.frontend';\n\nexport interface StepUpAuthContextType {\n isStepUpPending: boolean;\n}\n\nexport const StepUpAuthContext: React.Context<StepUpAuthContextType | undefined> = createContext<StepUpAuthContextType | undefined>(undefined);\n\nexport const StepUpAuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {\n const { setStepUpAuthHandler: setResourcesStepUpAuthHandler } = useResourceRegistry();\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n // The caught failure ITSELF, not text: the dialog resolves it into words through the i18n context, and\n // a string made here could only have been the error's own `message` — for a backend error, its i18n key.\n const [failure, setFailure] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(false);\n // Which proof the pending refusal asked for (#1417): it decides what the dialog offers and what is minted.\n const [purpose, setPurpose] = useState<ReAuthenticationPurpose>(ReAuthenticationPurpose.STEP_UP);\n\n const pendingResolveRef = useRef<((token: string) => void) | null>(null);\n const pendingRejectRef = useRef<((reason: Error) => void) | null>(null);\n const stepUpInFlightRef = useRef<Promise<string> | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const stepUpAuthHandler = useCallback((requestedPurpose: ReAuthenticationPurpose): Promise<string> => {\n // Deduplicate: if a step-up is already in flight, share the same promise. A STEP-UP refusal joining a\n // pending BINDING prompt upgrades it: a step-up proof opens binding doors too, while a binding proof\n // opens no step-up door, so the one shared proof must be the stronger kind (#1417).\n if (stepUpInFlightRef.current) {\n if (requestedPurpose === ReAuthenticationPurpose.STEP_UP) setPurpose(ReAuthenticationPurpose.STEP_UP);\n return stepUpInFlightRef.current;\n }\n setPurpose(requestedPurpose);\n const promise = new Promise<string>((resolve, reject) => {\n pendingResolveRef.current = resolve;\n pendingRejectRef.current = reject;\n setFailure(null);\n setIsLoading(false);\n setIsDialogOpen(true);\n });\n stepUpInFlightRef.current = promise;\n promise.finally(() => { stepUpInFlightRef.current = null; });\n return promise;\n }, []);\n\n const setResourcesHandlerRef = useRef(setResourcesStepUpAuthHandler);\n useEffect(() => {\n setResourcesHandlerRef.current = setResourcesStepUpAuthHandler;\n }, [setResourcesStepUpAuthHandler]);\n\n useEffect(() => {\n getManualCallsHttpClient().setStepUpAuthHandler(stepUpAuthHandler);\n setResourcesHandlerRef.current(stepUpAuthHandler);\n return () => {\n getManualCallsHttpClient().setStepUpAuthHandler(null);\n setResourcesHandlerRef.current(null);\n pendingRejectRef.current?.(new Error('StepUpAuthProvider unmounted'));\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n };\n }, [stepUpAuthHandler]);\n\n const handleConfirm = useCallback(async (proof: StepUpProof) => {\n setIsLoading(true);\n setFailure(null);\n // The dialog's Cancel ends a federated wait early (#1441); nothing else can, see\n // `federated-reauthentication.frontend.ts`.\n const abort = new AbortController();\n abortRef.current = abort;\n try {\n const { reAuthToken } = await obtainStepUpToken(proof, purpose, abort.signal);\n setIsDialogOpen(false);\n pendingResolveRef.current?.(reAuthToken);\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n } catch (e: unknown) {\n // A cancelled attempt's failure is not shown: the dialog is already closed, and would open next\n // time with it.\n if (!abort.signal.aborted) setFailure(e);\n } finally {\n if (abortRef.current === abort) abortRef.current = null;\n setIsLoading(false);\n }\n }, [purpose]);\n\n const handleCancel = useCallback(() => {\n abortRef.current?.abort();\n setIsDialogOpen(false);\n pendingRejectRef.current?.(new Error('Step-up authentication cancelled'));\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n }, []);\n\n const value = useMemo<StepUpAuthContextType>(() => ({\n isStepUpPending: isDialogOpen,\n }), [isDialogOpen]);\n\n return (\n <StepUpAuthContext.Provider value={value}>\n {children}\n <StepUpAuthDialog\n open={isDialogOpen}\n purpose={purpose}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n failure={failure}\n isLoading={isLoading}\n />\n </StepUpAuthContext.Provider>\n );\n};\n\n/**\n * Turn what the person supplied into a single-use step-up token.\n *\n * A passkey takes two round trips because WebAuthn is challenge-response: fetch the server's\n * challenge, have the authenticator sign it, then present the assertion. Password and TOTP are one. A\n * linked identity runs its provider in a popup and redeems the code it returns (#1441).\n */\nexport async function obtainStepUpToken(\n proof: StepUpProof,\n purpose: ReAuthenticationPurpose = ReAuthenticationPurpose.STEP_UP,\n signal?: AbortSignal,\n): Promise<{ reAuthToken: string }> {\n const client = getManualCallsHttpClient();\n switch (proof.method) {\n case AuthMethod.PASSWORD:\n return client.reAuthenticate(AuthMethod.PASSWORD, { password: proof.password }, purpose);\n case AuthMethod.TOTP:\n return client.reAuthenticate(AuthMethod.TOTP, { code: proof.code }, purpose);\n case AuthMethod.PASSKEY: {\n const options = (await client.reAuthPasskeyOptions()) as unknown as PublicKeyCredentialRequestOptionsJSON;\n const assertion = await startAuthentication({ optionsJSON: options });\n return client.reAuthenticate(AuthMethod.PASSKEY, { passkeyResponse: assertion as unknown as Record<string, unknown> }, purpose);\n }\n case AuthMethod.EXTERNAL_OAUTH2:\n case AuthMethod.ORG_OPENID_CONNECT:\n case AuthMethod.ORG_SAML:\n return obtainFederatedReAuthenticationToken(proof.identityLinkId, purpose, proof.popup, signal);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"StepUpAuthContext.js","sourceRoot":"","sources":["../../../../../src/core/security/StepUpAuthContext.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * StepUpAuthContext\n *\n * Manages the step-up re-authentication flow triggered by HTTP 403 STEP_UP_REQUIRED responses.\n *\n * The provider registers a handler on both HTTP clients (manual calls + resources).\n * When the backend rejects a request because the user's last authentication is stale,\n * the HTTP interceptor calls the handler, which opens a dialog for re-authentication.\n * On success, the interceptor retries the original request with the new X-Reauth-Token header.\n */\n\nimport React, { createContext, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AuthMethod, ReAuthenticationPurpose } from '@wildo-ai/saas-models';\nimport { getManualCallsHttpClient } from '~wildo-frontend-lib/core/requests/wildo-http-client-manual-calls.frontend.service';\nimport { StepUpRefusalOrigin } from '~wildo-frontend-lib/core/requests/wildo-http-client.frontend.service';\nimport { useResourceRegistry } from '~wildo-frontend-lib/core/resources/useResourceRegistry';\nimport { startAuthentication } from '@simplewebauthn/browser';\nimport type { PublicKeyCredentialRequestOptionsJSON } from '@simplewebauthn/browser';\nimport { StepUpAuthDialog, type StepUpProof } from '~wildo-frontend-lib/components/auth/StepUpAuthDialog';\nimport { obtainFederatedReAuthenticationToken } from '~wildo-frontend-lib/core/security/federated-reauthentication.frontend';\n\nexport interface StepUpAuthContextType {\n isStepUpPending: boolean;\n}\n\nexport const StepUpAuthContext: React.Context<StepUpAuthContextType | undefined> = createContext<StepUpAuthContextType | undefined>(undefined);\n\nexport const StepUpAuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {\n const { setStepUpAuthHandler: setResourcesStepUpAuthHandler } = useResourceRegistry();\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n // The caught failure ITSELF, not text: the dialog resolves it into words through the i18n context, and\n // a string made here could only have been the error's own `message` — for a backend error, its i18n key.\n const [failure, setFailure] = useState<unknown>(null);\n const [isLoading, setIsLoading] = useState(false);\n // Which proof the pending refusal asked for (#1417): it decides what the dialog offers and what is minted.\n const [purpose, setPurpose] = useState<ReAuthenticationPurpose>(ReAuthenticationPurpose.STEP_UP);\n // Who asked (#1633): a client organization's policy asks a firm's expert for a second factor for that client only.\n const [origin, setOrigin] = useState<StepUpRefusalOrigin>(StepUpRefusalOrigin.ACCOUNT_OR_OPERATION);\n\n const pendingResolveRef = useRef<((token: string) => void) | null>(null);\n const pendingRejectRef = useRef<((reason: Error) => void) | null>(null);\n const stepUpInFlightRef = useRef<Promise<string> | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const stepUpAuthHandler = useCallback((\n requestedPurpose: ReAuthenticationPurpose,\n requestedOrigin: StepUpRefusalOrigin = StepUpRefusalOrigin.ACCOUNT_OR_OPERATION,\n ): Promise<string> => {\n // Deduplicate: if a step-up is already in flight, share the same promise. A STEP-UP refusal joining a\n // pending BINDING prompt upgrades it: a step-up proof opens binding doors too, while a binding proof\n // opens no step-up door, so the one shared proof must be the stronger kind (#1417).\n if (stepUpInFlightRef.current) {\n if (requestedPurpose === ReAuthenticationPurpose.STEP_UP) setPurpose(ReAuthenticationPurpose.STEP_UP);\n // A client's refusal joining a pending prompt makes the shared proof a second factor: a password would satisfy\n // the account's gate and still be refused by the client's, so the stricter origin wins.\n if (requestedOrigin === StepUpRefusalOrigin.CLIENT_ORGANIZATION) setOrigin(StepUpRefusalOrigin.CLIENT_ORGANIZATION);\n return stepUpInFlightRef.current;\n }\n setPurpose(requestedPurpose);\n setOrigin(requestedOrigin);\n const promise = new Promise<string>((resolve, reject) => {\n pendingResolveRef.current = resolve;\n pendingRejectRef.current = reject;\n setFailure(null);\n setIsLoading(false);\n setIsDialogOpen(true);\n });\n stepUpInFlightRef.current = promise;\n promise.finally(() => { stepUpInFlightRef.current = null; });\n return promise;\n }, []);\n\n const setResourcesHandlerRef = useRef(setResourcesStepUpAuthHandler);\n useEffect(() => {\n setResourcesHandlerRef.current = setResourcesStepUpAuthHandler;\n }, [setResourcesStepUpAuthHandler]);\n\n useEffect(() => {\n getManualCallsHttpClient().setStepUpAuthHandler(stepUpAuthHandler);\n setResourcesHandlerRef.current(stepUpAuthHandler);\n return () => {\n getManualCallsHttpClient().setStepUpAuthHandler(null);\n setResourcesHandlerRef.current(null);\n pendingRejectRef.current?.(new Error('StepUpAuthProvider unmounted'));\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n };\n }, [stepUpAuthHandler]);\n\n const handleConfirm = useCallback(async (proof: StepUpProof) => {\n setIsLoading(true);\n setFailure(null);\n // The dialog's Cancel ends a federated wait early (#1441); nothing else can, see\n // `federated-reauthentication.frontend.ts`.\n const abort = new AbortController();\n abortRef.current = abort;\n try {\n const { reAuthToken } = await obtainStepUpToken(proof, purpose, abort.signal);\n setIsDialogOpen(false);\n pendingResolveRef.current?.(reAuthToken);\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n } catch (e: unknown) {\n // A cancelled attempt's failure is not shown: the dialog is already closed, and would open next\n // time with it.\n if (!abort.signal.aborted) setFailure(e);\n } finally {\n if (abortRef.current === abort) abortRef.current = null;\n setIsLoading(false);\n }\n }, [purpose]);\n\n const handleCancel = useCallback(() => {\n abortRef.current?.abort();\n setIsDialogOpen(false);\n pendingRejectRef.current?.(new Error('Step-up authentication cancelled'));\n pendingResolveRef.current = null;\n pendingRejectRef.current = null;\n }, []);\n\n const value = useMemo<StepUpAuthContextType>(() => ({\n isStepUpPending: isDialogOpen,\n }), [isDialogOpen]);\n\n return (\n <StepUpAuthContext.Provider value={value}>\n {children}\n <StepUpAuthDialog\n open={isDialogOpen}\n purpose={purpose}\n origin={origin}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n failure={failure}\n isLoading={isLoading}\n />\n </StepUpAuthContext.Provider>\n );\n};\n\n/**\n * Turn what the person supplied into a single-use step-up token.\n *\n * A passkey takes two round trips because WebAuthn is challenge-response: fetch the server's\n * challenge, have the authenticator sign it, then present the assertion. Password and TOTP are one. A\n * linked identity runs its provider in a popup and redeems the code it returns (#1441).\n */\nexport async function obtainStepUpToken(\n proof: StepUpProof,\n purpose: ReAuthenticationPurpose = ReAuthenticationPurpose.STEP_UP,\n signal?: AbortSignal,\n): Promise<{ reAuthToken: string }> {\n const client = getManualCallsHttpClient();\n switch (proof.method) {\n case AuthMethod.PASSWORD:\n return client.reAuthenticate(AuthMethod.PASSWORD, { password: proof.password }, purpose);\n case AuthMethod.TOTP:\n return client.reAuthenticate(AuthMethod.TOTP, { code: proof.code }, purpose);\n case AuthMethod.PASSKEY: {\n const options = (await client.reAuthPasskeyOptions()) as unknown as PublicKeyCredentialRequestOptionsJSON;\n const assertion = await startAuthentication({ optionsJSON: options });\n return client.reAuthenticate(AuthMethod.PASSKEY, { passkeyResponse: assertion as unknown as Record<string, unknown> }, purpose);\n }\n case AuthMethod.EXTERNAL_OAUTH2:\n case AuthMethod.ORG_OPENID_CONNECT:\n case AuthMethod.ORG_SAML:\n return obtainFederatedReAuthenticationToken(proof.identityLinkId, purpose, proof.popup, signal);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrgsContext.d.ts","sourceRoot":"","sources":["../../../../../src/core/security/UserOrgsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAA2B,SAAS,EAA2C,MAAM,OAAO,CAAC;AAC3G,OAAO,EACL,WAAW,EACX,mBAAmB,EAMnB,6BAA6B,EAC7B,WAAW,EAIX,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA2BlD;;;;GAIG;AAEH,MAAM,WAAW,mBAAmB;IAElC,IAAI,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,wBAAwB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,0BAA0B,CAAC,CAAC;IACxF,YAAY,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,cAAc,CAAC,CAAC;IAChE,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAGvC,mBAAmB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC;IAC9E,sBAAsB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,wBAAwB,CAAC,CAAC;IAGpF,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAGzB,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACzC,wBAAwB,EAAE,6BAA6B,GAAG,IAAI,CAAC;IAG/D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAG5B,sBAAsB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,sBAAsB,EAAE,MAAM,mBAAmB,GAAG,IAAI,CAAC;IACzD,oBAAoB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAG1C,UAAU,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAErC;;;;;;;;;;;;OAYG;IACH,qBAAqB,EAAE,CAAC,eAAe,EAAE,SAAS,cAAc,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7F;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAA6D,CAAC;AAEzI,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"UserOrgsContext.d.ts","sourceRoot":"","sources":["../../../../../src/core/security/UserOrgsContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAA2B,SAAS,EAA2C,MAAM,OAAO,CAAC;AAC3G,OAAO,EACL,WAAW,EACX,mBAAmB,EAMnB,6BAA6B,EAC7B,WAAW,EAIX,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA2BlD;;;;GAIG;AAEH,MAAM,WAAW,mBAAmB;IAElC,IAAI,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IAChD,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,wBAAwB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,0BAA0B,CAAC,CAAC;IACxF,YAAY,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,cAAc,CAAC,CAAC;IAChE,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,eAAe,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACtE,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAGvC,mBAAmB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC;IAC9E,sBAAsB,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,wBAAwB,CAAC,CAAC;IAGpF,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAGzB,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACzC,wBAAwB,EAAE,6BAA6B,GAAG,IAAI,CAAC;IAG/D,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAG5B,sBAAsB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,sBAAsB,EAAE,MAAM,mBAAmB,GAAG,IAAI,CAAC;IACzD,oBAAoB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAG1C,UAAU,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAErC;;;;;;;;;;;;OAYG;IACH,qBAAqB,EAAE,CAAC,eAAe,EAAE,SAAS,cAAc,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7F;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAA6D,CAAC;AAEzI,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CAo3B9D,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { CoreResourceType, ResourcesConfig_OperationPathUtils, CoreResourceOpera
|
|
|
4
4
|
import { useResourceRegistry } from '../../core/resources/useResourceRegistry.js';
|
|
5
5
|
import { LoggerFrontendService } from '../../core/monitoring/logger.frontend.service.js';
|
|
6
6
|
import { useEventBus } from '../../core/events/useEventBus.js';
|
|
7
|
-
import { FrontendEvents } from '../../core/events/events.frontend.schemas.js';
|
|
7
|
+
import { FrontendEvents, SessionEndReason } from '../../core/events/events.frontend.schemas.js';
|
|
8
8
|
import { useAuthSession } from './useAuthSession.js';
|
|
9
9
|
import { AuthSessionUtils } from './auth-session.utils.js';
|
|
10
10
|
import { isTransientBackendFailure } from '../../core/requests/auth-refresh-resilience.frontend.js';
|
|
@@ -40,7 +40,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
40
40
|
const { emit } = useEventBus();
|
|
41
41
|
// Consume auth session context
|
|
42
42
|
const authSession = useAuthSession();
|
|
43
|
-
const { auth, tokenStorage, identifyByEmail, authenticateWithPassword, authenticate, getSessionState, isAuthenticated, logout: authLogout, initiateOAuth2Login, handleAuthCodeExchange, markSessionRestored, setSessionRestoring, connectWebSocket, } = authSession;
|
|
43
|
+
const { auth, tokenStorage, identifyByEmail, authenticateWithPassword, authenticate, getSessionState, isAuthenticated, logout: authLogout, endSession, getSessionEstablishment, getSessionEndReason, initiateOAuth2Login, handleAuthCodeExchange, markSessionRestored, setSessionRestoring, connectWebSocket, } = authSession;
|
|
44
44
|
const appScope = useAppScope();
|
|
45
45
|
const { commitOrganizationScopeValue } = useAppScopeInternal();
|
|
46
46
|
const currentOrganizationId = appScope.currentOrganizationId;
|
|
@@ -104,6 +104,66 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
104
104
|
...(preferences?.privacy !== undefined ? { privacy: preferences.privacy } : {}),
|
|
105
105
|
});
|
|
106
106
|
}, [emit]);
|
|
107
|
+
/*
|
|
108
|
+
* `USER_LOGIN` / `USER_LOGOUT` — announced HERE, once per transition of the known person (#1977).
|
|
109
|
+
*
|
|
110
|
+
* Nothing emitted them before, so every listener — error-report attribution, analytics identify and
|
|
111
|
+
* reset, the sign-in and sign-out analytics events — was dead code that read as if sign-in were
|
|
112
|
+
* observed. This is the one place every sign-in method and every way a session ends converge: each
|
|
113
|
+
* authentication stores a token, the auto-load effect below restores the user from it, and every
|
|
114
|
+
* sign-out, refused refresh, failed restore and cross-tab sign-out clears the token, which clears the
|
|
115
|
+
* user. Emitting at each auth method instead would be a dozen call sites, and the next method added
|
|
116
|
+
* would be the one that forgot. Declared BEFORE the preferences effect, because effects run in
|
|
117
|
+
* declaration order and a person's arrival must precede their preferences.
|
|
118
|
+
*
|
|
119
|
+
* The id last announced is the guard, so a re-render, a preferences write that replaces the user
|
|
120
|
+
* object, or StrictMode re-running an effect announces nothing, and a direct switch from one person to
|
|
121
|
+
* another announces the first one's departure before the second one's arrival. HOW the session began
|
|
122
|
+
* and WHY it ended are recorded by `AuthSessionProvider`, the only code that knows, and read at the
|
|
123
|
+
* moment of announcing.
|
|
124
|
+
*
|
|
125
|
+
* A DEPARTURE is announced by the two places that clear the user, BEFORE they publish `privacy: null`:
|
|
126
|
+
* a listener that must act while the person's consent still holds (the sign-out analytics event, sent
|
|
127
|
+
* before the destinations are reset) needs the announcement first, and the consent-based providers
|
|
128
|
+
* stop on the `privacy: null` that follows. The effect announces ARRIVALS, and a departure only as a
|
|
129
|
+
* backstop for a path that cleared the user without announcing. An unmount announces nothing: the
|
|
130
|
+
* provider going away is not the person signing out.
|
|
131
|
+
*/
|
|
132
|
+
const announcedUserIdRef = useRef(null);
|
|
133
|
+
const announceDeparture = useCallback((reason) => {
|
|
134
|
+
const departedUserId = announcedUserIdRef.current;
|
|
135
|
+
if (departedUserId === null)
|
|
136
|
+
return;
|
|
137
|
+
announcedUserIdRef.current = null;
|
|
138
|
+
emit(FrontendEvents.USER_LOGOUT, { userId: departedUserId, reason });
|
|
139
|
+
}, [emit]);
|
|
140
|
+
const knownUserId = user?._id ?? null;
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
const previousUserId = announcedUserIdRef.current;
|
|
143
|
+
if (previousUserId === knownUserId)
|
|
144
|
+
return;
|
|
145
|
+
if (previousUserId !== null && knownUserId !== null) {
|
|
146
|
+
/*
|
|
147
|
+
* One person REPLACED by another with no sign-out between them. Believed unreachable today: a sign-in
|
|
148
|
+
* while someone is loaded sets `isRestoringSession` with `hasInitializedRef` already true, so the
|
|
149
|
+
* auto-load effect below skips it, and `restoreSession` returns early while a user is loaded. Handled
|
|
150
|
+
* anyway, because the consequence of getting it wrong is the next person's analytics running under
|
|
151
|
+
* the previous person's consent: the departure is followed by the same `privacy: null` a sign-out
|
|
152
|
+
* publishes, BEFORE the arrival, so the next person is judged on their own preferences, which the
|
|
153
|
+
* preferences effect below publishes after this one.
|
|
154
|
+
*/
|
|
155
|
+
announceDeparture(SessionEndReason.REPLACED);
|
|
156
|
+
setPrivacy(null);
|
|
157
|
+
emitPreferencesChanged(null);
|
|
158
|
+
}
|
|
159
|
+
else if (previousUserId !== null) {
|
|
160
|
+
announceDeparture(getSessionEndReason());
|
|
161
|
+
}
|
|
162
|
+
if (knownUserId !== null) {
|
|
163
|
+
announcedUserIdRef.current = knownUserId;
|
|
164
|
+
emit(FrontendEvents.USER_LOGIN, { userId: knownUserId, establishment: getSessionEstablishment() });
|
|
165
|
+
}
|
|
166
|
+
}, [knownUserId, emit, announceDeparture, emitPreferencesChanged, getSessionEndReason, getSessionEstablishment]);
|
|
107
167
|
const primaryScopeInitiatorIds = useMemo(() => {
|
|
108
168
|
return ScopeUtilsService.buildInitiatorIds({
|
|
109
169
|
userId: appScope.currentUserId,
|
|
@@ -404,7 +464,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
404
464
|
}
|
|
405
465
|
else {
|
|
406
466
|
logger.warn('Session restoration could not build a valid authenticated context; logging out to avoid a half-restored state');
|
|
407
|
-
|
|
467
|
+
endSession(SessionEndReason.SESSION_ENDED);
|
|
408
468
|
}
|
|
409
469
|
return restored;
|
|
410
470
|
}
|
|
@@ -455,7 +515,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
455
515
|
errorType: error?.wildoError?.type || error?.response?.data?.error?.type,
|
|
456
516
|
status: error?.response?.status,
|
|
457
517
|
});
|
|
458
|
-
|
|
518
|
+
endSession(SessionEndReason.SESSION_ENDED);
|
|
459
519
|
return false;
|
|
460
520
|
}
|
|
461
521
|
// Fail closed on unexpected NON-transient errors. A partially restored
|
|
@@ -465,7 +525,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
465
525
|
error: errorMessage,
|
|
466
526
|
errorType: error?.wildoError?.type,
|
|
467
527
|
});
|
|
468
|
-
|
|
528
|
+
endSession(SessionEndReason.SESSION_ENDED);
|
|
469
529
|
return false;
|
|
470
530
|
}
|
|
471
531
|
}
|
|
@@ -475,7 +535,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
475
535
|
auth.sessionType,
|
|
476
536
|
auth.accessToken,
|
|
477
537
|
user,
|
|
478
|
-
|
|
538
|
+
endSession,
|
|
479
539
|
markSessionRestored,
|
|
480
540
|
setSessionRestoring,
|
|
481
541
|
connectWebSocket,
|
|
@@ -585,6 +645,8 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
585
645
|
*/
|
|
586
646
|
const logout = useCallback(() => {
|
|
587
647
|
logDebug('Logging out user', { userId: user?._id, organizationId: currentOrganizationId });
|
|
648
|
+
// Announced first, while the person's consent still holds — see the block above (#1977).
|
|
649
|
+
announceDeparture(SessionEndReason.SIGNED_OUT);
|
|
588
650
|
// Clear user/org data first
|
|
589
651
|
setUser(null);
|
|
590
652
|
setOrganizations([]);
|
|
@@ -597,7 +659,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
597
659
|
previousTokenRef.current = null;
|
|
598
660
|
// Call auth logout (clears tokens, disconnects WebSocket)
|
|
599
661
|
authLogout();
|
|
600
|
-
}, [user?._id, currentOrganizationId, authLogout, commitOrganizationScopeValue, emitPreferencesChanged]);
|
|
662
|
+
}, [user?._id, currentOrganizationId, authLogout, announceDeparture, commitOrganizationScopeValue, emitPreferencesChanged]);
|
|
601
663
|
// Auto-load user/org data when token becomes available
|
|
602
664
|
useEffect(() => {
|
|
603
665
|
const accessToken = auth.accessToken;
|
|
@@ -629,6 +691,8 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
629
691
|
useEffect(() => {
|
|
630
692
|
if (!auth.accessToken && previousTokenRef.current) {
|
|
631
693
|
logDebug('Token removed, clearing user/org data');
|
|
694
|
+
// Announced before `privacy: null`, with the reason the auth session recorded (#1977).
|
|
695
|
+
announceDeparture(getSessionEndReason());
|
|
632
696
|
setUser(null);
|
|
633
697
|
setOrganizations([]);
|
|
634
698
|
commitOrganizationScopeValue(null);
|
|
@@ -638,7 +702,7 @@ export const UserOrgsProvider = ({ children }) => {
|
|
|
638
702
|
previousTokenRef.current = null;
|
|
639
703
|
hasInitializedRef.current = false;
|
|
640
704
|
}
|
|
641
|
-
}, [auth.accessToken, commitOrganizationScopeValue, emitPreferencesChanged]);
|
|
705
|
+
}, [auth.accessToken, announceDeparture, commitOrganizationScopeValue, emitPreferencesChanged, getSessionEndReason]);
|
|
642
706
|
const value = useMemo(() => ({
|
|
643
707
|
// Re-exported from AuthSession for backward compatibility
|
|
644
708
|
auth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserOrgsContext.js","sourceRoot":"","sources":["../../../../../src/core/security/UserOrgsContext.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { createContext, useState, ReactNode, useMemo, useEffect, useCallback, useRef } from 'react';\nimport {\n UserContext,\n OrganizationContext,\n CoreResourceType,\n ResourcesConfig_OperationPathUtils,\n CoreResourceOperation,\n ResourceOperationVariantType,\n OPERATION_VARIANT_KEY,\n ExecutionContext_InitiatorIds,\n UserPrivacy,\n UserPreferences,\n SessionType,\n normalizeConsentPurposes,\n type ConsentPurpose,\n} from '@wildo-ai/saas-models';\nimport { useResourceRegistry } from '~wildo-frontend-lib/core/resources/useResourceRegistry';\nimport { LoggerFrontendService } from '~wildo-frontend-lib/core/monitoring/logger.frontend.service';\nimport { useEventBus } from '~wildo-frontend-lib/core/events/useEventBus';\nimport { FrontendEvents } from '~wildo-frontend-lib/core/events/events.frontend.schemas';\nimport {\n EffectivePermissions,\n} from './security.frontend.schemas';\nimport { useAuthSession } from './useAuthSession';\nimport { AuthSessionUtils } from './auth-session.utils';\nimport { isTransientBackendFailure } from '~wildo-frontend-lib/core/requests/auth-refresh-resilience.frontend';\nimport { decodeJwtPayload } from './jwt.frontend.utils';\nimport { useAppScope } from '~wildo-frontend-lib/core/scope/useAppScope';\nimport { useAppScopeInternal } from '~wildo-frontend-lib/core/scope/AppScopeContext';\nimport { ScopeUtilsService } from '~wildo-frontend-lib/core/scope/scope.utils.frontend.service';\nimport { findDefaultApiReadOperation } from './route-organization-access.frontend.utils';\n\nconst logger: LoggerFrontendService = LoggerFrontendService.getLogger();\nconst logDebug: (message: string, context?: Record<string, unknown>) => void = logger.debugByType('UserOrgsContext');\nlogger.setDebugTypeLogging('UserOrgsContext', false);\n\n/**\n * Session-restore retry backoff bounds (transient backend failures only).\n *\n * On RELOAD, a backend that is recompiling/restarting (dev) or briefly\n * unavailable (prod) makes the session-restore fetch fail transiently. Rather\n * than force a logout — which clears the shared `__wildo_refresh` cookie and\n * drops the user to the login screen — restore preserves the session and\n * retries with exponential backoff until the backend returns. Genuine auth/authz\n * and non-network errors do NOT retry (see `restoreSession`). Backoff caps so a\n * sustained outage settles at one attempt per {@link RESTORE_RETRY_MAX_DELAY_MS}.\n */\nconst RESTORE_RETRY_BASE_DELAY_MS = 1_000;\nconst RESTORE_RETRY_MAX_DELAY_MS = 30_000;\n\n/**\n * User Organizations Context\n * Manages user data, organizations, permissions, and preferences\n * Consumes AuthSessionContext for authentication state\n */\n\nexport interface UserOrgsContextType {\n // Re-exported from AuthSession for backward compatibility\n auth: ReturnType<typeof useAuthSession>['auth'];\n identifyByEmail: ReturnType<typeof useAuthSession>['identifyByEmail'];\n authenticateWithPassword: ReturnType<typeof useAuthSession>['authenticateWithPassword'];\n authenticate: ReturnType<typeof useAuthSession>['authenticate'];\n getSessionState: ReturnType<typeof useAuthSession>['getSessionState'];\n isAuthenticated: ReturnType<typeof useAuthSession>['isAuthenticated'];\n logout: () => void;\n restoreSession: () => Promise<boolean>;\n\n // OAuth2 + cross-frontend-handoff methods (delegated from AuthSession)\n initiateOAuth2Login: ReturnType<typeof useAuthSession>['initiateOAuth2Login'];\n handleAuthCodeExchange: ReturnType<typeof useAuthSession>['handleAuthCodeExchange'];\n\n // User data\n user: UserContext | null;\n\n // Organization data\n organizations: OrganizationContext[];\n currentOrganizationId: string | null;\n permissions: EffectivePermissions | null;\n primaryScopeInitiatorIds: ExecutionContext_InitiatorIds | null;\n\n // Privacy (only preference managed here, others are in their respective contexts)\n privacy: UserPrivacy | null;\n\n // Organization management\n setCurrentOrganization: (organizationId: string) => void;\n getCurrentOrganization: () => OrganizationContext | null;\n refreshOrganizations: () => Promise<void>;\n\n // Privacy getter\n getPrivacy: () => UserPrivacy | null;\n\n /**\n * Record the signed-in person's consent decision: exactly the purposes they granted (#534).\n *\n * The argument is the WHOLE granted set, never a delta — a purpose left out is a purpose not granted,\n * so an unticked box is a withdrawal rather than \"no change\". The write always carries a decision\n * claim, which is what lets \"grant nothing\" be recorded as a decision instead of reading as a person\n * who was never asked; the recorded instant is the server's (`buildConsentDecisionPatch`).\n *\n * Resolves with the stored privacy block once it is in state, so a caller gating on consent (the\n * consent gate) sees the new decision on the next render. Rejects when the application mounts no\n * self-preferences UPDATE door or the write fails — a consent surface must say it could not save,\n * never behave as though it had.\n */\n recordConsentDecision: (grantedPurposes: readonly ConsentPurpose[]) => Promise<UserPrivacy>;\n}\n\n/**\n * UserOrgs Context\n * Exported for use in separate hook file (Fast Refresh compatibility)\n * @internal - Use useUserOrgs() hook instead of accessing this directly\n */\nexport const UserOrgsContext: React.Context<UserOrgsContextType | undefined> = createContext<UserOrgsContextType | undefined>(undefined);\n\nexport const UserOrgsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {\n const { doOperation, registry } = useResourceRegistry();\n const { emit } = useEventBus();\n\n // Consume auth session context\n const authSession = useAuthSession();\n const {\n auth,\n tokenStorage,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout: authLogout,\n initiateOAuth2Login,\n handleAuthCodeExchange,\n markSessionRestored,\n setSessionRestoring,\n connectWebSocket,\n } = authSession;\n const appScope = useAppScope();\n const { commitOrganizationScopeValue } = useAppScopeInternal();\n const currentOrganizationId = appScope.currentOrganizationId;\n\n const hasInitializedRef = useRef(false);\n const previousTokenRef = useRef<string | null>(null);\n // Restore-retry lifecycle: `restoreAbortRef` flips true on unmount so an\n // in-flight backoff loop bails instead of touching state on a dead component;\n // `restoreRetryTimerRef` holds the pending backoff timer for cleanup.\n const restoreAbortRef = useRef(false);\n const restoreRetryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const [user, setUser] = useState<UserContext | null>(null);\n\n const [organizations, setOrganizations] = useState<OrganizationContext[]>([]);\n\n const [permissions, setPermissions] = useState<{\n appLevel: string[];\n organizations: Record<string, string[]>;\n } | null>(null);\n\n const [privacy, setPrivacy] = useState<UserPrivacy | null>(null);\n\n type PreferencesPayload = Pick<UserPreferences, 'languagePreferences' | 'regional' | 'ui' | 'notifications' | 'privacy'>;\n\n /**\n * The TENANT's half of the payload, derived from its preferences record rather than passed\n * alongside it (#410).\n *\n * The organization contributes two things to `I18nContext` — its language policy and its regional\n * defaults — and they are forwarded together because they come from one record. An earlier shape\n * took the language block as its own argument, and when the regional half was added every call\n * site would have had to remember to forward a second one: three sites, one obligation each, and\n * a fourth site tomorrow that forwards neither. Passing the record makes forgetting impossible.\n */\n const organizationPreferencesPayload = (\n organizationPreferences: OrganizationContext['preferences'] | null | undefined,\n ): Record<string, unknown> => {\n if (organizationPreferences === undefined) {\n return {};\n }\n if (organizationPreferences === null) {\n return { organizationLanguagePreferences: null, organizationRegionalPreferences: null };\n }\n return {\n organizationLanguagePreferences: organizationPreferences.languagePreferences ?? null,\n organizationRegionalPreferences: {\n timezone: organizationPreferences.timezone,\n locale: organizationPreferences.locale,\n dateFormat: organizationPreferences.dateFormat,\n timeFormat: organizationPreferences.timeFormat,\n },\n };\n };\n\n const emitPreferencesChanged = useCallback((\n preferences: PreferencesPayload | null | undefined,\n organizationPreferences?: OrganizationContext['preferences'] | null,\n ): void => {\n if (preferences === null) {\n emit(FrontendEvents.USER_PREFERENCES_CHANGED, {\n languagePreferences: null,\n organizationLanguagePreferences: null,\n regionalPreferences: null,\n organizationRegionalPreferences: null,\n notificationsPreferences: null,\n uiPreferences: null,\n privacy: null,\n });\n return;\n }\n\n emit(FrontendEvents.USER_PREFERENCES_CHANGED, {\n ...(preferences?.languagePreferences !== undefined ? { languagePreferences: preferences.languagePreferences } : {}),\n ...organizationPreferencesPayload(organizationPreferences),\n ...(preferences?.regional !== undefined ? { regionalPreferences: preferences.regional } : {}),\n ...(preferences?.notifications !== undefined ? { notificationsPreferences: preferences.notifications } : {}),\n ...(preferences?.ui !== undefined ? { uiPreferences: preferences.ui } : {}),\n ...(preferences?.privacy !== undefined ? { privacy: preferences.privacy } : {}),\n });\n }, [emit]);\n\n const primaryScopeInitiatorIds = useMemo<ExecutionContext_InitiatorIds | null>(() => {\n return ScopeUtilsService.buildInitiatorIds({\n userId: appScope.currentUserId,\n organizationId: appScope.currentOrganizationId,\n applicationId: appScope.currentApplicationId,\n anonymousUserId: appScope.currentAnonymousUserId,\n });\n }, [\n appScope.currentApplicationId,\n appScope.currentAnonymousUserId,\n appScope.currentOrganizationId,\n appScope.currentUserId,\n ]);\n\n /**\n * Extract and store user preferences from context\n * Stores preferences in state for other contexts to read and apply\n */\n const storePreferences = useCallback((\n preferences: PreferencesPayload,\n organizationPreferences?: OrganizationContext['preferences'] | null,\n ): void => {\n // Store privacy preferences in state\n if (preferences.privacy) {\n setPrivacy(preferences.privacy);\n }\n\n const currentOrganizationPreferences = organizationPreferences !== undefined\n ? organizationPreferences\n : currentOrganizationId\n ? organizations.find((organization) => organization._id === currentOrganizationId)?.preferences\n : undefined;\n\n // Emit preference change event to notify parent contexts\n emitPreferencesChanged(\n preferences,\n currentOrganizationPreferences,\n );\n }, [currentOrganizationId, emitPreferencesChanged, organizations]);\n\n /**\n * Compute effective permissions from user's app roles and organization roles\n * This is a basic implementation - can be enhanced based on role hierarchy\n */\n const computeEffectivePermissions = (\n userContext: UserContext,\n organizationsList: OrganizationContext[]\n ): EffectivePermissions | null => {\n // App-level permissions from user's app roles\n const appLevel = (userContext.appRoles || []) as string[];\n\n // Per-organization permissions from organization membership roles\n // Use new field name from relationship-based context\n const organizationsPermissions: Record<string, string[]> = {};\n const memberships = userContext.organizationMembers || [];\n\n for (const membership of memberships) {\n organizationsPermissions[membership.organizationId] = (membership.roles || []) as string[];\n }\n\n return {\n appLevel,\n organizations: organizationsPermissions,\n };\n };\n\n /**\n * Load organizations independently (can be called separately from authentication)\n */\n const loadOrganizations = useCallback(async (userContext: UserContext): Promise<{\n organizationsList: OrganizationContext[];\n selectedOrgId: string | null;\n }> => {\n const allMemberships = userContext.organizationMembers || [];\n\n // W7.3b: For one-off sessions, restrict to the scoped organization only\n const scopedOrgId = auth.sessionType === SessionType.ONE_OFF\n ? tokenStorage.getOrganizationId()\n : null;\n\n const memberships = scopedOrgId\n ? allMemberships.filter((m: any) => m.organizationId === scopedOrgId)\n : allMemberships;\n\n logDebug('Loading organizations', {\n userId: userContext._id,\n membershipCount: memberships.length,\n isOneOff: auth.sessionType === SessionType.ONE_OFF,\n });\n\n const organizationsList: OrganizationContext[] = [];\n\n if (memberships.length > 0) {\n const organizationsConfig = registry.resourceConfigurations[CoreResourceType.ORGANIZATIONS];\n if (!organizationsConfig) {\n logger.warn('ORGANIZATIONS resource not available');\n return { organizationsList, selectedOrgId: null };\n }\n\n // Shared with the route organization-access probe, which must address the same READ.\n const orgsReadOp = findDefaultApiReadOperation(organizationsConfig);\n\n if (!orgsReadOp) {\n logger.warn('ORGANIZATIONS READ operation not found');\n return { organizationsList, selectedOrgId: null };\n }\n\n const organizationsOperationPath = ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(orgsReadOp);\n\n /**\n * The tenant's preference record is fetched SEPARATELY, and that is a decision rather than an\n * omission (#563).\n *\n * `OrganizationContextSchema` declares `preferences`, and `doOperation<OrganizationContext>`\n * is a CAST — nothing validates the response against it — so the field read as available\n * while no producer existed: the ORGANIZATIONS **default** READ returns a plain\n * `Organization`, and the organisation's regional block therefore never reached\n * `I18nContext`. Every date and number in every generated application formatted at the\n * framework floor as a result.\n *\n * The rejected alternative was to switch this call to the ORGANIZATIONS **context** variant,\n * which does populate the child. Measured against the running stack on 2026-09-10, that\n * response carries every context-enabled child of an organisation — `auditLogs`, `todos`,\n * `tasks`, `knowledgeDocuments`, `organizationMembers`, … — so session restore would pull an\n * unbounded page of tenant data per membership to obtain four regional fields. (#583 has since\n * taken the audit and delivery logs off the context surface and capped every 1:many child at\n * `contextPolicy.limit`, 20 by default. The page is bounded now, but it is still a page of tenant\n * data per membership, so the reasoning stands.) The\n * preference record has its own default READ (`GET /organizations/{id}/organization-preference`,\n * reachable by an ordinary `ORG_MEMBER`), which is one small request with a stable shape.\n *\n * Best-effort by construction: a tenant whose preferences cannot be read still yields a\n * usable organisation, and `organizationPreferencesPayload(undefined)` then contributes\n * nothing to the i18n event rather than clearing the member's own settings.\n */\n const organizationPreferencesConfig = registry.resourceConfigurations[CoreResourceType.ORGANIZATION_PREFERENCES];\n const organizationPreferencesReadOp = findDefaultApiReadOperation(organizationPreferencesConfig);\n\n if (!organizationPreferencesReadOp) {\n logger.warn('ORGANIZATION_PREFERENCES READ operation not found — tenant regional defaults will not be applied');\n }\n\n const organizationPreferencesOperationPath = organizationPreferencesReadOp\n ? ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(organizationPreferencesReadOp)\n : null;\n\n const fetchOrganizationPreferences = async (\n organizationId: string,\n ): Promise<OrganizationContext['preferences'] | undefined> => {\n if (!organizationPreferencesOperationPath) return undefined;\n try {\n return await doOperation<NonNullable<OrganizationContext['preferences']>>(\n organizationPreferencesOperationPath,\n { contextualParameters: { organizationId } },\n ) ?? undefined;\n } catch (error) {\n logger.warn('Failed to fetch organization preferences', { organizationId, error });\n return undefined;\n }\n };\n\n const orgPromises = memberships.map(async (membership: any) => {\n try {\n const [org, preferences] = await Promise.all([\n doOperation<OrganizationContext>(\n organizationsOperationPath,\n { contextualParameters: { organizationId: membership.organizationId } }),\n fetchOrganizationPreferences(membership.organizationId),\n ]);\n\n if (!org) return null;\n // OMIT the key when the read failed rather than attaching `null`. The payload builder\n // reads the two differently: `undefined`/absent contributes nothing to the i18n event,\n // while `null` means \"the tenant has cleared its preferences\" and actively resets the\n // organisation half — which would silently downgrade a member to the framework floor\n // because one request failed.\n return preferences ? { ...org, preferences } : org;\n } catch (error) {\n logger.warn('Failed to fetch organization', { organizationId: membership.organizationId, error });\n return null;\n }\n });\n\n const orgResults = await Promise.all(orgPromises);\n organizationsList.push(...orgResults.filter((org): org is OrganizationContext => org !== null));\n }\n\n // Restore current organization selection\n const storedOrgId = tokenStorage.getOrganizationId();\n const selectedOrgId = storedOrgId && organizationsList.find(o => o._id === storedOrgId)\n ? storedOrgId\n : organizationsList[0]?._id || null;\n\n // Compute effective permissions from roles\n const computedPermissions = computeEffectivePermissions(userContext, organizationsList);\n\n setOrganizations(organizationsList);\n commitOrganizationScopeValue(selectedOrgId);\n setPermissions(computedPermissions);\n\n logDebug('Organizations loaded', { organizationCount: organizationsList.length, currentOrganizationId: selectedOrgId });\n return { organizationsList, selectedOrgId };\n }, [commitOrganizationScopeValue, doOperation, registry, tokenStorage, auth.sessionType]);\n\n /**\n * Restore regular user session\n */\n const restoreUserSession = useCallback(async (accessToken: string): Promise<boolean> => {\n logDebug('Restoring user session');\n\n // Check if USER_SELF is available\n const availableResources = Object.keys(registry.resourceConfigurations);\n const hasUserSelf = availableResources.includes(CoreResourceType.USER_SELF);\n\n if (!hasUserSelf) {\n logger.warn('USER_SELF resource not available for session restoration');\n return false;\n }\n\n // Get USER_SELF resource config\n const userSelfConfig = registry.resourceConfigurations[CoreResourceType.USER_SELF];\n\n const readOperation = findDefaultApiReadOperation(userSelfConfig);\n\n if (!readOperation) {\n logger.warn('USER_SELF READ operation not found');\n return false;\n }\n\n // Find context variant (auto-generated with relationship population)\n const readContextOp = userSelfConfig.operations.find((op: any) =>\n op.operationIdentifier === CoreResourceOperation.READ &&\n op.isBulkOperation !== true &&\n (\n op.variantType === ResourceOperationVariantType.API_CALL ||\n op.variantType === ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ) &&\n op.variantKey === OPERATION_VARIANT_KEY.CONTEXT\n );\n\n if (!readContextOp) {\n logger.warn('USER_SELF context variant not found');\n return false;\n }\n\n const initiatorInfo = readOperation.initiatorInfos?.[0];\n const requiresUserId = initiatorInfo?.parameters?.some((p: any) => p.fieldIdentifier === 'userId');\n\n const contextualParameters: Record<string, string> = {};\n\n if (requiresUserId && accessToken) {\n try {\n const payload = decodeJwtPayload<{ userId?: string }>(accessToken);\n if (payload.userId) {\n contextualParameters.userId = payload.userId;\n }\n } catch (e) {\n logDebug('Failed to decode JWT for userId extraction', { error: e });\n }\n }\n\n // Build operation path and fetch user context\n const contextPath = ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(readContextOp);\n const userContext = await doOperation<UserContext>(contextPath, { contextualParameters });\n\n if (!userContext) {\n logger.warn('Failed to fetch user context during session restoration');\n return false;\n }\n\n // Use new field name from relationship-based context\n const membershipsCount = (userContext.organizationMembers || []).length;\n logDebug('User context restored', { userId: userContext._id, organizationCount: membershipsCount });\n\n // Update user state\n setUser(userContext);\n\n // Load organizations separately\n // If this fails, session restoration still succeeds (user context is restored)\n const { organizationsList, selectedOrgId } = await loadOrganizations(userContext);\n\n // Store preferences after organization loading so i18n receives user and\n // active-organization language policy in the same event.\n const preferences = userContext.userSelfPreferences;\n if (preferences) {\n const currentOrganization = selectedOrgId\n ? organizationsList.find((organization) => organization._id === selectedOrgId)\n : null;\n storePreferences(preferences, currentOrganization?.preferences);\n }\n\n logger.info('Session restored successfully', {\n userId: userContext._id,\n organizationCount: membershipsCount\n });\n\n return true;\n }, [doOperation, registry, loadOrganizations, storePreferences]);\n\n // Stop any pending restore-retry backoff when the provider unmounts, so the\n // loop in `restoreSession` bails instead of calling setState on a dead tree.\n useEffect(() => {\n restoreAbortRef.current = false;\n return () => {\n restoreAbortRef.current = true;\n if (restoreRetryTimerRef.current) {\n clearTimeout(restoreRetryTimerRef.current);\n restoreRetryTimerRef.current = null;\n }\n };\n }, []);\n\n /**\n * Restore session from stored JWT token\n * Fetches user context using USER_SELF resource (userId comes from JWT)\n * Then fetches full organization details for each organization membership\n *\n * Resilience: a TRANSIENT backend failure (unreachable / 5xx / timeout, or a\n * 401 whose in-flight renewal failed transiently) does NOT log out — restore\n * preserves the session and retries with capped exponential backoff until the\n * backend returns. Genuine authentication (401), authorization (403), and\n * non-network errors terminate immediately (no retry on a dead-or-buggy path).\n */\n const restoreSession = useCallback(async (): Promise<boolean> => {\n logDebug('Restoring session from stored token');\n\n // Check if session is already restored to avoid duplicate restoration attempts\n if (auth.sessionRestored && auth.accessToken && user) {\n logDebug('Session already restored, skipping restoration');\n return true;\n }\n\n // Read token from auth state\n const accessToken = auth.accessToken;\n\n if (!accessToken) {\n logDebug('No access token available');\n return false;\n }\n\n setSessionRestoring(true);\n\n let attempt = 0;\n // Single backoff loop: the invoking effect won't re-enter while\n // `isRestoringSession` is true, so this is the sole restore in flight.\n while (true) {\n try {\n const restored = await restoreUserSession(accessToken);\n\n if (restored) {\n markSessionRestored();\n\n // W7.3b: One-off sessions already connected WebSocket in handleOneOffTokenExchange\n // (with consumableToken). Reconnecting here would lose the consumable token.\n if (auth.sessionType !== SessionType.ONE_OFF) {\n // Connect with the FRESHEST token, read live from storage — NOT the\n // `accessToken` captured at the top of `restoreSession`. During the\n // awaited `restoreUserSession` above, the HTTP interceptor may have\n // hit a `401 OUTDATED_AUTH_JWT` and rotated the token via\n // `tokenRenewalHandler` (which writes the new token to storage AND\n // seeds the WS `authStateRef` synchronously). The captured\n // `accessToken` is then stale/expired; passing it into `connect()`\n // reseeds the WS credential source-of-truth back to the expired token\n // (clobbering the fresh one the refresh just stored), and the Socket.IO\n // handshake gets rejected with \"Authentication failed\". `getAccessToken()`\n // returns the live, post-refresh value (falling back to the captured\n // token only if storage is somehow empty).\n const freshestAccessToken = tokenStorage.getAccessToken() ?? accessToken;\n connectWebSocket(freshestAccessToken, tokenStorage.getOrganizationId());\n }\n } else {\n logger.warn('Session restoration could not build a valid authenticated context; logging out to avoid a half-restored state');\n authLogout();\n }\n\n return restored;\n\n } catch (error: any) {\n // Authorization (403 / scope) is checked FIRST and is non-destructive: a\n // permission denial must NEVER destroy a valid session. Authentication\n // (401 / session-invalid) is the only branch that force-logs-out.\n // `isAuthenticationError` already excludes authorization errors (see\n // `AuthSessionUtils`), so these are mutually exclusive — the explicit\n // ordering here is defense-in-depth so the non-destructive path wins even\n // if that guard is ever loosened.\n const isAuthorizationError = AuthSessionUtils.isAuthorizationError(error);\n\n if (isAuthorizationError) {\n const errorMessage = error?.message || 'Session restoration blocked by authorization';\n logger.warn('Session restoration encountered authorization/scope error', {\n error: errorMessage,\n errorType: error?.wildoError?.type || error?.response?.data?.error?.type,\n status: error?.response?.status,\n });\n setSessionRestoring(false);\n markSessionRestored();\n return false;\n }\n\n // TRANSIENT backend failure (checked BEFORE the authentication branch so\n // a 401 whose renewal failed transiently is retried, not logged out):\n // preserve the session, back off, and retry. Bail if the component\n // unmounted or the session was cleared (logout elsewhere) while waiting.\n if (isTransientBackendFailure(error)) {\n attempt += 1;\n const delay = Math.min(\n RESTORE_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1),\n RESTORE_RETRY_MAX_DELAY_MS,\n );\n logger.warn('Session restoration hit a transient backend failure; preserving session and retrying', {\n attempt,\n retryInMs: delay,\n status: error?.response?.status,\n code: error?.code,\n });\n await new Promise<void>((resolve) => {\n restoreRetryTimerRef.current = setTimeout(resolve, delay);\n });\n if (restoreAbortRef.current || !tokenStorage.getAccessToken()) {\n setSessionRestoring(false);\n return false;\n }\n continue;\n }\n\n if (AuthSessionUtils.isAuthenticationError(error)) {\n logDebug('Session restoration failed due to authentication error', {\n errorType: error?.wildoError?.type || error?.response?.data?.error?.type,\n status: error?.response?.status,\n });\n authLogout();\n return false;\n }\n\n // Fail closed on unexpected NON-transient errors. A partially restored\n // authenticated shell is less safe than dropping back to a clean login.\n const errorMessage = error?.message || 'Session restoration failed';\n logger.warn('Session restoration encountered a non-transient error; logging out', {\n error: errorMessage,\n errorType: error?.wildoError?.type,\n });\n\n authLogout();\n return false;\n }\n }\n }, [\n restoreUserSession,\n auth.sessionRestored,\n auth.sessionType,\n auth.accessToken,\n user,\n authLogout,\n markSessionRestored,\n setSessionRestoring,\n connectWebSocket,\n tokenStorage\n ]);\n\n /**\n * Refresh organizations data (e.g., after organization update)\n */\n const refreshOrganizations = useCallback(async (): Promise<void> => {\n // Use new field name from relationship-based context\n const memberships = user?.organizationMembers || [];\n\n if (memberships.length === 0) {\n logDebug('No organizations membership to refresh');\n return;\n }\n\n logDebug('Refreshing organizations', { membershipCount: memberships.length });\n\n // Use loadOrganizations to refresh\n await loadOrganizations(user!);\n }, [user, loadOrganizations]);\n\n useEffect(() => {\n if (!user?.userSelfPreferences) {\n return;\n }\n\n const currentOrganization = currentOrganizationId\n ? organizations.find((organization) => organization._id === currentOrganizationId)\n : null;\n\n emitPreferencesChanged(\n user.userSelfPreferences,\n currentOrganization?.preferences,\n );\n }, [currentOrganizationId, emitPreferencesChanged, organizations, user]);\n\n /**\n * Set the current active organization\n */\n const setCurrentOrganization = useCallback((organizationId: string): void => {\n // Validate that organization exists in user's organizations\n const org = organizations.find(o => o._id === organizationId);\n if (!org) {\n logger.warn('Attempted to set invalid organization', { organizationId, availableOrganizations: organizations.map(o => o._id) });\n return;\n }\n\n const previousOrganizationId = currentOrganizationId;\n\n // Skip if the organization hasn't changed\n if (previousOrganizationId === organizationId) {\n return;\n }\n\n logDebug('Setting current organization', { organizationId, organizationName: org.name, previousOrganizationId });\n commitOrganizationScopeValue(organizationId);\n }, [organizations, currentOrganizationId, commitOrganizationScopeValue]);\n\n /**\n * Get the current active organization\n */\n const getCurrentOrganization = useCallback((): OrganizationContext | null => {\n if (!currentOrganizationId) {\n return null;\n }\n return organizations.find(o => o._id === currentOrganizationId) || null;\n }, [currentOrganizationId, organizations]);\n\n /**\n * Get privacy preferences\n */\n const getPrivacy = useCallback((): UserPrivacy | null => {\n return privacy;\n }, [privacy]);\n\n // Depend on the builder alone: the whole AppScope value changes with every custom scope value, and through\n // this callback it would re-render every `useUserOrgs` consumer.\n const buildScopeContextualParameters = appScope.buildContextualParameters;\n const recordConsentDecision = useCallback(async (grantedPurposes: readonly ConsentPurpose[]): Promise<UserPrivacy> => {\n const operation = registry.resourceConfigurations[CoreResourceType.USER_SELF_PREFERENCES]?.operations.find(\n (candidate) => candidate.operationIdentifier === CoreResourceOperation.UPDATE\n && candidate.isOperationDefault === true\n && candidate.isBulkOperation !== true\n && (\n candidate.variantType === ResourceOperationVariantType.API_CALL\n || candidate.variantType === ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ),\n );\n if (!operation) {\n throw new Error('Cannot record a consent decision: this application mounts no user self-preferences UPDATE operation');\n }\n\n const updated = await doOperation<UserPreferences>(\n ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(operation),\n {\n // This provider sits ABOVE `ScopedResourceRegistryProvider`, so the `doOperation` it holds injects\n // no scope: the user id the self-preferences route is addressed by has to be supplied here. With an\n // empty set the client could not build the URL and every decision failed before a request left\n // (`frontend_resource_no_endpoint_available`, #977 — found by driving the prompt in a browser).\n contextualParameters: buildScopeContextualParameters(),\n requestData: {\n // The client instant is only a CLAIM that this write is a decision; the server replaces it.\n privacy: { consentedPurposes: normalizeConsentPurposes(grantedPurposes), consentDecidedAt: new Date() },\n },\n },\n );\n const storedPrivacy = updated?.privacy;\n if (!storedPrivacy) {\n throw new Error('Consent decision was written but the response carried no privacy block');\n }\n\n setPrivacy(storedPrivacy);\n // Updating the user's preferences record re-emits USER_PREFERENCES_CHANGED through the effect\n // above, which is how the analytics provider learns the new set without a second channel.\n setUser((previous) => previous\n ? { ...previous, userSelfPreferences: { ...(previous.userSelfPreferences ?? {}), privacy: storedPrivacy } as UserContext['userSelfPreferences'] }\n : previous);\n // While a required purpose was missing the backend refused this person's organization reads, so\n // session restore may have loaded none (#534 re-review N1). Re-load them now that the decision is\n // stored; a failure leaves the decision recorded and is retried on the next restore.\n if (organizations.length === 0) {\n await refreshOrganizations().catch((error: unknown) => {\n logger.warn('Organizations could not be re-loaded after a consent decision', { error });\n });\n }\n return storedPrivacy;\n }, [buildScopeContextualParameters, doOperation, registry, organizations.length, refreshOrganizations]);\n\n /**\n * Logout wrapper that also clears user/org data\n */\n const logout = useCallback((): void => {\n logDebug('Logging out user', { userId: user?._id, organizationId: currentOrganizationId });\n\n // Clear user/org data first\n setUser(null);\n setOrganizations([]);\n commitOrganizationScopeValue(null);\n setPermissions(null);\n setPrivacy(null);\n emitPreferencesChanged(null);\n\n // Reset initialization flag\n hasInitializedRef.current = false;\n previousTokenRef.current = null;\n\n // Call auth logout (clears tokens, disconnects WebSocket)\n authLogout();\n }, [user?._id, currentOrganizationId, authLogout, commitOrganizationScopeValue, emitPreferencesChanged]);\n\n // Auto-load user/org data when token becomes available\n useEffect(() => {\n const accessToken = auth.accessToken;\n\n // Skip if no token or token hasn't changed\n if (!accessToken || accessToken === previousTokenRef.current) {\n return;\n }\n\n // Skip if session is already restored with this token\n if (auth.sessionRestored && user) {\n previousTokenRef.current = accessToken;\n return;\n }\n\n // Skip if already initializing\n if (hasInitializedRef.current && auth.isRestoringSession) {\n return;\n }\n\n logDebug('Token changed, initiating session restoration', {\n hasToken: !!accessToken,\n previousToken: !!previousTokenRef.current\n });\n\n previousTokenRef.current = accessToken;\n hasInitializedRef.current = true;\n\n // Restore session (will fetch user/org data)\n restoreSession().catch((error) => {\n logger.error('Session restoration failed', { error });\n });\n }, [auth.accessToken, auth.sessionRestored, auth.isRestoringSession, user, restoreSession]);\n\n // Clear data when token is removed (logged out)\n useEffect(() => {\n if (!auth.accessToken && previousTokenRef.current) {\n logDebug('Token removed, clearing user/org data');\n setUser(null);\n setOrganizations([]);\n commitOrganizationScopeValue(null);\n setPermissions(null);\n setPrivacy(null);\n emitPreferencesChanged(null);\n previousTokenRef.current = null;\n hasInitializedRef.current = false;\n }\n }, [auth.accessToken, commitOrganizationScopeValue, emitPreferencesChanged]);\n\n const value = useMemo<UserOrgsContextType>(() => ({\n // Re-exported from AuthSession for backward compatibility\n auth,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout,\n restoreSession,\n\n // OAuth2 + cross-frontend-handoff methods (delegated from AuthSession)\n initiateOAuth2Login,\n handleAuthCodeExchange,\n\n // User data\n user,\n\n // Organization data\n organizations,\n currentOrganizationId,\n permissions,\n primaryScopeInitiatorIds,\n\n // Privacy (only preference managed here)\n privacy,\n\n // Organization management\n setCurrentOrganization,\n getCurrentOrganization,\n refreshOrganizations,\n\n // Privacy getter\n getPrivacy,\n recordConsentDecision,\n }), [\n auth,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout,\n restoreSession,\n initiateOAuth2Login,\n handleAuthCodeExchange,\n user,\n organizations,\n currentOrganizationId,\n permissions,\n primaryScopeInitiatorIds,\n privacy,\n setCurrentOrganization,\n getCurrentOrganization,\n refreshOrganizations,\n getPrivacy,\n recordConsentDecision,\n ]);\n\n return <UserOrgsContext.Provider value={value}>{children}</UserOrgsContext.Provider>;\n};\n\n// useUserOrgs hook is now in separate file: ./useUserOrgs.ts\n// This separation is required for React Fast Refresh compatibility\n"]}
|
|
1
|
+
{"version":3,"file":"UserOrgsContext.js","sourceRoot":"","sources":["../../../../../src/core/security/UserOrgsContext.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { createContext, useState, ReactNode, useMemo, useEffect, useCallback, useRef } from 'react';\nimport {\n UserContext,\n OrganizationContext,\n CoreResourceType,\n ResourcesConfig_OperationPathUtils,\n CoreResourceOperation,\n ResourceOperationVariantType,\n OPERATION_VARIANT_KEY,\n ExecutionContext_InitiatorIds,\n UserPrivacy,\n UserPreferences,\n SessionType,\n normalizeConsentPurposes,\n type ConsentPurpose,\n} from '@wildo-ai/saas-models';\nimport { useResourceRegistry } from '~wildo-frontend-lib/core/resources/useResourceRegistry';\nimport { LoggerFrontendService } from '~wildo-frontend-lib/core/monitoring/logger.frontend.service';\nimport { useEventBus } from '~wildo-frontend-lib/core/events/useEventBus';\nimport { FrontendEvents, SessionEndReason } from '~wildo-frontend-lib/core/events/events.frontend.schemas';\nimport {\n EffectivePermissions,\n} from './security.frontend.schemas';\nimport { useAuthSession } from './useAuthSession';\nimport { AuthSessionUtils } from './auth-session.utils';\nimport { isTransientBackendFailure } from '~wildo-frontend-lib/core/requests/auth-refresh-resilience.frontend';\nimport { decodeJwtPayload } from './jwt.frontend.utils';\nimport { useAppScope } from '~wildo-frontend-lib/core/scope/useAppScope';\nimport { useAppScopeInternal } from '~wildo-frontend-lib/core/scope/AppScopeContext';\nimport { ScopeUtilsService } from '~wildo-frontend-lib/core/scope/scope.utils.frontend.service';\nimport { findDefaultApiReadOperation } from './route-organization-access.frontend.utils';\n\nconst logger: LoggerFrontendService = LoggerFrontendService.getLogger();\nconst logDebug: (message: string, context?: Record<string, unknown>) => void = logger.debugByType('UserOrgsContext');\nlogger.setDebugTypeLogging('UserOrgsContext', false);\n\n/**\n * Session-restore retry backoff bounds (transient backend failures only).\n *\n * On RELOAD, a backend that is recompiling/restarting (dev) or briefly\n * unavailable (prod) makes the session-restore fetch fail transiently. Rather\n * than force a logout — which clears the shared `__wildo_refresh` cookie and\n * drops the user to the login screen — restore preserves the session and\n * retries with exponential backoff until the backend returns. Genuine auth/authz\n * and non-network errors do NOT retry (see `restoreSession`). Backoff caps so a\n * sustained outage settles at one attempt per {@link RESTORE_RETRY_MAX_DELAY_MS}.\n */\nconst RESTORE_RETRY_BASE_DELAY_MS = 1_000;\nconst RESTORE_RETRY_MAX_DELAY_MS = 30_000;\n\n/**\n * User Organizations Context\n * Manages user data, organizations, permissions, and preferences\n * Consumes AuthSessionContext for authentication state\n */\n\nexport interface UserOrgsContextType {\n // Re-exported from AuthSession for backward compatibility\n auth: ReturnType<typeof useAuthSession>['auth'];\n identifyByEmail: ReturnType<typeof useAuthSession>['identifyByEmail'];\n authenticateWithPassword: ReturnType<typeof useAuthSession>['authenticateWithPassword'];\n authenticate: ReturnType<typeof useAuthSession>['authenticate'];\n getSessionState: ReturnType<typeof useAuthSession>['getSessionState'];\n isAuthenticated: ReturnType<typeof useAuthSession>['isAuthenticated'];\n logout: () => void;\n restoreSession: () => Promise<boolean>;\n\n // OAuth2 + cross-frontend-handoff methods (delegated from AuthSession)\n initiateOAuth2Login: ReturnType<typeof useAuthSession>['initiateOAuth2Login'];\n handleAuthCodeExchange: ReturnType<typeof useAuthSession>['handleAuthCodeExchange'];\n\n // User data\n user: UserContext | null;\n\n // Organization data\n organizations: OrganizationContext[];\n currentOrganizationId: string | null;\n permissions: EffectivePermissions | null;\n primaryScopeInitiatorIds: ExecutionContext_InitiatorIds | null;\n\n // Privacy (only preference managed here, others are in their respective contexts)\n privacy: UserPrivacy | null;\n\n // Organization management\n setCurrentOrganization: (organizationId: string) => void;\n getCurrentOrganization: () => OrganizationContext | null;\n refreshOrganizations: () => Promise<void>;\n\n // Privacy getter\n getPrivacy: () => UserPrivacy | null;\n\n /**\n * Record the signed-in person's consent decision: exactly the purposes they granted (#534).\n *\n * The argument is the WHOLE granted set, never a delta — a purpose left out is a purpose not granted,\n * so an unticked box is a withdrawal rather than \"no change\". The write always carries a decision\n * claim, which is what lets \"grant nothing\" be recorded as a decision instead of reading as a person\n * who was never asked; the recorded instant is the server's (`buildConsentDecisionPatch`).\n *\n * Resolves with the stored privacy block once it is in state, so a caller gating on consent (the\n * consent gate) sees the new decision on the next render. Rejects when the application mounts no\n * self-preferences UPDATE door or the write fails — a consent surface must say it could not save,\n * never behave as though it had.\n */\n recordConsentDecision: (grantedPurposes: readonly ConsentPurpose[]) => Promise<UserPrivacy>;\n}\n\n/**\n * UserOrgs Context\n * Exported for use in separate hook file (Fast Refresh compatibility)\n * @internal - Use useUserOrgs() hook instead of accessing this directly\n */\nexport const UserOrgsContext: React.Context<UserOrgsContextType | undefined> = createContext<UserOrgsContextType | undefined>(undefined);\n\nexport const UserOrgsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {\n const { doOperation, registry } = useResourceRegistry();\n const { emit } = useEventBus();\n\n // Consume auth session context\n const authSession = useAuthSession();\n const {\n auth,\n tokenStorage,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout: authLogout,\n endSession,\n getSessionEstablishment,\n getSessionEndReason,\n initiateOAuth2Login,\n handleAuthCodeExchange,\n markSessionRestored,\n setSessionRestoring,\n connectWebSocket,\n } = authSession;\n const appScope = useAppScope();\n const { commitOrganizationScopeValue } = useAppScopeInternal();\n const currentOrganizationId = appScope.currentOrganizationId;\n\n const hasInitializedRef = useRef(false);\n const previousTokenRef = useRef<string | null>(null);\n // Restore-retry lifecycle: `restoreAbortRef` flips true on unmount so an\n // in-flight backoff loop bails instead of touching state on a dead component;\n // `restoreRetryTimerRef` holds the pending backoff timer for cleanup.\n const restoreAbortRef = useRef(false);\n const restoreRetryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const [user, setUser] = useState<UserContext | null>(null);\n\n const [organizations, setOrganizations] = useState<OrganizationContext[]>([]);\n\n const [permissions, setPermissions] = useState<{\n appLevel: string[];\n organizations: Record<string, string[]>;\n } | null>(null);\n\n const [privacy, setPrivacy] = useState<UserPrivacy | null>(null);\n\n type PreferencesPayload = Pick<UserPreferences, 'languagePreferences' | 'regional' | 'ui' | 'notifications' | 'privacy'>;\n\n /**\n * The TENANT's half of the payload, derived from its preferences record rather than passed\n * alongside it (#410).\n *\n * The organization contributes two things to `I18nContext` — its language policy and its regional\n * defaults — and they are forwarded together because they come from one record. An earlier shape\n * took the language block as its own argument, and when the regional half was added every call\n * site would have had to remember to forward a second one: three sites, one obligation each, and\n * a fourth site tomorrow that forwards neither. Passing the record makes forgetting impossible.\n */\n const organizationPreferencesPayload = (\n organizationPreferences: OrganizationContext['preferences'] | null | undefined,\n ): Record<string, unknown> => {\n if (organizationPreferences === undefined) {\n return {};\n }\n if (organizationPreferences === null) {\n return { organizationLanguagePreferences: null, organizationRegionalPreferences: null };\n }\n return {\n organizationLanguagePreferences: organizationPreferences.languagePreferences ?? null,\n organizationRegionalPreferences: {\n timezone: organizationPreferences.timezone,\n locale: organizationPreferences.locale,\n dateFormat: organizationPreferences.dateFormat,\n timeFormat: organizationPreferences.timeFormat,\n },\n };\n };\n\n const emitPreferencesChanged = useCallback((\n preferences: PreferencesPayload | null | undefined,\n organizationPreferences?: OrganizationContext['preferences'] | null,\n ): void => {\n if (preferences === null) {\n emit(FrontendEvents.USER_PREFERENCES_CHANGED, {\n languagePreferences: null,\n organizationLanguagePreferences: null,\n regionalPreferences: null,\n organizationRegionalPreferences: null,\n notificationsPreferences: null,\n uiPreferences: null,\n privacy: null,\n });\n return;\n }\n\n emit(FrontendEvents.USER_PREFERENCES_CHANGED, {\n ...(preferences?.languagePreferences !== undefined ? { languagePreferences: preferences.languagePreferences } : {}),\n ...organizationPreferencesPayload(organizationPreferences),\n ...(preferences?.regional !== undefined ? { regionalPreferences: preferences.regional } : {}),\n ...(preferences?.notifications !== undefined ? { notificationsPreferences: preferences.notifications } : {}),\n ...(preferences?.ui !== undefined ? { uiPreferences: preferences.ui } : {}),\n ...(preferences?.privacy !== undefined ? { privacy: preferences.privacy } : {}),\n });\n }, [emit]);\n\n /*\n * `USER_LOGIN` / `USER_LOGOUT` — announced HERE, once per transition of the known person (#1977).\n *\n * Nothing emitted them before, so every listener — error-report attribution, analytics identify and\n * reset, the sign-in and sign-out analytics events — was dead code that read as if sign-in were\n * observed. This is the one place every sign-in method and every way a session ends converge: each\n * authentication stores a token, the auto-load effect below restores the user from it, and every\n * sign-out, refused refresh, failed restore and cross-tab sign-out clears the token, which clears the\n * user. Emitting at each auth method instead would be a dozen call sites, and the next method added\n * would be the one that forgot. Declared BEFORE the preferences effect, because effects run in\n * declaration order and a person's arrival must precede their preferences.\n *\n * The id last announced is the guard, so a re-render, a preferences write that replaces the user\n * object, or StrictMode re-running an effect announces nothing, and a direct switch from one person to\n * another announces the first one's departure before the second one's arrival. HOW the session began\n * and WHY it ended are recorded by `AuthSessionProvider`, the only code that knows, and read at the\n * moment of announcing.\n *\n * A DEPARTURE is announced by the two places that clear the user, BEFORE they publish `privacy: null`:\n * a listener that must act while the person's consent still holds (the sign-out analytics event, sent\n * before the destinations are reset) needs the announcement first, and the consent-based providers\n * stop on the `privacy: null` that follows. The effect announces ARRIVALS, and a departure only as a\n * backstop for a path that cleared the user without announcing. An unmount announces nothing: the\n * provider going away is not the person signing out.\n */\n const announcedUserIdRef = useRef<string | null>(null);\n const announceDeparture = useCallback((reason: SessionEndReason): void => {\n const departedUserId = announcedUserIdRef.current;\n if (departedUserId === null) return;\n announcedUserIdRef.current = null;\n emit(FrontendEvents.USER_LOGOUT, { userId: departedUserId, reason });\n }, [emit]);\n const knownUserId = user?._id ?? null;\n useEffect(() => {\n const previousUserId = announcedUserIdRef.current;\n if (previousUserId === knownUserId) return;\n if (previousUserId !== null && knownUserId !== null) {\n /*\n * One person REPLACED by another with no sign-out between them. Believed unreachable today: a sign-in\n * while someone is loaded sets `isRestoringSession` with `hasInitializedRef` already true, so the\n * auto-load effect below skips it, and `restoreSession` returns early while a user is loaded. Handled\n * anyway, because the consequence of getting it wrong is the next person's analytics running under\n * the previous person's consent: the departure is followed by the same `privacy: null` a sign-out\n * publishes, BEFORE the arrival, so the next person is judged on their own preferences, which the\n * preferences effect below publishes after this one.\n */\n announceDeparture(SessionEndReason.REPLACED);\n setPrivacy(null);\n emitPreferencesChanged(null);\n } else if (previousUserId !== null) {\n announceDeparture(getSessionEndReason());\n }\n if (knownUserId !== null) {\n announcedUserIdRef.current = knownUserId;\n emit(FrontendEvents.USER_LOGIN, { userId: knownUserId, establishment: getSessionEstablishment() });\n }\n }, [knownUserId, emit, announceDeparture, emitPreferencesChanged, getSessionEndReason, getSessionEstablishment]);\n\n const primaryScopeInitiatorIds = useMemo<ExecutionContext_InitiatorIds | null>(() => {\n return ScopeUtilsService.buildInitiatorIds({\n userId: appScope.currentUserId,\n organizationId: appScope.currentOrganizationId,\n applicationId: appScope.currentApplicationId,\n anonymousUserId: appScope.currentAnonymousUserId,\n });\n }, [\n appScope.currentApplicationId,\n appScope.currentAnonymousUserId,\n appScope.currentOrganizationId,\n appScope.currentUserId,\n ]);\n\n /**\n * Extract and store user preferences from context\n * Stores preferences in state for other contexts to read and apply\n */\n const storePreferences = useCallback((\n preferences: PreferencesPayload,\n organizationPreferences?: OrganizationContext['preferences'] | null,\n ): void => {\n // Store privacy preferences in state\n if (preferences.privacy) {\n setPrivacy(preferences.privacy);\n }\n\n const currentOrganizationPreferences = organizationPreferences !== undefined\n ? organizationPreferences\n : currentOrganizationId\n ? organizations.find((organization) => organization._id === currentOrganizationId)?.preferences\n : undefined;\n\n // Emit preference change event to notify parent contexts\n emitPreferencesChanged(\n preferences,\n currentOrganizationPreferences,\n );\n }, [currentOrganizationId, emitPreferencesChanged, organizations]);\n\n /**\n * Compute effective permissions from user's app roles and organization roles\n * This is a basic implementation - can be enhanced based on role hierarchy\n */\n const computeEffectivePermissions = (\n userContext: UserContext,\n organizationsList: OrganizationContext[]\n ): EffectivePermissions | null => {\n // App-level permissions from user's app roles\n const appLevel = (userContext.appRoles || []) as string[];\n\n // Per-organization permissions from organization membership roles\n // Use new field name from relationship-based context\n const organizationsPermissions: Record<string, string[]> = {};\n const memberships = userContext.organizationMembers || [];\n\n for (const membership of memberships) {\n organizationsPermissions[membership.organizationId] = (membership.roles || []) as string[];\n }\n\n return {\n appLevel,\n organizations: organizationsPermissions,\n };\n };\n\n /**\n * Load organizations independently (can be called separately from authentication)\n */\n const loadOrganizations = useCallback(async (userContext: UserContext): Promise<{\n organizationsList: OrganizationContext[];\n selectedOrgId: string | null;\n }> => {\n const allMemberships = userContext.organizationMembers || [];\n\n // W7.3b: For one-off sessions, restrict to the scoped organization only\n const scopedOrgId = auth.sessionType === SessionType.ONE_OFF\n ? tokenStorage.getOrganizationId()\n : null;\n\n const memberships = scopedOrgId\n ? allMemberships.filter((m: any) => m.organizationId === scopedOrgId)\n : allMemberships;\n\n logDebug('Loading organizations', {\n userId: userContext._id,\n membershipCount: memberships.length,\n isOneOff: auth.sessionType === SessionType.ONE_OFF,\n });\n\n const organizationsList: OrganizationContext[] = [];\n\n if (memberships.length > 0) {\n const organizationsConfig = registry.resourceConfigurations[CoreResourceType.ORGANIZATIONS];\n if (!organizationsConfig) {\n logger.warn('ORGANIZATIONS resource not available');\n return { organizationsList, selectedOrgId: null };\n }\n\n // Shared with the route organization-access probe, which must address the same READ.\n const orgsReadOp = findDefaultApiReadOperation(organizationsConfig);\n\n if (!orgsReadOp) {\n logger.warn('ORGANIZATIONS READ operation not found');\n return { organizationsList, selectedOrgId: null };\n }\n\n const organizationsOperationPath = ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(orgsReadOp);\n\n /**\n * The tenant's preference record is fetched SEPARATELY, and that is a decision rather than an\n * omission (#563).\n *\n * `OrganizationContextSchema` declares `preferences`, and `doOperation<OrganizationContext>`\n * is a CAST — nothing validates the response against it — so the field read as available\n * while no producer existed: the ORGANIZATIONS **default** READ returns a plain\n * `Organization`, and the organisation's regional block therefore never reached\n * `I18nContext`. Every date and number in every generated application formatted at the\n * framework floor as a result.\n *\n * The rejected alternative was to switch this call to the ORGANIZATIONS **context** variant,\n * which does populate the child. Measured against the running stack on 2026-09-10, that\n * response carries every context-enabled child of an organisation — `auditLogs`, `todos`,\n * `tasks`, `knowledgeDocuments`, `organizationMembers`, … — so session restore would pull an\n * unbounded page of tenant data per membership to obtain four regional fields. (#583 has since\n * taken the audit and delivery logs off the context surface and capped every 1:many child at\n * `contextPolicy.limit`, 20 by default. The page is bounded now, but it is still a page of tenant\n * data per membership, so the reasoning stands.) The\n * preference record has its own default READ (`GET /organizations/{id}/organization-preference`,\n * reachable by an ordinary `ORG_MEMBER`), which is one small request with a stable shape.\n *\n * Best-effort by construction: a tenant whose preferences cannot be read still yields a\n * usable organisation, and `organizationPreferencesPayload(undefined)` then contributes\n * nothing to the i18n event rather than clearing the member's own settings.\n */\n const organizationPreferencesConfig = registry.resourceConfigurations[CoreResourceType.ORGANIZATION_PREFERENCES];\n const organizationPreferencesReadOp = findDefaultApiReadOperation(organizationPreferencesConfig);\n\n if (!organizationPreferencesReadOp) {\n logger.warn('ORGANIZATION_PREFERENCES READ operation not found — tenant regional defaults will not be applied');\n }\n\n const organizationPreferencesOperationPath = organizationPreferencesReadOp\n ? ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(organizationPreferencesReadOp)\n : null;\n\n const fetchOrganizationPreferences = async (\n organizationId: string,\n ): Promise<OrganizationContext['preferences'] | undefined> => {\n if (!organizationPreferencesOperationPath) return undefined;\n try {\n return await doOperation<NonNullable<OrganizationContext['preferences']>>(\n organizationPreferencesOperationPath,\n { contextualParameters: { organizationId } },\n ) ?? undefined;\n } catch (error) {\n logger.warn('Failed to fetch organization preferences', { organizationId, error });\n return undefined;\n }\n };\n\n const orgPromises = memberships.map(async (membership: any) => {\n try {\n const [org, preferences] = await Promise.all([\n doOperation<OrganizationContext>(\n organizationsOperationPath,\n { contextualParameters: { organizationId: membership.organizationId } }),\n fetchOrganizationPreferences(membership.organizationId),\n ]);\n\n if (!org) return null;\n // OMIT the key when the read failed rather than attaching `null`. The payload builder\n // reads the two differently: `undefined`/absent contributes nothing to the i18n event,\n // while `null` means \"the tenant has cleared its preferences\" and actively resets the\n // organisation half — which would silently downgrade a member to the framework floor\n // because one request failed.\n return preferences ? { ...org, preferences } : org;\n } catch (error) {\n logger.warn('Failed to fetch organization', { organizationId: membership.organizationId, error });\n return null;\n }\n });\n\n const orgResults = await Promise.all(orgPromises);\n organizationsList.push(...orgResults.filter((org): org is OrganizationContext => org !== null));\n }\n\n // Restore current organization selection\n const storedOrgId = tokenStorage.getOrganizationId();\n const selectedOrgId = storedOrgId && organizationsList.find(o => o._id === storedOrgId)\n ? storedOrgId\n : organizationsList[0]?._id || null;\n\n // Compute effective permissions from roles\n const computedPermissions = computeEffectivePermissions(userContext, organizationsList);\n\n setOrganizations(organizationsList);\n commitOrganizationScopeValue(selectedOrgId);\n setPermissions(computedPermissions);\n\n logDebug('Organizations loaded', { organizationCount: organizationsList.length, currentOrganizationId: selectedOrgId });\n return { organizationsList, selectedOrgId };\n }, [commitOrganizationScopeValue, doOperation, registry, tokenStorage, auth.sessionType]);\n\n /**\n * Restore regular user session\n */\n const restoreUserSession = useCallback(async (accessToken: string): Promise<boolean> => {\n logDebug('Restoring user session');\n\n // Check if USER_SELF is available\n const availableResources = Object.keys(registry.resourceConfigurations);\n const hasUserSelf = availableResources.includes(CoreResourceType.USER_SELF);\n\n if (!hasUserSelf) {\n logger.warn('USER_SELF resource not available for session restoration');\n return false;\n }\n\n // Get USER_SELF resource config\n const userSelfConfig = registry.resourceConfigurations[CoreResourceType.USER_SELF];\n\n const readOperation = findDefaultApiReadOperation(userSelfConfig);\n\n if (!readOperation) {\n logger.warn('USER_SELF READ operation not found');\n return false;\n }\n\n // Find context variant (auto-generated with relationship population)\n const readContextOp = userSelfConfig.operations.find((op: any) =>\n op.operationIdentifier === CoreResourceOperation.READ &&\n op.isBulkOperation !== true &&\n (\n op.variantType === ResourceOperationVariantType.API_CALL ||\n op.variantType === ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ) &&\n op.variantKey === OPERATION_VARIANT_KEY.CONTEXT\n );\n\n if (!readContextOp) {\n logger.warn('USER_SELF context variant not found');\n return false;\n }\n\n const initiatorInfo = readOperation.initiatorInfos?.[0];\n const requiresUserId = initiatorInfo?.parameters?.some((p: any) => p.fieldIdentifier === 'userId');\n\n const contextualParameters: Record<string, string> = {};\n\n if (requiresUserId && accessToken) {\n try {\n const payload = decodeJwtPayload<{ userId?: string }>(accessToken);\n if (payload.userId) {\n contextualParameters.userId = payload.userId;\n }\n } catch (e) {\n logDebug('Failed to decode JWT for userId extraction', { error: e });\n }\n }\n\n // Build operation path and fetch user context\n const contextPath = ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(readContextOp);\n const userContext = await doOperation<UserContext>(contextPath, { contextualParameters });\n\n if (!userContext) {\n logger.warn('Failed to fetch user context during session restoration');\n return false;\n }\n\n // Use new field name from relationship-based context\n const membershipsCount = (userContext.organizationMembers || []).length;\n logDebug('User context restored', { userId: userContext._id, organizationCount: membershipsCount });\n\n // Update user state\n setUser(userContext);\n\n // Load organizations separately\n // If this fails, session restoration still succeeds (user context is restored)\n const { organizationsList, selectedOrgId } = await loadOrganizations(userContext);\n\n // Store preferences after organization loading so i18n receives user and\n // active-organization language policy in the same event.\n const preferences = userContext.userSelfPreferences;\n if (preferences) {\n const currentOrganization = selectedOrgId\n ? organizationsList.find((organization) => organization._id === selectedOrgId)\n : null;\n storePreferences(preferences, currentOrganization?.preferences);\n }\n\n logger.info('Session restored successfully', {\n userId: userContext._id,\n organizationCount: membershipsCount\n });\n\n return true;\n }, [doOperation, registry, loadOrganizations, storePreferences]);\n\n // Stop any pending restore-retry backoff when the provider unmounts, so the\n // loop in `restoreSession` bails instead of calling setState on a dead tree.\n useEffect(() => {\n restoreAbortRef.current = false;\n return () => {\n restoreAbortRef.current = true;\n if (restoreRetryTimerRef.current) {\n clearTimeout(restoreRetryTimerRef.current);\n restoreRetryTimerRef.current = null;\n }\n };\n }, []);\n\n /**\n * Restore session from stored JWT token\n * Fetches user context using USER_SELF resource (userId comes from JWT)\n * Then fetches full organization details for each organization membership\n *\n * Resilience: a TRANSIENT backend failure (unreachable / 5xx / timeout, or a\n * 401 whose in-flight renewal failed transiently) does NOT log out — restore\n * preserves the session and retries with capped exponential backoff until the\n * backend returns. Genuine authentication (401), authorization (403), and\n * non-network errors terminate immediately (no retry on a dead-or-buggy path).\n */\n const restoreSession = useCallback(async (): Promise<boolean> => {\n logDebug('Restoring session from stored token');\n\n // Check if session is already restored to avoid duplicate restoration attempts\n if (auth.sessionRestored && auth.accessToken && user) {\n logDebug('Session already restored, skipping restoration');\n return true;\n }\n\n // Read token from auth state\n const accessToken = auth.accessToken;\n\n if (!accessToken) {\n logDebug('No access token available');\n return false;\n }\n\n setSessionRestoring(true);\n\n let attempt = 0;\n // Single backoff loop: the invoking effect won't re-enter while\n // `isRestoringSession` is true, so this is the sole restore in flight.\n while (true) {\n try {\n const restored = await restoreUserSession(accessToken);\n\n if (restored) {\n markSessionRestored();\n\n // W7.3b: One-off sessions already connected WebSocket in handleOneOffTokenExchange\n // (with consumableToken). Reconnecting here would lose the consumable token.\n if (auth.sessionType !== SessionType.ONE_OFF) {\n // Connect with the FRESHEST token, read live from storage — NOT the\n // `accessToken` captured at the top of `restoreSession`. During the\n // awaited `restoreUserSession` above, the HTTP interceptor may have\n // hit a `401 OUTDATED_AUTH_JWT` and rotated the token via\n // `tokenRenewalHandler` (which writes the new token to storage AND\n // seeds the WS `authStateRef` synchronously). The captured\n // `accessToken` is then stale/expired; passing it into `connect()`\n // reseeds the WS credential source-of-truth back to the expired token\n // (clobbering the fresh one the refresh just stored), and the Socket.IO\n // handshake gets rejected with \"Authentication failed\". `getAccessToken()`\n // returns the live, post-refresh value (falling back to the captured\n // token only if storage is somehow empty).\n const freshestAccessToken = tokenStorage.getAccessToken() ?? accessToken;\n connectWebSocket(freshestAccessToken, tokenStorage.getOrganizationId());\n }\n } else {\n logger.warn('Session restoration could not build a valid authenticated context; logging out to avoid a half-restored state');\n endSession(SessionEndReason.SESSION_ENDED);\n }\n\n return restored;\n\n } catch (error: any) {\n // Authorization (403 / scope) is checked FIRST and is non-destructive: a\n // permission denial must NEVER destroy a valid session. Authentication\n // (401 / session-invalid) is the only branch that force-logs-out.\n // `isAuthenticationError` already excludes authorization errors (see\n // `AuthSessionUtils`), so these are mutually exclusive — the explicit\n // ordering here is defense-in-depth so the non-destructive path wins even\n // if that guard is ever loosened.\n const isAuthorizationError = AuthSessionUtils.isAuthorizationError(error);\n\n if (isAuthorizationError) {\n const errorMessage = error?.message || 'Session restoration blocked by authorization';\n logger.warn('Session restoration encountered authorization/scope error', {\n error: errorMessage,\n errorType: error?.wildoError?.type || error?.response?.data?.error?.type,\n status: error?.response?.status,\n });\n setSessionRestoring(false);\n markSessionRestored();\n return false;\n }\n\n // TRANSIENT backend failure (checked BEFORE the authentication branch so\n // a 401 whose renewal failed transiently is retried, not logged out):\n // preserve the session, back off, and retry. Bail if the component\n // unmounted or the session was cleared (logout elsewhere) while waiting.\n if (isTransientBackendFailure(error)) {\n attempt += 1;\n const delay = Math.min(\n RESTORE_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1),\n RESTORE_RETRY_MAX_DELAY_MS,\n );\n logger.warn('Session restoration hit a transient backend failure; preserving session and retrying', {\n attempt,\n retryInMs: delay,\n status: error?.response?.status,\n code: error?.code,\n });\n await new Promise<void>((resolve) => {\n restoreRetryTimerRef.current = setTimeout(resolve, delay);\n });\n if (restoreAbortRef.current || !tokenStorage.getAccessToken()) {\n setSessionRestoring(false);\n return false;\n }\n continue;\n }\n\n if (AuthSessionUtils.isAuthenticationError(error)) {\n logDebug('Session restoration failed due to authentication error', {\n errorType: error?.wildoError?.type || error?.response?.data?.error?.type,\n status: error?.response?.status,\n });\n endSession(SessionEndReason.SESSION_ENDED);\n return false;\n }\n\n // Fail closed on unexpected NON-transient errors. A partially restored\n // authenticated shell is less safe than dropping back to a clean login.\n const errorMessage = error?.message || 'Session restoration failed';\n logger.warn('Session restoration encountered a non-transient error; logging out', {\n error: errorMessage,\n errorType: error?.wildoError?.type,\n });\n\n endSession(SessionEndReason.SESSION_ENDED);\n return false;\n }\n }\n }, [\n restoreUserSession,\n auth.sessionRestored,\n auth.sessionType,\n auth.accessToken,\n user,\n endSession,\n markSessionRestored,\n setSessionRestoring,\n connectWebSocket,\n tokenStorage\n ]);\n\n /**\n * Refresh organizations data (e.g., after organization update)\n */\n const refreshOrganizations = useCallback(async (): Promise<void> => {\n // Use new field name from relationship-based context\n const memberships = user?.organizationMembers || [];\n\n if (memberships.length === 0) {\n logDebug('No organizations membership to refresh');\n return;\n }\n\n logDebug('Refreshing organizations', { membershipCount: memberships.length });\n\n // Use loadOrganizations to refresh\n await loadOrganizations(user!);\n }, [user, loadOrganizations]);\n\n useEffect(() => {\n if (!user?.userSelfPreferences) {\n return;\n }\n\n const currentOrganization = currentOrganizationId\n ? organizations.find((organization) => organization._id === currentOrganizationId)\n : null;\n\n emitPreferencesChanged(\n user.userSelfPreferences,\n currentOrganization?.preferences,\n );\n }, [currentOrganizationId, emitPreferencesChanged, organizations, user]);\n\n /**\n * Set the current active organization\n */\n const setCurrentOrganization = useCallback((organizationId: string): void => {\n // Validate that organization exists in user's organizations\n const org = organizations.find(o => o._id === organizationId);\n if (!org) {\n logger.warn('Attempted to set invalid organization', { organizationId, availableOrganizations: organizations.map(o => o._id) });\n return;\n }\n\n const previousOrganizationId = currentOrganizationId;\n\n // Skip if the organization hasn't changed\n if (previousOrganizationId === organizationId) {\n return;\n }\n\n logDebug('Setting current organization', { organizationId, organizationName: org.name, previousOrganizationId });\n commitOrganizationScopeValue(organizationId);\n }, [organizations, currentOrganizationId, commitOrganizationScopeValue]);\n\n /**\n * Get the current active organization\n */\n const getCurrentOrganization = useCallback((): OrganizationContext | null => {\n if (!currentOrganizationId) {\n return null;\n }\n return organizations.find(o => o._id === currentOrganizationId) || null;\n }, [currentOrganizationId, organizations]);\n\n /**\n * Get privacy preferences\n */\n const getPrivacy = useCallback((): UserPrivacy | null => {\n return privacy;\n }, [privacy]);\n\n // Depend on the builder alone: the whole AppScope value changes with every custom scope value, and through\n // this callback it would re-render every `useUserOrgs` consumer.\n const buildScopeContextualParameters = appScope.buildContextualParameters;\n const recordConsentDecision = useCallback(async (grantedPurposes: readonly ConsentPurpose[]): Promise<UserPrivacy> => {\n const operation = registry.resourceConfigurations[CoreResourceType.USER_SELF_PREFERENCES]?.operations.find(\n (candidate) => candidate.operationIdentifier === CoreResourceOperation.UPDATE\n && candidate.isOperationDefault === true\n && candidate.isBulkOperation !== true\n && (\n candidate.variantType === ResourceOperationVariantType.API_CALL\n || candidate.variantType === ResourceOperationVariantType.API_CALL_WITH_CALLBACK\n ),\n );\n if (!operation) {\n throw new Error('Cannot record a consent decision: this application mounts no user self-preferences UPDATE operation');\n }\n\n const updated = await doOperation<UserPreferences>(\n ResourcesConfig_OperationPathUtils.buildOperationPathKeyFromOperation(operation),\n {\n // This provider sits ABOVE `ScopedResourceRegistryProvider`, so the `doOperation` it holds injects\n // no scope: the user id the self-preferences route is addressed by has to be supplied here. With an\n // empty set the client could not build the URL and every decision failed before a request left\n // (`frontend_resource_no_endpoint_available`, #977 — found by driving the prompt in a browser).\n contextualParameters: buildScopeContextualParameters(),\n requestData: {\n // The client instant is only a CLAIM that this write is a decision; the server replaces it.\n privacy: { consentedPurposes: normalizeConsentPurposes(grantedPurposes), consentDecidedAt: new Date() },\n },\n },\n );\n const storedPrivacy = updated?.privacy;\n if (!storedPrivacy) {\n throw new Error('Consent decision was written but the response carried no privacy block');\n }\n\n setPrivacy(storedPrivacy);\n // Updating the user's preferences record re-emits USER_PREFERENCES_CHANGED through the effect\n // above, which is how the analytics provider learns the new set without a second channel.\n setUser((previous) => previous\n ? { ...previous, userSelfPreferences: { ...(previous.userSelfPreferences ?? {}), privacy: storedPrivacy } as UserContext['userSelfPreferences'] }\n : previous);\n // While a required purpose was missing the backend refused this person's organization reads, so\n // session restore may have loaded none (#534 re-review N1). Re-load them now that the decision is\n // stored; a failure leaves the decision recorded and is retried on the next restore.\n if (organizations.length === 0) {\n await refreshOrganizations().catch((error: unknown) => {\n logger.warn('Organizations could not be re-loaded after a consent decision', { error });\n });\n }\n return storedPrivacy;\n }, [buildScopeContextualParameters, doOperation, registry, organizations.length, refreshOrganizations]);\n\n /**\n * Logout wrapper that also clears user/org data\n */\n const logout = useCallback((): void => {\n logDebug('Logging out user', { userId: user?._id, organizationId: currentOrganizationId });\n\n // Announced first, while the person's consent still holds — see the block above (#1977).\n announceDeparture(SessionEndReason.SIGNED_OUT);\n\n // Clear user/org data first\n setUser(null);\n setOrganizations([]);\n commitOrganizationScopeValue(null);\n setPermissions(null);\n setPrivacy(null);\n emitPreferencesChanged(null);\n\n // Reset initialization flag\n hasInitializedRef.current = false;\n previousTokenRef.current = null;\n\n // Call auth logout (clears tokens, disconnects WebSocket)\n authLogout();\n }, [user?._id, currentOrganizationId, authLogout, announceDeparture, commitOrganizationScopeValue, emitPreferencesChanged]);\n\n // Auto-load user/org data when token becomes available\n useEffect(() => {\n const accessToken = auth.accessToken;\n\n // Skip if no token or token hasn't changed\n if (!accessToken || accessToken === previousTokenRef.current) {\n return;\n }\n\n // Skip if session is already restored with this token\n if (auth.sessionRestored && user) {\n previousTokenRef.current = accessToken;\n return;\n }\n\n // Skip if already initializing\n if (hasInitializedRef.current && auth.isRestoringSession) {\n return;\n }\n\n logDebug('Token changed, initiating session restoration', {\n hasToken: !!accessToken,\n previousToken: !!previousTokenRef.current\n });\n\n previousTokenRef.current = accessToken;\n hasInitializedRef.current = true;\n\n // Restore session (will fetch user/org data)\n restoreSession().catch((error) => {\n logger.error('Session restoration failed', { error });\n });\n }, [auth.accessToken, auth.sessionRestored, auth.isRestoringSession, user, restoreSession]);\n\n // Clear data when token is removed (logged out)\n useEffect(() => {\n if (!auth.accessToken && previousTokenRef.current) {\n logDebug('Token removed, clearing user/org data');\n // Announced before `privacy: null`, with the reason the auth session recorded (#1977).\n announceDeparture(getSessionEndReason());\n setUser(null);\n setOrganizations([]);\n commitOrganizationScopeValue(null);\n setPermissions(null);\n setPrivacy(null);\n emitPreferencesChanged(null);\n previousTokenRef.current = null;\n hasInitializedRef.current = false;\n }\n }, [auth.accessToken, announceDeparture, commitOrganizationScopeValue, emitPreferencesChanged, getSessionEndReason]);\n\n const value = useMemo<UserOrgsContextType>(() => ({\n // Re-exported from AuthSession for backward compatibility\n auth,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout,\n restoreSession,\n\n // OAuth2 + cross-frontend-handoff methods (delegated from AuthSession)\n initiateOAuth2Login,\n handleAuthCodeExchange,\n\n // User data\n user,\n\n // Organization data\n organizations,\n currentOrganizationId,\n permissions,\n primaryScopeInitiatorIds,\n\n // Privacy (only preference managed here)\n privacy,\n\n // Organization management\n setCurrentOrganization,\n getCurrentOrganization,\n refreshOrganizations,\n\n // Privacy getter\n getPrivacy,\n recordConsentDecision,\n }), [\n auth,\n identifyByEmail,\n authenticateWithPassword,\n authenticate,\n getSessionState,\n isAuthenticated,\n logout,\n restoreSession,\n initiateOAuth2Login,\n handleAuthCodeExchange,\n user,\n organizations,\n currentOrganizationId,\n permissions,\n primaryScopeInitiatorIds,\n privacy,\n setCurrentOrganization,\n getCurrentOrganization,\n refreshOrganizations,\n getPrivacy,\n recordConsentDecision,\n ]);\n\n return <UserOrgsContext.Provider value={value}>{children}</UserOrgsContext.Provider>;\n};\n\n// useUserOrgs hook is now in separate file: ./useUserOrgs.ts\n// This separation is required for React Fast Refresh compatibility\n"]}
|