@datalayer/core 1.1.60 → 1.2.10
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/README.md +41 -18
- package/lib/api/DatalayerApi.d.ts +42 -1
- package/lib/api/DatalayerApi.js +90 -3
- package/lib/api/constants.d.ts +19 -1
- package/lib/api/constants.js +19 -1
- package/lib/api/contents/attachments.d.ts +9 -0
- package/lib/api/contents/attachments.js +39 -0
- package/lib/api/contents/bridges.d.ts +22 -0
- package/lib/api/contents/bridges.js +79 -0
- package/lib/api/contents/capabilities.d.ts +11 -0
- package/lib/api/contents/capabilities.js +21 -0
- package/lib/api/contents/cloudStorage.d.ts +31 -0
- package/lib/api/contents/cloudStorage.js +89 -0
- package/lib/api/contents/dataservers.d.ts +37 -0
- package/lib/api/contents/dataservers.js +121 -0
- package/lib/api/contents/datasets.d.ts +63 -0
- package/lib/api/contents/datasets.js +82 -0
- package/lib/api/contents/datasources.d.ts +70 -0
- package/lib/api/contents/datasources.js +149 -0
- package/lib/api/contents/generated.d.ts +1070 -0
- package/lib/api/contents/index.d.ts +16 -0
- package/lib/api/contents/index.js +20 -0
- package/lib/api/contents/mcp.d.ts +46 -0
- package/lib/api/contents/mcp.js +157 -0
- package/lib/api/contents/objects.d.ts +31 -0
- package/lib/api/contents/objects.js +88 -0
- package/lib/api/contents/operations.d.ts +3 -0
- package/lib/api/contents/operations.js +19 -0
- package/lib/api/contents/runtimeMounts.d.ts +40 -0
- package/lib/api/contents/runtimeMounts.js +59 -0
- package/lib/api/contents/sandboxUid.d.ts +21 -0
- package/lib/api/contents/sandboxUid.js +27 -0
- package/lib/api/contents/sources.d.ts +19 -0
- package/lib/api/contents/sources.js +119 -0
- package/lib/api/contents/sync.d.ts +18 -0
- package/lib/api/contents/sync.js +69 -0
- package/lib/api/contents/transfers.d.ts +38 -0
- package/lib/api/contents/transfers.js +123 -0
- package/lib/api/evals/client.d.ts +402 -0
- package/lib/api/evals/client.js +359 -0
- package/lib/api/evals/index.d.ts +10 -0
- package/lib/api/evals/index.js +18 -0
- package/lib/api/evals/request.d.ts +43 -0
- package/lib/api/evals/request.js +67 -0
- package/lib/api/evals/status.d.ts +27 -0
- package/lib/api/evals/status.js +122 -0
- package/lib/api/evals/types.d.ts +1335 -0
- package/lib/api/evals/types.js +5 -0
- package/lib/api/iam/connectedAgents.d.ts +68 -0
- package/lib/api/iam/connectedAgents.js +87 -0
- package/lib/api/iam/identityProviders.d.ts +76 -0
- package/lib/api/iam/identityProviders.js +187 -0
- package/lib/api/iam/index.d.ts +3 -1
- package/lib/api/iam/index.js +3 -1
- package/lib/api/iam/mcpAlertRules.d.ts +51 -0
- package/lib/api/iam/mcpAlertRules.js +198 -0
- package/lib/api/iam/mcpAuditSettings.d.ts +46 -0
- package/lib/api/iam/mcpAuditSettings.js +120 -0
- package/lib/api/iam/mcpPolicy.d.ts +181 -0
- package/lib/api/iam/mcpPolicy.js +168 -0
- package/lib/api/iam/organizationTeams.d.ts +13 -0
- package/lib/api/iam/organizationTeams.js +43 -0
- package/lib/api/iam/profile.d.ts +17 -1
- package/lib/api/iam/profile.js +27 -0
- package/lib/api/iam/scimTokens.d.ts +79 -0
- package/lib/api/iam/scimTokens.js +141 -0
- package/lib/api/iam/secrets.js +9 -21
- package/lib/api/iam/serviceAgents.d.ts +68 -0
- package/lib/api/iam/serviceAgents.js +119 -0
- package/lib/api/iam/trials.d.ts +38 -0
- package/lib/api/iam/trials.js +66 -0
- package/lib/api/index.d.ts +8 -1
- package/lib/api/index.js +7 -1
- package/lib/api/mcp/activity.d.ts +37 -0
- package/lib/api/mcp/activity.js +26 -0
- package/lib/api/mcp/alerts.d.ts +25 -0
- package/lib/api/mcp/alerts.js +51 -0
- package/lib/api/mcp/audit.d.ts +29 -0
- package/lib/api/mcp/audit.js +55 -0
- package/lib/api/mcp/bindings.d.ts +18 -0
- package/lib/api/mcp/bindings.js +42 -0
- package/lib/api/mcp/forwarding.d.ts +25 -0
- package/lib/api/mcp/forwarding.js +46 -0
- package/lib/api/mcp/gateway.d.ts +16 -0
- package/lib/api/mcp/gateway.js +70 -0
- package/lib/api/mcp/generated.d.ts +22 -0
- package/lib/api/mcp/generated.js +213 -0
- package/lib/api/mcp/index.d.ts +17 -0
- package/lib/api/mcp/index.js +25 -0
- package/lib/api/mcp/observability.d.ts +141 -0
- package/lib/api/mcp/observability.js +267 -0
- package/lib/api/mcp/operations.d.ts +83 -0
- package/lib/api/mcp/operations.js +50 -0
- package/lib/api/mcp/organizations.d.ts +102 -0
- package/lib/api/mcp/organizations.js +46 -0
- package/lib/api/mcp/policy.d.ts +9 -0
- package/lib/api/mcp/policy.js +23 -0
- package/lib/api/mcp/tasks.d.ts +49 -0
- package/lib/api/mcp/tasks.js +147 -0
- package/lib/api/orchestration/client.d.ts +53 -0
- package/lib/api/orchestration/client.js +105 -0
- package/lib/api/orchestration/events.d.ts +88 -0
- package/lib/api/orchestration/events.js +245 -0
- package/lib/api/orchestration/generated.d.ts +693 -0
- package/lib/api/orchestration/generated.js +687 -0
- package/lib/api/orchestration/index.d.ts +30 -0
- package/lib/api/orchestration/index.js +34 -0
- package/lib/api/orchestration/lifecycle.d.ts +39 -0
- package/lib/api/orchestration/lifecycle.js +57 -0
- package/lib/api/orchestration/measures.d.ts +55 -0
- package/lib/api/orchestration/measures.js +99 -0
- package/lib/api/otel/dashboards.d.ts +56 -0
- package/lib/api/otel/dashboards.js +50 -0
- package/lib/api/otel/index.d.ts +1 -0
- package/lib/api/otel/index.js +1 -0
- package/lib/api/otel/metrics.d.ts +16 -0
- package/lib/api/otel/metrics.js +15 -0
- package/lib/api/scheduler/client.d.ts +32 -0
- package/lib/api/scheduler/client.js +42 -0
- package/lib/api/scheduler/index.d.ts +8 -0
- package/lib/api/scheduler/index.js +16 -0
- package/lib/api/scheduler/request.d.ts +28 -0
- package/lib/api/scheduler/request.js +50 -0
- package/lib/api/scheduler/types.d.ts +88 -0
- package/lib/api/scheduler/types.js +5 -0
- package/lib/api/spacer/comments.d.ts +97 -0
- package/lib/api/spacer/comments.js +45 -0
- package/lib/api/spacer/index.d.ts +9 -0
- package/lib/api/spacer/index.js +17 -0
- package/lib/api/spacer/notebooks.d.ts +33 -0
- package/lib/api/spacer/notebooks.js +39 -0
- package/lib/api/spacer/request.d.ts +25 -0
- package/lib/api/spacer/request.js +46 -0
- package/lib/api/spacer/spaces.d.ts +68 -0
- package/lib/api/spacer/spaces.js +45 -0
- package/lib/api/utils/validation.d.ts +4 -4
- package/lib/api/utils/validation.js +10 -7
- package/lib/client/auth/index.js +0 -5
- package/lib/client/auth/storage.js +0 -5
- package/lib/client/auth/strategies.js +0 -5
- package/lib/client/base.d.ts +6 -0
- package/lib/client/base.js +8 -0
- package/lib/client/constants.d.ts +1 -0
- package/lib/client/constants.js +1 -0
- package/lib/client/index.d.ts +0 -10
- package/lib/client/index.js +2 -2
- package/lib/client/mixins/ContentsMixin.d.ts +71 -0
- package/lib/client/mixins/ContentsMixin.js +157 -0
- package/lib/client/mixins/IAMMixin.d.ts +0 -31
- package/lib/client/mixins/IAMMixin.js +0 -58
- package/lib/components/animation/AnimatedText.d.ts +2 -44
- package/lib/components/animation/AnimatedText.js +6 -126
- package/lib/components/anonymous/AnonymousKeyExpired.d.ts +56 -0
- package/lib/components/anonymous/AnonymousKeyExpired.js +96 -0
- package/lib/components/anonymous/AnonymousKeyTimer.d.ts +63 -0
- package/lib/components/anonymous/AnonymousKeyTimer.js +140 -0
- package/lib/components/anonymous/index.d.ts +7 -0
- package/lib/components/anonymous/index.js +15 -0
- package/lib/components/auth/SigInAPIKey.d.ts +1 -0
- package/lib/components/auth/SigInAPIKey.js +0 -6
- package/lib/components/auth/SignIn.d.ts +1 -0
- package/lib/components/auth/SignIn.js +0 -4
- package/lib/components/auth/SignIn.stories.d.ts +2 -2
- package/lib/components/avatars/BoringAvatar.d.ts +1 -1
- package/lib/components/avatars/BoringAvatar.stories.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.js +0 -4
- package/lib/components/avatars/UserAvatar.d.ts +16 -1
- package/lib/components/avatars/UserAvatar.js +15 -13
- package/lib/components/avatars/UserProfileAvatar.d.ts +1 -1
- package/lib/components/banners/NoAutomationBanner.d.ts +1 -1
- package/lib/components/billing/BillingEntitySelect.d.ts +16 -0
- package/lib/components/billing/BillingEntitySelect.js +49 -27
- package/lib/components/billing/eligibility.d.ts +22 -0
- package/lib/components/billing/eligibility.js +27 -0
- package/lib/components/billing/index.d.ts +1 -0
- package/lib/components/billing/index.js +1 -4
- package/lib/components/buttons/DownloadCSVButton.d.ts +1 -1
- package/lib/components/buttons/DownloadJsonButton.d.ts +1 -1
- package/lib/components/buttons/LongActionButton.d.ts +1 -0
- package/lib/components/buttons/LongActionButton.js +0 -4
- package/lib/components/buttons/UploadButton.d.ts +1 -0
- package/lib/components/buttons/UploadButton.js +0 -4
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +36 -0
- package/lib/components/collaboration/LiveEditorCollaborators.js +88 -53
- package/lib/components/collaboration/index.js +0 -4
- package/lib/components/confetti/ConfettiSuccess.d.ts +1 -1
- package/lib/components/contents/ContentSourceCard.d.ts +8 -0
- package/lib/components/contents/ContentSourceCard.js +23 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +10 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.js +148 -0
- package/lib/components/contents/index.d.ts +2 -0
- package/lib/components/contents/index.js +6 -0
- package/lib/components/context/OrganizationSelect.d.ts +1 -1
- package/lib/components/display/AvatarSkeleton.d.ts +1 -1
- package/lib/components/display/BusyDots.d.ts +1 -1
- package/lib/components/display/CenteredSpinner.d.ts +1 -1
- package/lib/components/display/CodePreview.d.ts +1 -1
- package/lib/components/display/DatalayerBox.d.ts +7 -3
- package/lib/components/display/DatalayerBox.js +7 -7
- package/lib/components/display/HorizontalCenter.d.ts +1 -1
- package/lib/components/display/JupyterDialog.d.ts +1 -0
- package/lib/components/display/JupyterDialog.js +1 -7
- package/lib/components/display/Markdown.d.ts +1 -0
- package/lib/components/display/NavLink.js +3 -2
- package/lib/components/display/NotebookSkeleton.d.ts +1 -1
- package/lib/components/display/Placeholder.d.ts +1 -1
- package/lib/components/display/ToTopBranded.d.ts +1 -1
- package/lib/components/echarts/EChartsReact.d.ts +1 -1
- package/lib/components/flashes/FlashClosable.d.ts +1 -0
- package/lib/components/flashes/FlashClosable.js +0 -4
- package/lib/components/flashes/FlashGuest.d.ts +1 -1
- package/lib/components/flashes/FlashSurveys.d.ts +1 -1
- package/lib/components/flashes/FlashUnauthorized.d.ts +1 -0
- package/lib/components/flashes/FlashUnauthorized.js +0 -6
- package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
- package/lib/components/iam/ExternalTokenSilentLogin.d.ts +1 -1
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/labels/StatusLabels.d.ts +2 -9
- package/lib/components/labels/StatusLabels.js +2 -26
- package/lib/components/labels/VisibilityLabel.d.ts +1 -1
- package/lib/components/landings/StepBlock.d.ts +1 -1
- package/lib/components/mcp/ClientBadge.d.ts +41 -0
- package/lib/components/mcp/ClientBadge.js +33 -0
- package/lib/components/mcp/McpErrorBlankslate.d.ts +21 -0
- package/lib/components/mcp/McpErrorBlankslate.js +17 -0
- package/lib/components/mcp/ScopeList.d.ts +28 -0
- package/lib/components/mcp/ScopeList.js +14 -0
- package/lib/components/mcp/index.d.ts +10 -0
- package/lib/components/mcp/index.js +18 -0
- package/lib/components/navbar/NavigationVisbilityObserver.d.ts +2 -1
- package/lib/components/navbar/SubdomainNavBar.d.ts +10 -5
- package/lib/components/navbar/SubdomainNavBar.js +2 -1
- package/lib/components/notebooks/JupyterNotebook.d.ts +1 -1
- package/lib/components/notebooks/JupyterNotebookToolbar.d.ts +1 -1
- package/lib/components/principal/PrincipalAppearance.d.ts +22 -42
- package/lib/components/principal/PrincipalAppearance.js +232 -182
- package/lib/components/principal/PrincipalAvatar.d.ts +9 -1
- package/lib/components/principal/PrincipalAvatar.js +18 -10
- package/lib/components/principal/PrincipalBadge.d.ts +1 -1
- package/lib/components/principal/PrincipalBanner.d.ts +1 -1
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +38 -1
- package/lib/components/principal/PrincipalDetailsOverlay.js +64 -33
- package/lib/components/principal/PrincipalHoverCard.d.ts +31 -0
- package/lib/components/principal/PrincipalHoverCard.js +52 -0
- package/lib/components/principal/PrincipalSwitcherMenu.d.ts +1 -0
- package/lib/components/principal/PrincipalSwitcherMenu.js +5 -14
- package/lib/components/principal/index.d.ts +2 -1
- package/lib/components/principal/index.js +2 -1
- package/lib/components/progress/ConsumptionBar.d.ts +1 -0
- package/lib/components/progress/ConsumptionBar.js +0 -4
- package/lib/components/progress/ProgressRing.d.ts +1 -0
- package/lib/components/progress/SpinnerBar.d.ts +1 -1
- package/lib/components/progress/Timer.d.ts +1 -0
- package/lib/components/progress/Timer.js +0 -4
- package/lib/components/screencapture/Screencapture.js +46 -3
- package/lib/components/screencapture/ScreencaptureButton.d.ts +1 -1
- package/lib/components/sharing/ShareAccessComponent.d.ts +58 -3
- package/lib/components/sharing/ShareAccessComponent.js +143 -98
- package/lib/components/sharing/SharingEditor.d.ts +21 -0
- package/lib/components/sharing/SharingEditor.js +9 -28
- package/lib/components/sharing/index.d.ts +1 -0
- package/lib/components/sharing/index.js +1 -0
- package/lib/components/sharing/sandboxSharing.d.ts +26 -0
- package/lib/components/sharing/sandboxSharing.js +41 -0
- package/lib/components/spaces/SpaceDetailsOverlay.d.ts +39 -0
- package/lib/components/spaces/SpaceDetailsOverlay.js +80 -0
- package/lib/components/spaces/SpaceDisplay.d.ts +38 -0
- package/lib/components/spaces/SpaceDisplay.js +92 -0
- package/lib/components/spaces/index.d.ts +4 -0
- package/lib/components/spaces/index.js +7 -0
- package/lib/components/spaces/spaceDisplayModel.d.ts +93 -0
- package/lib/components/spaces/spaceDisplayModel.js +170 -0
- package/lib/components/sparklines/Sparklines.js +3 -4
- package/lib/components/sparklines/index.js +0 -4
- package/lib/components/storage/ContentsBrowser.d.ts +25 -1
- package/lib/components/storage/ContentsBrowser.js +145 -52
- package/lib/components/storage/ContentsBrowserMock.d.ts +3 -0
- package/lib/components/storage/ContentsBrowserMock.js +75 -0
- package/lib/components/storage/ContentsItems.d.ts +2 -1
- package/lib/components/storage/ContentsItems.js +0 -4
- package/lib/components/storage/ContentsTable.d.ts +50 -0
- package/lib/components/storage/ContentsTable.js +134 -0
- package/lib/components/storage/HomeFolderDrive.d.ts +71 -0
- package/lib/components/storage/HomeFolderDrive.js +248 -0
- package/lib/components/storage/index.d.ts +2 -0
- package/lib/components/storage/index.js +2 -0
- package/lib/components/students/StudentItemStatus.d.ts +1 -1
- package/lib/components/students/StudentResultCircle.d.ts +1 -1
- package/lib/components/subnav/SubNav.d.ts +5 -5
- package/lib/components/subnav/SubNav.js +11 -9
- package/lib/components/tables/DataTable.d.ts +1 -1
- package/lib/components/text-reveal/TextRevealAnimation.d.ts +2 -2
- package/lib/components/text-reveal/useTextRevealAnimationLines.d.ts +1 -1
- package/lib/components/time/LiveRelativeTime.d.ts +1 -0
- package/lib/components/time/LiveRelativeTime.js +0 -8
- package/lib/components/time/index.js +0 -4
- package/lib/components/timeline/Timeline.d.ts +1 -1
- package/lib/components/timeline/index.js +0 -4
- package/lib/components/users/PeerIndicator.d.ts +1 -0
- package/lib/components/users/PeerIndicator.js +0 -4
- package/lib/config/Configuration.d.ts +15 -17
- package/lib/config/Configuration.js +7 -0
- package/lib/hooks/cacheConverters.d.ts +0 -7
- package/lib/hooks/cacheConverters.js +0 -25
- package/lib/hooks/index.d.ts +3 -0
- package/lib/hooks/index.js +3 -0
- package/lib/hooks/layouts/LayoutBackdrop.d.ts +1 -1
- package/lib/hooks/layouts/LayoutScreencapture.d.ts +1 -1
- package/lib/hooks/useBackdrop.d.ts +1 -1
- package/lib/hooks/useBackdropJupyterLab.d.ts +3 -2
- package/lib/hooks/useBackdropJupyterLab.js +0 -4
- package/lib/hooks/useBillingEntityStore.js +3 -0
- package/lib/hooks/useCache.d.ts +478 -130
- package/lib/hooks/useCache.js +1580 -676
- package/lib/hooks/useContainsFocus.d.ts +1 -1
- package/lib/hooks/useContents.d.ts +334 -0
- package/lib/hooks/useContents.js +1033 -0
- package/lib/hooks/useFocusTrap.d.ts +4 -4
- package/lib/hooks/useFocusTrap.js +1 -1
- package/lib/hooks/useMcp.d.ts +315 -0
- package/lib/hooks/useMcp.js +891 -0
- package/lib/hooks/useMobile.js +0 -5
- package/lib/hooks/useNavigate.d.ts +41 -3
- package/lib/hooks/useNavigate.js +106 -52
- package/lib/hooks/usePrincipalCacheStore.js +3 -0
- package/lib/hooks/usePrincipalStore.js +3 -0
- package/lib/hooks/useProjectStore.d.ts +3 -3
- package/lib/hooks/useProjectStore.js +4 -4
- package/lib/hooks/useRef.d.ts +1 -1
- package/lib/hooks/useRef.js +3 -0
- package/lib/hooks/useScreencapture.d.ts +2 -1
- package/lib/hooks/useScreencapture.js +0 -4
- package/lib/hooks/useSpaceCacheStore.d.ts +50 -0
- package/lib/hooks/useSpaceCacheStore.js +85 -0
- package/lib/hooks/useToast.js +0 -4
- package/lib/hooks/useVisibilityObserver.d.ts +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +3 -1
- package/lib/mocks/components/FlashMock.d.ts +1 -1
- package/lib/mocks/views/ActionMenuMock.d.ts +1 -1
- package/lib/mocks/views/ChartMock.d.ts +1 -1
- package/lib/mocks/views/DashboardMock.d.ts +1 -1
- package/lib/mocks/views/FormMock.d.ts +1 -1
- package/lib/mocks/views/TableMock.d.ts +1 -1
- package/lib/mocks/views/WipMock.d.ts +1 -1
- package/lib/models/Credits.d.ts +16 -0
- package/lib/models/Credits.js +22 -0
- package/lib/models/CreditsDTO.d.ts +6 -5
- package/lib/models/CreditsDTO.js +7 -5
- package/lib/models/McpAuditEvent.d.ts +52 -0
- package/lib/models/McpAuditEvent.js +5 -0
- package/lib/models/McpBinding.d.ts +57 -0
- package/lib/models/McpBinding.js +5 -0
- package/lib/models/McpPolicy.d.ts +77 -0
- package/lib/models/McpPolicy.js +5 -0
- package/lib/models/McpTask.d.ts +94 -0
- package/lib/models/McpTask.js +7 -0
- package/lib/models/Organization.d.ts +69 -0
- package/lib/models/Organization.js +96 -0
- package/lib/models/Secret.d.ts +1 -2
- package/lib/models/Secret.js +2 -18
- package/lib/models/StartedBy.d.ts +91 -0
- package/lib/models/StartedBy.js +117 -0
- package/lib/models/Team.d.ts +2 -0
- package/lib/models/Team.js +2 -0
- package/lib/models/User.d.ts +4 -0
- package/lib/models/User.js +3 -0
- package/lib/models/UserDTO.js +4 -2
- package/lib/models/UserSettings.d.ts +13 -0
- package/lib/models/UserSettings.js +9 -0
- package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
- package/lib/models/contents/__fixtures__/v1-contracts.json +194 -0
- package/lib/models/contents/fieldCase.d.ts +8 -0
- package/lib/models/contents/fieldCase.js +37 -0
- package/lib/models/contents/index.d.ts +2 -0
- package/lib/models/contents/index.js +6 -0
- package/lib/models/contents/permissions.d.ts +16 -0
- package/lib/models/contents/permissions.js +34 -0
- package/lib/models/index.d.ts +5 -1
- package/lib/models/index.js +5 -1
- package/lib/navigation/components.js +2 -3
- package/lib/routes/publicPaths.js +4 -0
- package/lib/state/index.d.ts +1 -0
- package/lib/state/index.js +1 -0
- package/lib/state/sessionEnd.d.ts +55 -0
- package/lib/state/sessionEnd.js +162 -0
- package/lib/state/substates/CoreState.d.ts +15 -7
- package/lib/state/substates/CoreState.js +21 -17
- package/lib/state/substates/IAMState.d.ts +1 -1
- package/lib/state/substates/IAMState.js +12 -5
- package/lib/state/substates/LayoutState.js +12 -0
- package/lib/state/substates/ProfileState.d.ts +1 -0
- package/lib/state/substates/ProfileState.js +1 -4
- package/lib/state/substates/index.d.ts +0 -1
- package/lib/state/substates/index.js +0 -1
- package/lib/utils/Jwt.d.ts +26 -0
- package/lib/utils/Jwt.js +37 -0
- package/lib/utils/Lazy.d.ts +20 -0
- package/lib/utils/Lazy.js +32 -6
- package/lib/utils/Screencapture.js +3 -0
- package/lib/utils/WithSuspense.d.ts +11 -1
- package/lib/utils/WithSuspense.js +11 -1
- package/lib/views/api-keys/APIKeyEdit.d.ts +1 -1
- package/lib/views/api-keys/APIKeyNew.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.js +30 -4
- package/lib/views/api-keys/APIKeysStandalone.d.ts +5 -1
- package/lib/views/api-keys/APIKeysStandalone.js +2 -2
- package/lib/views/datasources/DatasourceDetail.d.ts +12 -5
- package/lib/views/datasources/DatasourceDetail.js +80 -110
- package/lib/views/datasources/DatasourceNew.d.ts +14 -8
- package/lib/views/datasources/DatasourceNew.js +129 -118
- package/lib/views/datasources/Datasources.d.ts +39 -7
- package/lib/views/datasources/Datasources.js +95 -40
- package/lib/views/datasources/DatasourcesMock.d.ts +3 -0
- package/lib/views/datasources/DatasourcesMock.js +57 -0
- package/lib/views/iam/SignInSimple.d.ts +12 -0
- package/lib/views/iam/SignInSimple.js +4 -4
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +1 -0
- package/lib/views/mcp/AdmittedClients.d.ts +44 -0
- package/lib/views/mcp/AdmittedClients.js +59 -0
- package/lib/views/mcp/AlertDestinations.d.ts +34 -0
- package/lib/views/mcp/AlertDestinations.js +75 -0
- package/lib/views/mcp/AlertRules.d.ts +32 -0
- package/lib/views/mcp/AlertRules.js +245 -0
- package/lib/views/mcp/ApprovalQueue.d.ts +66 -0
- package/lib/views/mcp/ApprovalQueue.js +95 -0
- package/lib/views/mcp/AuditLog.d.ts +42 -0
- package/lib/views/mcp/AuditLog.js +144 -0
- package/lib/views/mcp/ConnectedAgents.d.ts +34 -0
- package/lib/views/mcp/ConnectedAgents.js +135 -0
- package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
- package/lib/views/mcp/EnterpriseConsole.js +195 -0
- package/lib/views/mcp/IdentityProviders.d.ts +33 -0
- package/lib/views/mcp/IdentityProviders.js +299 -0
- package/lib/views/mcp/McpDashboard.d.ts +50 -0
- package/lib/views/mcp/McpDashboard.js +430 -0
- package/lib/views/mcp/McpHome.d.ts +92 -0
- package/lib/views/mcp/McpHome.js +153 -0
- package/lib/views/mcp/McpObservability.d.ts +79 -0
- package/lib/views/mcp/McpObservability.js +236 -0
- package/lib/views/mcp/NotebookRuns.d.ts +39 -0
- package/lib/views/mcp/NotebookRuns.js +44 -0
- package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
- package/lib/views/mcp/OrganizationPolicy.js +108 -0
- package/lib/views/mcp/OrganizationUsage.d.ts +69 -0
- package/lib/views/mcp/OrganizationUsage.js +113 -0
- package/lib/views/mcp/PersonalPolicy.d.ts +54 -0
- package/lib/views/mcp/PersonalPolicy.js +126 -0
- package/lib/views/mcp/Policies.d.ts +53 -0
- package/lib/views/mcp/Policies.js +210 -0
- package/lib/views/mcp/PolicyForm.d.ts +83 -0
- package/lib/views/mcp/PolicyForm.js +113 -0
- package/lib/views/mcp/PolicyHistory.d.ts +58 -0
- package/lib/views/mcp/PolicyHistory.js +75 -0
- package/lib/views/mcp/RunDetail.d.ts +87 -0
- package/lib/views/mcp/RunDetail.js +186 -0
- package/lib/views/mcp/ScimProvisioning.d.ts +54 -0
- package/lib/views/mcp/ScimProvisioning.js +173 -0
- package/lib/views/mcp/ServiceAgents.d.ts +46 -0
- package/lib/views/mcp/ServiceAgents.js +194 -0
- package/lib/views/mcp/TeamPolicies.d.ts +33 -0
- package/lib/views/mcp/TeamPolicies.js +159 -0
- package/lib/views/mcp/ToolAccess.d.ts +60 -0
- package/lib/views/mcp/ToolAccess.js +101 -0
- package/lib/views/mcp/TraceTimeline.d.ts +81 -0
- package/lib/views/mcp/TraceTimeline.js +132 -0
- package/lib/views/mcp/format.d.ts +25 -0
- package/lib/views/mcp/format.js +77 -0
- package/lib/views/mcp/index.d.ts +34 -0
- package/lib/views/mcp/index.js +42 -0
- package/lib/views/mcp/types.d.ts +66 -0
- package/lib/views/mcp/types.js +5 -0
- package/lib/views/otel/simpleAuthStore.js +3 -0
- package/lib/views/secrets/SecretEdit.d.ts +5 -1
- package/lib/views/secrets/SecretEdit.js +5 -4
- package/lib/views/secrets/SecretNew.d.ts +11 -1
- package/lib/views/secrets/SecretNew.js +7 -3
- package/lib/views/secrets/Secrets.d.ts +12 -1
- package/lib/views/secrets/Secrets.js +2 -2
- package/package.json +269 -260
- package/scripts/generate-contents-types.py +169 -0
- package/scripts/generate-mcp-types.py +233 -0
- package/scripts/generate-orchestration-types.py +920 -0
- package/lib/api/iam/datasources.d.ts +0 -86
- package/lib/api/iam/datasources.js +0 -185
- package/lib/components/toolbars/index.d.ts +0 -1
- package/lib/models/Datasource.d.ts +0 -181
- package/lib/models/Datasource.js +0 -154
- package/lib/state/substates/DatasourceState.d.ts +0 -11
- package/lib/state/substates/DatasourceState.js +0 -16
- /package/lib/{components/toolbars/index.js → api/contents/generated.js} +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The MCP policy layer IAM holds for one organization, team or person.
|
|
11
|
+
*
|
|
12
|
+
* Distinct from the *effective* policy the gateway answers, which is every
|
|
13
|
+
* layer intersected with, per rule, the layer that decided it. That one is
|
|
14
|
+
* the read: "what may my agent do, and who said so". This one is the write:
|
|
15
|
+
* "what does my organization narrow".
|
|
16
|
+
*
|
|
17
|
+
* Only four kinds of rule can be stored, and IAM refuses anything else —
|
|
18
|
+
* so a policy page cannot promise something the gateway never enforces, and
|
|
19
|
+
* `toolDenyList` comes back as a typo rather than being kept as a setting
|
|
20
|
+
* that does nothing.
|
|
21
|
+
*
|
|
22
|
+
* **Writes carry the version that was read.** A policy is small and read
|
|
23
|
+
* whole, so a write replaces rather than merges; without the version, two
|
|
24
|
+
* owners editing the same policy would each silently overwrite the other,
|
|
25
|
+
* and the loser would not know. IAM answers `409` instead, and the caller
|
|
26
|
+
* re-reads.
|
|
27
|
+
*
|
|
28
|
+
* @module api/iam/mcpPolicy
|
|
29
|
+
*/
|
|
30
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
31
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
32
|
+
/**
|
|
33
|
+
* Which layer a policy belongs to.
|
|
34
|
+
*
|
|
35
|
+
* The names IAM stores, exactly: `personal`, not `user`. It refuses an
|
|
36
|
+
* unknown scope with a `422`, so getting this wrong is not a subtle
|
|
37
|
+
* mis-scoping — it is every read and every write of that layer failing.
|
|
38
|
+
* Held against IAM's own `POLICY_SCOPES` by a test in the gateway's suite.
|
|
39
|
+
*/
|
|
40
|
+
export const MCP_POLICY_SCOPES = ['organization', 'team', 'personal'];
|
|
41
|
+
/**
|
|
42
|
+
* Every rule name IAM will store, in the order a form should show them.
|
|
43
|
+
*
|
|
44
|
+
* Exported so a form cannot drift from what the gateway enforces: a rule
|
|
45
|
+
* rendered here and unknown to IAM is refused at the write, which reads to
|
|
46
|
+
* the person filling it in as the page being broken.
|
|
47
|
+
*/
|
|
48
|
+
export const MCP_POLICY_RULES = [
|
|
49
|
+
'toolDenylist',
|
|
50
|
+
'toolAllowlist',
|
|
51
|
+
'allowedClients',
|
|
52
|
+
'maxCallsPerMinute',
|
|
53
|
+
'maxCreditsPerDay',
|
|
54
|
+
'maxConcurrentSandboxes',
|
|
55
|
+
'gpuHoursPerMonth',
|
|
56
|
+
'storageBytes',
|
|
57
|
+
'sessionMaxHours',
|
|
58
|
+
'ssoAdmitsWithoutConsent',
|
|
59
|
+
];
|
|
60
|
+
/** Raised when the policy changed between the read and the write. */
|
|
61
|
+
export class McpPolicyConflict extends Error {
|
|
62
|
+
constructor(message) {
|
|
63
|
+
super(message);
|
|
64
|
+
this.name = 'McpPolicyConflict';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** `suffix` is appended verbatim: a query string, or a further path segment. */
|
|
68
|
+
const policyUrl = (baseUrl, scope, subjectUid, suffix = '') => `${baseUrl}${API_BASE_PATHS.IAM}/mcp-policies/${encodeURIComponent(scope)}` +
|
|
69
|
+
`/${encodeURIComponent(subjectUid)}${suffix}`;
|
|
70
|
+
/**
|
|
71
|
+
* One layer's rules, or `null` where nobody has written it.
|
|
72
|
+
*
|
|
73
|
+
* `null` rather than an empty object, and the difference is the whole point:
|
|
74
|
+
* "this organization narrows nothing" and "this organization has no policy"
|
|
75
|
+
* are the same in effect and different to edit. A form that cannot tell them
|
|
76
|
+
* apart offers **Remove** for a policy that does not exist.
|
|
77
|
+
*/
|
|
78
|
+
export const getMcpPolicy = async (token, scope, subjectUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
79
|
+
try {
|
|
80
|
+
return await requestDatalayerAPI({
|
|
81
|
+
url: policyUrl(baseUrl, scope, subjectUid),
|
|
82
|
+
method: 'GET',
|
|
83
|
+
token,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// A layer nobody has written is a `404`, and it is an ordinary answer
|
|
88
|
+
// rather than a failure — most organizations have never written one.
|
|
89
|
+
if (isNotFound(error)) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Replace one layer's rules.
|
|
97
|
+
*
|
|
98
|
+
* Replace, not merge: a policy is read whole and small, and merging would
|
|
99
|
+
* leave no way to express *removing* a rule — an owner clearing a denylist
|
|
100
|
+
* would find it still there.
|
|
101
|
+
*/
|
|
102
|
+
export const setMcpPolicy = async (token, scope, subjectUid, rules, options = {}, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
103
|
+
const query = options.expectedVersion === undefined
|
|
104
|
+
? ''
|
|
105
|
+
: `?expected_version=${encodeURIComponent(String(options.expectedVersion))}`;
|
|
106
|
+
try {
|
|
107
|
+
const response = await requestDatalayerAPI({
|
|
108
|
+
url: policyUrl(baseUrl, scope, subjectUid, query),
|
|
109
|
+
method: 'PUT',
|
|
110
|
+
token,
|
|
111
|
+
body: rules,
|
|
112
|
+
});
|
|
113
|
+
return response.policy ?? {};
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (isConflict(error)) {
|
|
117
|
+
throw new McpPolicyConflict('This policy changed while you were editing it. Read it again and ' +
|
|
118
|
+
'reapply your change — otherwise one of the two edits is lost, and ' +
|
|
119
|
+
'whoever loses it is not told.');
|
|
120
|
+
}
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/** Remove one layer, so it narrows nothing again. */
|
|
125
|
+
export const deleteMcpPolicy = async (token, scope, subjectUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
126
|
+
await requestDatalayerAPI({
|
|
127
|
+
url: policyUrl(baseUrl, scope, subjectUid),
|
|
128
|
+
method: 'DELETE',
|
|
129
|
+
token,
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const statusOf = (error) => {
|
|
133
|
+
const candidate = error;
|
|
134
|
+
return candidate?.status ?? candidate?.response?.status;
|
|
135
|
+
};
|
|
136
|
+
const isNotFound = (error) => statusOf(error) === 404;
|
|
137
|
+
const isConflict = (error) => statusOf(error) === 409;
|
|
138
|
+
const admittedFromWire = (wire) => ({
|
|
139
|
+
entry: wire.entry ?? '',
|
|
140
|
+
kind: wire.kind === 'hostname' || wire.kind === 'url' ? wire.kind : 'unusable',
|
|
141
|
+
hostname: wire.hostname || undefined,
|
|
142
|
+
resolved: wire.resolved,
|
|
143
|
+
clientName: wire.client_name || undefined,
|
|
144
|
+
clientHostname: wire.client_hostname || undefined,
|
|
145
|
+
clientUri: wire.client_uri || undefined,
|
|
146
|
+
localhostOnly: wire.localhost_only,
|
|
147
|
+
detail: wire.detail || undefined,
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* What this layer's admitted-client entries actually name.
|
|
151
|
+
*
|
|
152
|
+
* Its own call rather than part of `getMcpPolicy`, because that one is what
|
|
153
|
+
* the gateway reads on every uncached tool call and this may fetch a client
|
|
154
|
+
* document per entry — which is exactly what must never happen on the
|
|
155
|
+
* enforcement path.
|
|
156
|
+
*/
|
|
157
|
+
export const getAdmittedClients = async (token, scope, subjectUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
158
|
+
const response = await requestDatalayerAPI({
|
|
159
|
+
url: policyUrl(baseUrl, scope, subjectUid, '/admitted-clients'),
|
|
160
|
+
method: 'GET',
|
|
161
|
+
token,
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
allowlisted: response.allowlisted === true,
|
|
165
|
+
clients: (response.clients ?? []).map(admittedFromWire),
|
|
166
|
+
detail: response.detail || undefined,
|
|
167
|
+
};
|
|
168
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface OrganizationTeam {
|
|
2
|
+
uid: string;
|
|
3
|
+
handle: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* One organization's teams.
|
|
8
|
+
*
|
|
9
|
+
* A team with no uid is dropped rather than rendered: it addresses no
|
|
10
|
+
* policy layer, so a row for it would offer a form whose every write is a
|
|
11
|
+
* `404`.
|
|
12
|
+
*/
|
|
13
|
+
export declare const listOrganizationTeams: (token: string, orgUid: string, baseUrl?: string) => Promise<OrganizationTeam[]>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The teams inside one organization.
|
|
11
|
+
*
|
|
12
|
+
* Only what the MCP console needs of them: a name to show and a uid to
|
|
13
|
+
* address a policy layer with. Team membership, invitations and the rest
|
|
14
|
+
* belong to the organization's own settings, not here.
|
|
15
|
+
*
|
|
16
|
+
* @module api/iam/organizationTeams
|
|
17
|
+
*/
|
|
18
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
19
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
20
|
+
/**
|
|
21
|
+
* One organization's teams.
|
|
22
|
+
*
|
|
23
|
+
* A team with no uid is dropped rather than rendered: it addresses no
|
|
24
|
+
* policy layer, so a row for it would offer a form whose every write is a
|
|
25
|
+
* `404`.
|
|
26
|
+
*/
|
|
27
|
+
export const listOrganizationTeams = async (token, orgUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
28
|
+
const response = await requestDatalayerAPI({
|
|
29
|
+
url: `${baseUrl}${API_BASE_PATHS.IAM}/organizations/` +
|
|
30
|
+
`${encodeURIComponent(orgUid)}/teams`,
|
|
31
|
+
method: 'GET',
|
|
32
|
+
token,
|
|
33
|
+
});
|
|
34
|
+
return (response.teams ?? [])
|
|
35
|
+
.filter(team => Boolean(team.uid))
|
|
36
|
+
.map(team => ({
|
|
37
|
+
uid: team.uid,
|
|
38
|
+
handle: team.handle_s ?? '',
|
|
39
|
+
// The handle is the fallback rather than the uid: a person picking a
|
|
40
|
+
// team from a list knows `data-science`, not `01ARZ3ND…`.
|
|
41
|
+
name: team.name_t || team.handle_s || team.uid,
|
|
42
|
+
}));
|
|
43
|
+
};
|
package/lib/api/iam/profile.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MembershipsResponse, ShareablePrincipalsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
|
|
1
|
+
import { MembershipsResponse, PrincipalSearchResponse, PrincipalSearchUser, ShareablePrincipalsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
|
|
2
2
|
/**
|
|
3
3
|
* Get current authenticated user profile
|
|
4
4
|
* @param token - Authentication token (required)
|
|
@@ -28,3 +28,19 @@ export declare const memberships: (token: string, baseUrl?: string) => Promise<M
|
|
|
28
28
|
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
29
29
|
*/
|
|
30
30
|
export declare const principalsShareable: (token: string, baseUrl?: string) => Promise<ShareablePrincipalsResponse>;
|
|
31
|
+
/**
|
|
32
|
+
* Search the people, teams and organizations the caller may name: what the
|
|
33
|
+
* sharing dialogs search, and whom a comment mentions or assigns (B4-02).
|
|
34
|
+
*
|
|
35
|
+
* @param token - Authentication token (required)
|
|
36
|
+
* @param query - What is typed: part of a handle or of a name
|
|
37
|
+
* @param principalTypes - What to search; people only by default
|
|
38
|
+
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
39
|
+
*/
|
|
40
|
+
export declare const searchPrincipals: (token: string, query: string, principalTypes?: Array<"user" | "team" | "organization">, baseUrl?: string) => Promise<PrincipalSearchResponse>;
|
|
41
|
+
/** A person `searchPrincipals` found, as a comment or a report names them. */
|
|
42
|
+
export declare const personOfPrincipalUser: (user: PrincipalSearchUser) => {
|
|
43
|
+
uid: string;
|
|
44
|
+
handle: string;
|
|
45
|
+
name: string | null;
|
|
46
|
+
};
|
package/lib/api/iam/profile.js
CHANGED
|
@@ -69,3 +69,30 @@ export const principalsShareable = async (token, baseUrl = DEFAULT_SERVICE_URLS.
|
|
|
69
69
|
token,
|
|
70
70
|
});
|
|
71
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Search the people, teams and organizations the caller may name: what the
|
|
74
|
+
* sharing dialogs search, and whom a comment mentions or assigns (B4-02).
|
|
75
|
+
*
|
|
76
|
+
* @param token - Authentication token (required)
|
|
77
|
+
* @param query - What is typed: part of a handle or of a name
|
|
78
|
+
* @param principalTypes - What to search; people only by default
|
|
79
|
+
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
80
|
+
*/
|
|
81
|
+
export const searchPrincipals = async (token, query, principalTypes = ['user'], baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
82
|
+
validateToken(token);
|
|
83
|
+
return requestDatalayerAPI({
|
|
84
|
+
url: `${baseUrl}${API_BASE_PATHS.IAM}/principals/search`,
|
|
85
|
+
method: 'POST',
|
|
86
|
+
body: { query, principalTypes },
|
|
87
|
+
token,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
/** A person `searchPrincipals` found, as a comment or a report names them. */
|
|
91
|
+
export const personOfPrincipalUser = (user) => ({
|
|
92
|
+
uid: user.uid,
|
|
93
|
+
handle: user.handle_s,
|
|
94
|
+
name: `${user.first_name_t ?? ''} ${user.last_name_t ?? ''}`.trim() ||
|
|
95
|
+
user.display_name_t ||
|
|
96
|
+
user.display_name ||
|
|
97
|
+
null,
|
|
98
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** A SCIM credential as the console may see it — never the secret or its hash. */
|
|
2
|
+
export interface ScimToken {
|
|
3
|
+
uid: string;
|
|
4
|
+
orgUid: string;
|
|
5
|
+
/** What an administrator called it, to tell two directories apart. */
|
|
6
|
+
name: string;
|
|
7
|
+
/**
|
|
8
|
+
* Revoked rather than deleted, so the rows a provisioning run wrote can
|
|
9
|
+
* still name the token that wrote them.
|
|
10
|
+
*/
|
|
11
|
+
revoked: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* When the secret was last replaced. A token that has never been rotated
|
|
14
|
+
* carries its creation moment here.
|
|
15
|
+
*/
|
|
16
|
+
rotatedAt?: string;
|
|
17
|
+
/**
|
|
18
|
+
* When it last authenticated a SCIM call, or empty for never. Written best
|
|
19
|
+
* effort — a provisioning call is never failed for the bookkeeping.
|
|
20
|
+
*/
|
|
21
|
+
lastUsedAt?: string;
|
|
22
|
+
createdBy?: string;
|
|
23
|
+
createdAt?: string;
|
|
24
|
+
updatedAt?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A freshly minted credential: the record, and the secret **this once**.
|
|
28
|
+
*
|
|
29
|
+
* The two are separate fields rather than one merged object on purpose. The
|
|
30
|
+
* secret does not belong in anything the console stores, renders twice, or
|
|
31
|
+
* puts in a list, and a shape that carried it alongside every other field
|
|
32
|
+
* invites exactly that.
|
|
33
|
+
*/
|
|
34
|
+
export interface MintedScimToken {
|
|
35
|
+
token: ScimToken;
|
|
36
|
+
/** Shown once. Not retrievable, by construction — only a hash is stored. */
|
|
37
|
+
secret: string;
|
|
38
|
+
}
|
|
39
|
+
export declare const listScimTokens: (token: string, orgUid: string, baseUrl?: string) => Promise<ScimToken[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Mint one. The secret is in this answer and nowhere else, ever again.
|
|
42
|
+
*
|
|
43
|
+
* The caller must put it in front of somebody before the next render. There
|
|
44
|
+
* is no second chance and no call that would provide one.
|
|
45
|
+
*/
|
|
46
|
+
export declare const createScimToken: (token: string, orgUid: string, name: string, baseUrl?: string) => Promise<MintedScimToken>;
|
|
47
|
+
/**
|
|
48
|
+
* A new secret for the same record; the old one stops at once.
|
|
49
|
+
*
|
|
50
|
+
* Rotation rather than delete-and-recreate because the record's uid is what
|
|
51
|
+
* the provisioning rows name. Replacing it would leave them pointing at
|
|
52
|
+
* nothing.
|
|
53
|
+
*/
|
|
54
|
+
export declare const rotateScimToken: (token: string, orgUid: string, uid: string, baseUrl?: string) => Promise<MintedScimToken>;
|
|
55
|
+
/** Stop a token, keeping the rows that name it readable. */
|
|
56
|
+
export declare const revokeScimToken: (token: string, orgUid: string, uid: string, baseUrl?: string) => Promise<ScimToken>;
|
|
57
|
+
/**
|
|
58
|
+
* The base URL a directory is configured with.
|
|
59
|
+
*
|
|
60
|
+
* Built here rather than typed into the page, because it is half of what an
|
|
61
|
+
* administrator copies into Okta or Entra and a typo in it looks like an
|
|
62
|
+
* outage on the directory's side. The directory appends `/Users` itself;
|
|
63
|
+
* RFC 7644 fixes everything after this.
|
|
64
|
+
*/
|
|
65
|
+
export declare const scimBaseUrl: (baseUrl?: string) => string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether this organization can actually be provisioned into right now.
|
|
68
|
+
*
|
|
69
|
+
* A list with tokens in it is not the same as a working integration, and the
|
|
70
|
+
* distinction is the one an administrator most needs: every token revoked
|
|
71
|
+
* reads, in a table, almost exactly like a healthy setup. `neverUsed` is the
|
|
72
|
+
* other quiet state — configured, live, and never once called, which is what
|
|
73
|
+
* a directory that was set up and never switched on looks like.
|
|
74
|
+
*/
|
|
75
|
+
export declare const scimStatus: (tokens: ScimToken[]) => {
|
|
76
|
+
state: "none" | "revoked" | "never-used" | "active";
|
|
77
|
+
live: ScimToken[];
|
|
78
|
+
lastUsedAt?: string;
|
|
79
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The credentials an organization's directory provisions with, over SCIM.
|
|
11
|
+
*
|
|
12
|
+
* The identity provider registry beside this one made a directory able to
|
|
13
|
+
* *sign somebody in*. SCIM is the half that does not wait for them to turn
|
|
14
|
+
* up: the directory says who exists when they join and, far more
|
|
15
|
+
* importantly, who has left.
|
|
16
|
+
*
|
|
17
|
+
* **The token is the tenant.** Every SCIM call resolves its organization
|
|
18
|
+
* from the bearer credential before it looks at anything else, so these
|
|
19
|
+
* records are not a convenience — each one *is* an organization's provisioning
|
|
20
|
+
* authority, and there is nothing else identifying the caller.
|
|
21
|
+
*
|
|
22
|
+
* **The secret is answered once and never again.** `createScimToken` and
|
|
23
|
+
* `rotateScimToken` return it; nothing reads it back, because only a SHA-256
|
|
24
|
+
* of it is stored. A console that offered to show it later would be
|
|
25
|
+
* promising something the server cannot do — so this client has no call that
|
|
26
|
+
* could, and the UI has to say "copy it now" and mean it.
|
|
27
|
+
*
|
|
28
|
+
* `lastUsedAt` is the column worth reading. A directory configured once and
|
|
29
|
+
* forgotten looks exactly like a live one in every other field, and the
|
|
30
|
+
* difference matters most for deprovisioning: the integration that has not
|
|
31
|
+
* called in a month is not removing anybody.
|
|
32
|
+
*
|
|
33
|
+
* @module api/iam/scimTokens
|
|
34
|
+
*/
|
|
35
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
36
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
37
|
+
const fromWire = (wire) => ({
|
|
38
|
+
uid: wire.uid ?? '',
|
|
39
|
+
orgUid: wire.org_uid ?? '',
|
|
40
|
+
name: wire.name ?? '',
|
|
41
|
+
// A record with no `revoked` field is a live one: absence is not
|
|
42
|
+
// revocation, and reading it as one would show every token as stopped.
|
|
43
|
+
revoked: wire.revoked === true,
|
|
44
|
+
rotatedAt: wire.rotated_at || undefined,
|
|
45
|
+
lastUsedAt: wire.last_used_at || undefined,
|
|
46
|
+
createdBy: wire.created_by || undefined,
|
|
47
|
+
createdAt: wire.created_at || undefined,
|
|
48
|
+
updatedAt: wire.updated_at || undefined,
|
|
49
|
+
});
|
|
50
|
+
const tokensUrl = (baseUrl, orgUid, suffix = '') => `${baseUrl}${API_BASE_PATHS.IAM}/organizations/${encodeURIComponent(orgUid)}` +
|
|
51
|
+
`/scim-tokens${suffix}`;
|
|
52
|
+
export const listScimTokens = async (token, orgUid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
53
|
+
const response = await requestDatalayerAPI({
|
|
54
|
+
url: tokensUrl(baseUrl, orgUid),
|
|
55
|
+
method: 'GET',
|
|
56
|
+
token,
|
|
57
|
+
});
|
|
58
|
+
return (response.tokens ?? []).map(fromWire);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Mint one. The secret is in this answer and nowhere else, ever again.
|
|
62
|
+
*
|
|
63
|
+
* The caller must put it in front of somebody before the next render. There
|
|
64
|
+
* is no second chance and no call that would provide one.
|
|
65
|
+
*/
|
|
66
|
+
export const createScimToken = async (token, orgUid, name, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
67
|
+
const response = await requestDatalayerAPI({
|
|
68
|
+
url: tokensUrl(baseUrl, orgUid),
|
|
69
|
+
method: 'POST',
|
|
70
|
+
token,
|
|
71
|
+
body: { name },
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
token: fromWire(response.token ?? {}),
|
|
75
|
+
secret: response.token?.token ?? '',
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* A new secret for the same record; the old one stops at once.
|
|
80
|
+
*
|
|
81
|
+
* Rotation rather than delete-and-recreate because the record's uid is what
|
|
82
|
+
* the provisioning rows name. Replacing it would leave them pointing at
|
|
83
|
+
* nothing.
|
|
84
|
+
*/
|
|
85
|
+
export const rotateScimToken = async (token, orgUid, uid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
86
|
+
const response = await requestDatalayerAPI({
|
|
87
|
+
url: tokensUrl(baseUrl, orgUid, `/${encodeURIComponent(uid)}/rotate`),
|
|
88
|
+
method: 'POST',
|
|
89
|
+
token,
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
token: fromWire(response.token ?? {}),
|
|
93
|
+
secret: response.token?.token ?? '',
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
/** Stop a token, keeping the rows that name it readable. */
|
|
97
|
+
export const revokeScimToken = async (token, orgUid, uid, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
98
|
+
const response = await requestDatalayerAPI({
|
|
99
|
+
url: tokensUrl(baseUrl, orgUid, `/${encodeURIComponent(uid)}`),
|
|
100
|
+
method: 'DELETE',
|
|
101
|
+
token,
|
|
102
|
+
});
|
|
103
|
+
return fromWire(response.token ?? {});
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* The base URL a directory is configured with.
|
|
107
|
+
*
|
|
108
|
+
* Built here rather than typed into the page, because it is half of what an
|
|
109
|
+
* administrator copies into Okta or Entra and a typo in it looks like an
|
|
110
|
+
* outage on the directory's side. The directory appends `/Users` itself;
|
|
111
|
+
* RFC 7644 fixes everything after this.
|
|
112
|
+
*/
|
|
113
|
+
export const scimBaseUrl = (baseUrl = DEFAULT_SERVICE_URLS.IAM) => `${baseUrl}/api/iam/scim/v2`;
|
|
114
|
+
/**
|
|
115
|
+
* Whether this organization can actually be provisioned into right now.
|
|
116
|
+
*
|
|
117
|
+
* A list with tokens in it is not the same as a working integration, and the
|
|
118
|
+
* distinction is the one an administrator most needs: every token revoked
|
|
119
|
+
* reads, in a table, almost exactly like a healthy setup. `neverUsed` is the
|
|
120
|
+
* other quiet state — configured, live, and never once called, which is what
|
|
121
|
+
* a directory that was set up and never switched on looks like.
|
|
122
|
+
*/
|
|
123
|
+
export const scimStatus = (tokens) => {
|
|
124
|
+
const live = tokens.filter(entry => !entry.revoked);
|
|
125
|
+
if (tokens.length === 0) {
|
|
126
|
+
return { state: 'none', live };
|
|
127
|
+
}
|
|
128
|
+
if (live.length === 0) {
|
|
129
|
+
return { state: 'revoked', live };
|
|
130
|
+
}
|
|
131
|
+
const used = live
|
|
132
|
+
.map(entry => entry.lastUsedAt)
|
|
133
|
+
.filter((value) => Boolean(value))
|
|
134
|
+
.sort();
|
|
135
|
+
const lastUsedAt = used.length > 0 ? used[used.length - 1] : undefined;
|
|
136
|
+
return {
|
|
137
|
+
state: lastUsedAt ? 'active' : 'never-used',
|
|
138
|
+
live,
|
|
139
|
+
lastUsedAt,
|
|
140
|
+
};
|
|
141
|
+
};
|
package/lib/api/iam/secrets.js
CHANGED
|
@@ -9,21 +9,6 @@
|
|
|
9
9
|
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
10
10
|
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
11
11
|
import { validateToken, validateRequiredString } from '../utils/validation.js';
|
|
12
|
-
/**
|
|
13
|
-
* Helper function to Base64 encode a value (cross-platform).
|
|
14
|
-
* @param value - Plain text value to encode
|
|
15
|
-
* @returns Base64 encoded string
|
|
16
|
-
*/
|
|
17
|
-
function encodeValue(value) {
|
|
18
|
-
if (typeof Buffer !== 'undefined') {
|
|
19
|
-
// Node.js environment
|
|
20
|
-
return Buffer.from(value).toString('base64');
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
// Browser environment
|
|
24
|
-
return btoa(value);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
12
|
/**
|
|
28
13
|
* Create a new secret.
|
|
29
14
|
* Creates a new encrypted secret for the authenticated user.
|
|
@@ -52,7 +37,10 @@ export const createSecret = async (token, data, baseUrl = DEFAULT_SERVICE_URLS.I
|
|
|
52
37
|
variant: data.variant || 'generic',
|
|
53
38
|
name: data.name,
|
|
54
39
|
description: data.description || '',
|
|
55
|
-
|
|
40
|
+
// As it is. A secret has one representation end to end (PLAN_ENVS.md
|
|
41
|
+
// E3-05): this used to base64-encode, and nothing on the read side undid
|
|
42
|
+
// it, so a build secret arrived at its build encoded and opened nothing.
|
|
43
|
+
value: data.value,
|
|
56
44
|
};
|
|
57
45
|
try {
|
|
58
46
|
return await requestDatalayerAPI({
|
|
@@ -64,7 +52,7 @@ export const createSecret = async (token, data, baseUrl = DEFAULT_SERVICE_URLS.I
|
|
|
64
52
|
}
|
|
65
53
|
catch (error) {
|
|
66
54
|
if (error.response?.status === 409) {
|
|
67
|
-
throw new Error(`Secret with name '${data.name}' already exists. Please use a different name
|
|
55
|
+
throw new Error(`Secret with name '${data.name}' already exists. Please use a different name.`, { cause: error });
|
|
68
56
|
}
|
|
69
57
|
throw error;
|
|
70
58
|
}
|
|
@@ -118,7 +106,7 @@ export const getSecret = async (token, secretId, baseUrl = DEFAULT_SERVICE_URLS.
|
|
|
118
106
|
}
|
|
119
107
|
catch (error) {
|
|
120
108
|
if (error.response?.status === 404) {
|
|
121
|
-
throw new Error(`Secret '${secretId}' not found
|
|
109
|
+
throw new Error(`Secret '${secretId}' not found.`, { cause: error });
|
|
122
110
|
}
|
|
123
111
|
throw error;
|
|
124
112
|
}
|
|
@@ -147,7 +135,7 @@ export const updateSecret = async (token, secretId, data, baseUrl = DEFAULT_SERV
|
|
|
147
135
|
// Base64 encode value if provided
|
|
148
136
|
const requestBody = { ...data };
|
|
149
137
|
if (data.value) {
|
|
150
|
-
requestBody.value =
|
|
138
|
+
requestBody.value = data.value;
|
|
151
139
|
}
|
|
152
140
|
try {
|
|
153
141
|
return await requestDatalayerAPI({
|
|
@@ -159,7 +147,7 @@ export const updateSecret = async (token, secretId, data, baseUrl = DEFAULT_SERV
|
|
|
159
147
|
}
|
|
160
148
|
catch (error) {
|
|
161
149
|
if (error.response?.status === 404) {
|
|
162
|
-
throw new Error(`Secret '${secretId}' not found
|
|
150
|
+
throw new Error(`Secret '${secretId}' not found.`, { cause: error });
|
|
163
151
|
}
|
|
164
152
|
throw error;
|
|
165
153
|
}
|
|
@@ -189,7 +177,7 @@ export const deleteSecret = async (token, secretId, baseUrl = DEFAULT_SERVICE_UR
|
|
|
189
177
|
}
|
|
190
178
|
catch (error) {
|
|
191
179
|
if (error.response?.status === 404) {
|
|
192
|
-
throw new Error(`Secret '${secretId}' not found
|
|
180
|
+
throw new Error(`Secret '${secretId}' not found.`, { cause: error });
|
|
193
181
|
}
|
|
194
182
|
throw error;
|
|
195
183
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a service agent may be granted.
|
|
3
|
+
*
|
|
4
|
+
* A subset of the OAuth scopes, and deliberately not all of them: the ones
|
|
5
|
+
* about a *person* — reading their profile, acting as them — mean nothing
|
|
6
|
+
* for a principal that is not one, and IAM refuses them. Offering one would
|
|
7
|
+
* invite somebody to grant something that silently does nothing.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SERVICE_AGENT_SCOPES: readonly ["runtimes:read", "runtimes:write", "data:read", "sandboxes:manage"];
|
|
10
|
+
export type ServiceAgentScope = (typeof SERVICE_AGENT_SCOPES)[number];
|
|
11
|
+
export interface ServiceAgent {
|
|
12
|
+
uid: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
/** The team it belongs to, where it is a team's rather than the organization's. */
|
|
16
|
+
teamUid: string;
|
|
17
|
+
/** Space-separated, as the token's `scope` claim carries them. */
|
|
18
|
+
scopes: string;
|
|
19
|
+
/**
|
|
20
|
+
* Revoked rather than removed. Its audit rows name it, and a uid that
|
|
21
|
+
* resolves to nothing makes a year-old row unreadable — so this is a
|
|
22
|
+
* state to render, never a reason to hide the row.
|
|
23
|
+
*/
|
|
24
|
+
revoked: boolean;
|
|
25
|
+
createdBy: string;
|
|
26
|
+
createdAt?: string | null;
|
|
27
|
+
/** When the key was last replaced, so a listing can show a stale one. */
|
|
28
|
+
keyRotatedAt?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A service agent as it comes back from a write, with the key.
|
|
32
|
+
*
|
|
33
|
+
* The key is present exactly twice in this API — creating and rotating —
|
|
34
|
+
* and nowhere else, ever.
|
|
35
|
+
*/
|
|
36
|
+
export interface ServiceAgentWithKey extends ServiceAgent {
|
|
37
|
+
key: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* One organization's service agents, revoked ones included.
|
|
41
|
+
*
|
|
42
|
+
* Included because hiding them makes a revoked agent invisible to whoever
|
|
43
|
+
* is deciding whether it is still needed, while its audit rows still name
|
|
44
|
+
* it. Any member of the organization may read this; only owners may write.
|
|
45
|
+
*/
|
|
46
|
+
export declare const listServiceAgents: (token: string, orgUid: string, baseUrl?: string) => Promise<ServiceAgent[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Create one. **The key is in this answer and in no other.**
|
|
49
|
+
*
|
|
50
|
+
* Scopes are sent as the array the caller holds; IAM joins and validates
|
|
51
|
+
* them, and refuses one that is not grantable to a principal that is not a
|
|
52
|
+
* person.
|
|
53
|
+
*/
|
|
54
|
+
export declare const createServiceAgent: (token: string, orgUid: string, agent: {
|
|
55
|
+
name: string;
|
|
56
|
+
scopes: string[];
|
|
57
|
+
description?: string;
|
|
58
|
+
teamUid?: string;
|
|
59
|
+
}, baseUrl?: string) => Promise<ServiceAgentWithKey>;
|
|
60
|
+
/**
|
|
61
|
+
* Replace the agent's key. The old one stops working with this call.
|
|
62
|
+
*
|
|
63
|
+
* No grace period, which is the point of rotating: a leaked key that still
|
|
64
|
+
* works for an hour is a leaked key that still works.
|
|
65
|
+
*/
|
|
66
|
+
export declare const rotateServiceAgentKey: (token: string, orgUid: string, agentUid: string, baseUrl?: string) => Promise<ServiceAgentWithKey>;
|
|
67
|
+
/** Stop the agent, keeping it readable for its audit. */
|
|
68
|
+
export declare const revokeServiceAgent: (token: string, orgUid: string, agentUid: string, baseUrl?: string) => Promise<ServiceAgent>;
|