@taskforcehq/taskforce 0.3.304 → 0.3.306
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 +140 -247
- package/dist/Taskforce.module.css +295 -89
- package/dist/TaskforceCore.js +378 -111
- package/dist/TaskforceCore.test.js +1221 -107
- package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/assets/fonts/Noir_medium.woff2 +0 -0
- package/dist/assets/fonts/Noir_regular.woff2 +0 -0
- package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/compat/workspaceSyncCompat.js +52 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +549 -0
- package/dist/components/features/AgentsModule.d.ts +10 -1
- package/dist/components/features/AgentsModule.js +260 -15
- package/dist/components/features/AgentsModule.test.js +255 -5
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +6 -2
- package/dist/components/features/DocumentViewer.js +90 -10
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +226 -6
- package/dist/components/features/TaskSettings.js +29 -3
- package/dist/components/features/TaskSettings.test.js +42 -1
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskCard.js +19 -28
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskForm.d.ts +8 -8
- package/dist/components/task/TaskForm.js +362 -230
- package/dist/components/task/TaskForm.test.js +558 -381
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +96 -14
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +70 -17
- package/dist/components/views/PlanComparisonPage.test.js +289 -41
- package/dist/components/views/PlansPage.js +239 -106
- package/dist/components/views/PlansPage.test.js +593 -42
- package/dist/components/views/StandaloneLayout.js +310 -554
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
- package/dist/components/views/panels/PlanningDrawer.js +18 -11
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
- package/dist/components/views/planningScope.d.ts +20 -0
- package/dist/components/views/planningScope.js +25 -0
- package/dist/components/views/planningScope.test.d.ts +1 -0
- package/dist/components/views/planningScope.test.js +60 -0
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +27 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
- package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
- package/dist/config/envSchema.js +1 -1
- package/dist/core/AiProfileService.d.ts +45 -3
- package/dist/core/AiProfileService.js +774 -63
- package/dist/core/AiProfileService.test.js +22 -2
- package/dist/core/AiProfiles.test.js +761 -2
- package/dist/core/AttachmentLinkService.js +57 -15
- package/dist/core/AuthIdentityService.d.ts +107 -0
- package/dist/core/AuthIdentityService.js +284 -0
- package/dist/core/AuthTokenService.d.ts +4 -0
- package/dist/core/AuthTokenService.js +34 -6
- package/dist/core/AuthTokenService.test.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/EntitlementsPolicy.test.js +77 -15
- package/dist/core/GlobalSettingsService.js +115 -6
- package/dist/core/PlanEntitlementService.d.ts +30 -3
- package/dist/core/PlanEntitlementService.js +454 -93
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +54 -28
- package/dist/core/PlanningEntities.test.js +52 -0
- package/dist/core/SignupMonetizationSettings.test.js +241 -44
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +244 -88
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +228 -14
- package/dist/core/Taskforce.js +814 -201
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
- package/dist/core/WorkspaceLifecycleService.js +0 -5
- package/dist/core/WorkspacePermissions.test.js +25 -1
- package/dist/core/WorkspacePlanMode.test.js +128 -27
- package/dist/core/shared.d.ts +3 -1
- package/dist/core/shared.js +16 -1
- package/dist/core/types.d.ts +68 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
- package/dist/hooks/sync/auth.js +3 -1
- package/dist/hooks/sync/bootstrap.js +2 -0
- package/dist/hooks/sync/controlPlane.d.ts +37 -0
- package/dist/hooks/sync/controlPlane.js +78 -0
- package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
- package/dist/hooks/sync/controlPlane.test.js +121 -0
- package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
- package/dist/hooks/sync/lifecyclePolicy.js +93 -0
- package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
- package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
- package/dist/hooks/sync/orchestratorShared.js +68 -47
- package/dist/hooks/sync/orchestratorShared.test.js +50 -1
- package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
- package/dist/hooks/sync/pullLifecycle.js +24 -0
- package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
- package/dist/hooks/sync/pullLifecycle.test.js +80 -0
- package/dist/hooks/sync/recovery.d.ts +16 -2
- package/dist/hooks/sync/recovery.js +171 -53
- package/dist/hooks/sync/recovery.test.d.ts +1 -0
- package/dist/hooks/sync/recovery.test.js +292 -0
- package/dist/hooks/sync/transfers.d.ts +16 -3
- package/dist/hooks/sync/transfers.js +186 -65
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +396 -0
- package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
- package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
- package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
- package/dist/hooks/sync/useSyncStatusActions.js +88 -0
- package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
- package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
- package/dist/hooks/sync/useSyncStatusControls.js +60 -0
- package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
- package/dist/hooks/useSyncOrchestrator.js +424 -175
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +12 -1
- package/dist/hooks/useTaskMutations.test.js +30 -1
- package/dist/hooks/useTaskforce.d.ts +65 -4
- package/dist/hooks/useTaskforce.js +564 -243
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
- package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
- package/dist/hooks/useWorkspaceSyncController.js +17 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
- package/dist/localization/locales/en-US.d.ts +0 -1
- package/dist/localization/locales/en-US.js +0 -1
- package/dist/localization/locales/es-419.js +0 -1
- package/dist/localization/locales/pt-BR.js +0 -1
- package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/runtime.d.ts +2 -0
- package/dist/mcp/runtime.js +2433 -3534
- package/dist/mcp/runtime.test.js +440 -2
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +171 -61
- package/dist/migrations/taskSchemaMigrations.test.js +15 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/dist/resources/templates/workflows/collaborate.yaml +1 -1
- package/dist/resources/templates/workflows/evaluate.yaml +2 -2
- package/dist/resources/templates/workflows/plan.yaml +1 -1
- package/dist/resources/templates/workflows/review.yaml +2 -2
- package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
- package/dist/server/auth/providers/apple.d.ts +33 -0
- package/dist/server/auth/providers/apple.js +82 -0
- package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
- package/dist/server/auth/providers/appleClientSecret.js +65 -0
- package/dist/server/auth/providers/github.d.ts +26 -0
- package/dist/server/auth/providers/github.js +86 -0
- package/dist/server/auth/providers/google.d.ts +21 -0
- package/dist/server/auth/providers/google.js +56 -0
- package/dist/server/auth/providers/types.d.ts +21 -0
- package/dist/server/auth/providers/types.js +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +6 -3
- package/dist/server/documentReviewRoutes.test.js +36 -3
- package/dist/server/index.cookieProxy.test.js +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +120 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +106 -3
- package/dist/server/routes/admin.d.ts +4 -5
- package/dist/server/routes/admin.js +410 -80
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +16 -6
- package/dist/server/routes/auth.js +1015 -118
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +276 -34
- package/dist/server/routes/billing.test.js +760 -52
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +242 -74
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +29 -3
- package/dist/server/routes/shared.js +69 -4
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.integration.test.js +437 -39
- package/dist/server/routes/sync.js +62 -606
- package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
- package/dist/server/routes/syncAuxRoutes.js +91 -0
- package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
- package/dist/server/routes/syncAuxRoutes.test.js +158 -0
- package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
- package/dist/server/routes/syncPullApplyRoutes.js +204 -0
- package/dist/server/routes/syncPushRoutes.d.ts +24 -0
- package/dist/server/routes/syncPushRoutes.js +212 -0
- package/dist/server/routes/syncRouteGuards.d.ts +36 -0
- package/dist/server/routes/syncRouteGuards.js +67 -0
- package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
- package/dist/server/routes/syncRouteGuards.test.js +94 -0
- package/dist/server/routes/syncRouteTypes.d.ts +13 -0
- package/dist/server/routes/syncRouteTypes.js +1 -0
- package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
- package/dist/server/routes/syncSnapshotRoutes.js +180 -0
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +44 -2
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +37 -6
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +136 -165
- package/dist/server/routes.test.js +2457 -162
- package/dist/services/workflowExportSnapshots.test.js +2 -0
- package/dist/shared/aiProfileSeatScope.d.ts +5 -0
- package/dist/shared/aiProfileSeatScope.js +21 -0
- package/dist/shared/passwordPolicy.d.ts +13 -0
- package/dist/shared/passwordPolicy.js +84 -0
- package/dist/shared/passwordPolicy.test.d.ts +1 -0
- package/dist/shared/passwordPolicy.test.js +34 -0
- package/dist/storage/workspaceAssetStore.d.ts +15 -3
- package/dist/storage/workspaceAssetStore.js +132 -44
- package/dist/storage/workspaceAssetStore.test.js +93 -6
- package/dist/styles/fonts.css +70 -0
- package/dist/sync/collaborationSyncPayload.d.ts +6 -1
- package/dist/sync/collaborationSyncPayload.js +17 -11
- package/dist/sync/collaborationSyncPayload.test.js +13 -1
- package/dist/sync/contentSyncState.d.ts +4 -8
- package/dist/sync/contentSyncState.js +33 -77
- package/dist/sync/syncApplyHandlers.d.ts +7 -0
- package/dist/sync/syncApplyHandlers.js +28 -13
- package/dist/sync/syncApplyHandlers.test.js +72 -3
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +44 -0
- package/dist/sync/syncResourceAdapters.js +77 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +60 -0
- package/dist/sync/syncService.test.js +71 -3
- package/dist/sync/taskSyncChangeKey.d.ts +2 -0
- package/dist/sync/taskSyncChangeKey.js +143 -0
- package/dist/sync/taskSyncPayload.js +3 -8
- package/dist/sync/workspacePullFeed.js +4 -3
- package/dist/sync/workspacePullFeed.test.js +43 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +48 -0
- package/dist/sync/workspaceSyncModel.js +195 -31
- package/dist/sync/workspaceSyncModel.test.js +325 -12
- package/dist/sync/workspaceSyncState.d.ts +19 -0
- package/dist/sync/workspaceSyncState.js +3 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +17 -0
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
- package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
- package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
- package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.js} +1 -1
- package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
- package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
- package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
- package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
- package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
- package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
- package/dist/ui/assets/TaskSettings-DZX4jk7e.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
- package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
- package/dist/ui/assets/index-C6k75jr8.js +6 -0
- package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.js} +1 -1
- package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/ui/fonts/Noir_medium.otf +0 -0
- package/dist/ui/fonts/Noir_medium.woff2 +0 -0
- package/dist/ui/fonts/Noir_regular.otf +0 -0
- package/dist/ui/fonts/Noir_regular.woff2 +0 -0
- package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/assignees.d.ts +2 -0
- package/dist/utils/assignees.js +2 -0
- package/dist/utils/avatarUpload.d.ts +27 -0
- package/dist/utils/avatarUpload.js +132 -0
- package/dist/utils/avatarUpload.test.d.ts +1 -0
- package/dist/utils/avatarUpload.test.js +40 -0
- package/dist/utils/bootstrapTrace.d.ts +7 -0
- package/dist/utils/bootstrapTrace.js +29 -0
- package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +199 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/syncEventDetails.d.ts +3 -0
- package/dist/utils/syncEventDetails.js +64 -0
- package/dist/utils/syncEventDetails.test.d.ts +1 -0
- package/dist/utils/syncEventDetails.test.js +23 -0
- package/dist/utils/syncEventPresentation.d.ts +15 -0
- package/dist/utils/syncEventPresentation.js +129 -0
- package/dist/utils/syncEventPresentation.test.d.ts +1 -0
- package/dist/utils/syncEventPresentation.test.js +64 -0
- package/dist/utils/syncStatusPresentation.d.ts +72 -0
- package/dist/utils/syncStatusPresentation.js +217 -0
- package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
- package/dist/utils/syncStatusPresentation.test.js +164 -0
- package/dist/utils/taskActivity.d.ts +2 -0
- package/dist/utils/taskActivity.js +228 -22
- package/dist/utils/taskActivity.test.js +119 -8
- package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.js +68 -2
- package/dist/utils/workspaceSyncPresentation.test.js +36 -1
- package/package.json +10 -2
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/playwright-auth.sh +5 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- package/scripts/run-e2e-realtime.sh +17 -3
- package/scripts/run-smoke.sh +17 -5
- package/scripts/run-soak.sh +17 -5
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/src/resources/templates/workflows/collaborate.yaml +1 -1
- package/src/resources/templates/workflows/evaluate.yaml +2 -2
- package/src/resources/templates/workflows/plan.yaml +1 -1
- package/src/resources/templates/workflows/review.yaml +2 -2
- package/dist/ui/assets/AgentsModule-BLWVbuKP.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
- package/dist/ui/assets/index-DXUdtH1B.js +0 -6
- package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
- package/scripts/migrate-planning-model.ts +0 -233
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Routes registered here:
|
|
9
9
|
* GET/POST /api/platform/plans
|
|
10
|
+
* GET /api/platform/onboarding-plan-options
|
|
10
11
|
* GET/POST /api/platform/plans/:planId/versions
|
|
11
12
|
* GET /api/platform/features
|
|
12
13
|
* GET/PATCH /api/platform/plans/:planId/versions/:versionId/features
|
|
@@ -23,6 +24,8 @@
|
|
|
23
24
|
* GET/POST /api/taskforce/admin/email-settings
|
|
24
25
|
* GET /api/taskforce/admin/email-settings/health
|
|
25
26
|
* POST /api/taskforce/admin/email-settings/test
|
|
27
|
+
* GET/POST /api/taskforce/admin/auth-provider-settings
|
|
28
|
+
* GET /api/taskforce/admin/auth-provider-settings/health
|
|
26
29
|
* GET/POST /api/taskforce/admin/system-settings
|
|
27
30
|
* GET/POST /api/taskforce/admin/object-storage-settings
|
|
28
31
|
* GET /api/taskforce/admin/object-storage-telemetry
|
|
@@ -50,9 +53,9 @@
|
|
|
50
53
|
import * as fs from 'fs';
|
|
51
54
|
import * as path from 'path';
|
|
52
55
|
import { TaskforceRuleError } from '../../core/Taskforce.js';
|
|
53
|
-
import { parseJsonBody } from '
|
|
56
|
+
import { escapeHtml, parseFormBody, parseJsonBody } from './primitives.js';
|
|
54
57
|
import { resolveRequestAccess } from '../auth.js';
|
|
55
|
-
import {
|
|
58
|
+
import { sendEmail } from '../email.js';
|
|
56
59
|
import { WorkspaceAssetStore } from '../../storage/workspaceAssetStore.js';
|
|
57
60
|
import { scanDocumentIntegrity } from '../../storage/documentIntegrity.js';
|
|
58
61
|
import { normalizeStorageIntegrityScheduleSettings, resolveStorageIntegrityScheduleSettings, } from '../../storage/integritySchedule.js';
|
|
@@ -64,67 +67,19 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
|
|
|
64
67
|
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
65
68
|
import { randomUUID } from 'crypto';
|
|
66
69
|
import { resolveDeploymentConfig } from '../../config/deployment.js';
|
|
67
|
-
import { getTaskforceCloudEnvironmentConfig, resolveTaskforceCloudEnvironmentFromBaseUrl } from '../../config/cloudEnvironment.js';
|
|
70
|
+
import { getTaskforceCloudEnvironmentConfig, resolveTaskforceCloudEnvironmentFromBaseUrl, resolveTaskforceMcpBaseUrlFromBaseUrl } from '../../config/cloudEnvironment.js';
|
|
68
71
|
import { buildCloudMcpRuntimeAuth, resolveErrorStatusCode } from './shared.js';
|
|
72
|
+
import { buildAuthBehavior, buildSiteBehavior, getRouteEmailConfig, resolvePublicAuthBaseUrl, resolveRuntimeConfigBaseUrl, } from './authSupport.js';
|
|
69
73
|
import { applyWorkspaceRepair, scanWorkspaceRepair } from '../../sync/workspaceRepair.js';
|
|
74
|
+
import { testMintAppleClientSecret } from '../auth/providers/appleClientSecret.js';
|
|
70
75
|
// === SECTION: Registration ===
|
|
71
76
|
export function registerAdminRoutes(deps) {
|
|
72
|
-
const { addRoute, core, context, requestWorkspaceId, requestUserId, requestRole, requestHeader, requestRuntimeMode, ensureAppAccess, ensureAdminRole, ensureCloudPlanData, requireCloudRuntime, resolveAuthenticatedUserId, resolveAdminRequestActor, auditAdminAction, resolveEffectiveObjectStorageConfig, getObjectStorageClient, taskAssetStore, normalizeDocumentPathInput, ensureWithinDir, getAssetMetadata, markAssetDeleted, clearAssetDeleted, removeAssetMetadata, getStorageTelemetry, appendStorageTelemetry, getStorageIntegrityHistory, appendStorageIntegrityHistory, getDocumentPurgeHistory, appendDocumentPurgeHistory, getCollaborationTelemetry, isCollaborationPolicyEnabled,
|
|
77
|
+
const { addRoute, core, context, requestWorkspaceId, requestUserId, requestRole, requestHeader, requestRuntimeMode, ensureAppAccess, ensureAdminRole, ensureCloudPlanData, requireCloudRuntime, resolveAuthenticatedUserId, resolveAdminRequestActor, auditAdminAction, resolveEffectiveObjectStorageConfig, getObjectStorageClient, taskAssetStore, normalizeDocumentPathInput, ensureWithinDir, getAssetMetadata, markAssetDeleted, clearAssetDeleted, removeAssetMetadata, getStorageTelemetry, appendStorageTelemetry, getStorageIntegrityHistory, appendStorageIntegrityHistory, getDocumentPurgeHistory, appendDocumentPurgeHistory, getCollaborationTelemetry, isCollaborationPolicyEnabled, normalizeMcpOauthScopeString, MCP_TOKEN_SCOPE_VALUES, MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS, MCP_WRITE_RATE_LIMIT_ENABLED, MCP_WRITE_RATE_LIMIT_ACTOR_MAX_REQUESTS, MCP_WRITE_RATE_LIMIT_WORKSPACE_MAX_REQUESTS, MCP_WRITE_RATE_LIMIT_WINDOW_MS, } = deps;
|
|
73
78
|
const baseVirusScanConfig = resolveVirusScanConfigFromEnv(process.env);
|
|
74
79
|
const workspaceAssetStore = typeof core.getDatabaseAdapter === 'function' && typeof core.getTenantId === 'function'
|
|
75
80
|
? new WorkspaceAssetStore(core.getDatabaseAdapter(), core.getTenantId())
|
|
76
81
|
: null;
|
|
77
82
|
// === SECTION: Email helpers ===
|
|
78
|
-
const getEmailConfig = () => {
|
|
79
|
-
if (context.authConfig?.runtimeMode !== 'cloud') {
|
|
80
|
-
return resolveEffectiveEmailConfig(process.env, { provider: 'console' });
|
|
81
|
-
}
|
|
82
|
-
const globalSettings = core.getGlobalSettings();
|
|
83
|
-
return resolveEffectiveEmailConfig(process.env, globalSettings.email || null);
|
|
84
|
-
};
|
|
85
|
-
const resolveBooleanSetting = (value, fallback) => {
|
|
86
|
-
if (typeof value === 'boolean')
|
|
87
|
-
return value;
|
|
88
|
-
if (typeof value === 'number')
|
|
89
|
-
return value !== 0;
|
|
90
|
-
const normalized = String(value || '').trim().toLowerCase();
|
|
91
|
-
if (!normalized)
|
|
92
|
-
return fallback;
|
|
93
|
-
if (['1', 'true', 'yes', 'on'].includes(normalized))
|
|
94
|
-
return true;
|
|
95
|
-
if (['0', 'false', 'no', 'off'].includes(normalized))
|
|
96
|
-
return false;
|
|
97
|
-
return fallback;
|
|
98
|
-
};
|
|
99
|
-
const getAuthBehavior = () => {
|
|
100
|
-
const globalSettings = core.getGlobalSettings();
|
|
101
|
-
const authSettings = globalSettings.auth || {};
|
|
102
|
-
const authRateLimitMaxRequestsRaw = Number(authSettings.authRateLimitMaxRequests);
|
|
103
|
-
const authRateLimitWindowMsRaw = Number(authSettings.authRateLimitWindowMs);
|
|
104
|
-
const onboardingPolicy = core.getOnboardingPolicy();
|
|
105
|
-
return {
|
|
106
|
-
allowSelfRegistration: resolveBooleanSetting(authSettings.allowSelfRegistration, true),
|
|
107
|
-
requireVerifiedEmail: resolveBooleanSetting(authSettings.requireVerifiedEmail, true),
|
|
108
|
-
defaultNewUserBetaAccess: resolveBooleanSetting(authSettings.defaultNewUserBetaAccess, false),
|
|
109
|
-
authRateLimitEnabled: resolveBooleanSetting(authSettings.authRateLimitEnabled, true),
|
|
110
|
-
authRateLimitMaxRequests: Number.isFinite(authRateLimitMaxRequestsRaw) && authRateLimitMaxRequestsRaw >= 1
|
|
111
|
-
? Math.floor(authRateLimitMaxRequestsRaw)
|
|
112
|
-
: 10,
|
|
113
|
-
authRateLimitWindowMs: Number.isFinite(authRateLimitWindowMsRaw) && authRateLimitWindowMsRaw >= 1000
|
|
114
|
-
? Math.floor(authRateLimitWindowMsRaw)
|
|
115
|
-
: 15 * 60_000,
|
|
116
|
-
onboardingPolicyMode: onboardingPolicy.mode,
|
|
117
|
-
onboardingPlanVersionId: onboardingPolicy.planVersionId
|
|
118
|
-
};
|
|
119
|
-
};
|
|
120
|
-
const getSiteBehavior = () => {
|
|
121
|
-
const globalSettings = core.getGlobalSettings();
|
|
122
|
-
const siteSettings = globalSettings.site || {};
|
|
123
|
-
return {
|
|
124
|
-
showRunTaskforceLocally: resolveBooleanSetting(siteSettings.showRunTaskforceLocally, true),
|
|
125
|
-
pricingPageEnabled: resolveBooleanSetting(siteSettings.pricingPageEnabled, true)
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
83
|
const resolveEffectiveVirusScanSettings = () => {
|
|
129
84
|
const settings = core.getGlobalSettings().objectStorage || {};
|
|
130
85
|
const asyncEnabled = typeof settings.virusScanAsyncEnabled === 'boolean'
|
|
@@ -139,6 +94,7 @@ export function registerAdminRoutes(deps) {
|
|
|
139
94
|
};
|
|
140
95
|
};
|
|
141
96
|
// === SECTION: MCP helpers ===
|
|
97
|
+
const MCP_CONNECTION_TEST_TIMEOUT_MS = 5000;
|
|
142
98
|
const writeMcpHttpError = (res, statusCode, message) => {
|
|
143
99
|
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
144
100
|
res.end(JSON.stringify({
|
|
@@ -171,6 +127,112 @@ export function registerAdminRoutes(deps) {
|
|
|
171
127
|
const resolveMcpOauthTokenUrl = (req) => `${resolveMcpOauthIssuer(req)}/oauth/mcp/token`;
|
|
172
128
|
const resolveMcpOauthRegisterUrl = (req) => `${resolveMcpOauthIssuer(req)}/oauth/mcp/register`;
|
|
173
129
|
const resolveMcpOauthResourceUrl = (req) => `${resolveMcpOauthIssuer(req)}/mcp`;
|
|
130
|
+
const resolveCloudMcpEndpoint = (req) => {
|
|
131
|
+
const requestBaseUrl = resolveRuntimeConfigBaseUrl(req);
|
|
132
|
+
const deployment = resolveDeploymentConfig(process.env, { requestBaseUrl });
|
|
133
|
+
const inferredMcpBaseUrl = resolveTaskforceMcpBaseUrlFromBaseUrl(deployment.cloudMcpBaseUrl
|
|
134
|
+
|| deployment.cloudAuthBaseUrl
|
|
135
|
+
|| deployment.cloudBaseUrl
|
|
136
|
+
|| requestBaseUrl
|
|
137
|
+
|| '');
|
|
138
|
+
const baseUrl = String(inferredMcpBaseUrl || deployment.cloudMcpBaseUrl || resolveMcpOauthIssuer(req)).trim().replace(/\/+$/, '');
|
|
139
|
+
return `${baseUrl}/mcp`;
|
|
140
|
+
};
|
|
141
|
+
const probeCloudMcpEndpoint = async (req, token) => {
|
|
142
|
+
const endpoint = resolveCloudMcpEndpoint(req);
|
|
143
|
+
const controller = new AbortController();
|
|
144
|
+
const timeout = setTimeout(() => controller.abort(), MCP_CONNECTION_TEST_TIMEOUT_MS);
|
|
145
|
+
try {
|
|
146
|
+
const response = await fetch(endpoint, {
|
|
147
|
+
method: 'POST',
|
|
148
|
+
headers: {
|
|
149
|
+
Authorization: `Bearer ${token}`,
|
|
150
|
+
Accept: 'application/json, text/event-stream',
|
|
151
|
+
'Content-Type': 'application/json'
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify({
|
|
154
|
+
jsonrpc: '2.0',
|
|
155
|
+
id: `mcp-connection-test-${randomUUID()}`,
|
|
156
|
+
method: 'initialize',
|
|
157
|
+
params: {
|
|
158
|
+
protocolVersion: '2025-03-26',
|
|
159
|
+
capabilities: {},
|
|
160
|
+
clientInfo: {
|
|
161
|
+
name: 'taskforce-settings-test',
|
|
162
|
+
version: '1.0.0'
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}),
|
|
166
|
+
signal: controller.signal
|
|
167
|
+
});
|
|
168
|
+
const responseText = await response.text();
|
|
169
|
+
let payload = null;
|
|
170
|
+
try {
|
|
171
|
+
payload = responseText ? JSON.parse(responseText) : null;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
payload = null;
|
|
175
|
+
}
|
|
176
|
+
const remoteMessage = typeof payload?.error?.message === 'string'
|
|
177
|
+
? payload.error.message.trim()
|
|
178
|
+
: '';
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
if (response.status >= 500) {
|
|
181
|
+
return {
|
|
182
|
+
ok: false,
|
|
183
|
+
statusCode: 502,
|
|
184
|
+
code: 'MCP_ENDPOINT_GATEWAY_ERROR',
|
|
185
|
+
error: `Cloud MCP endpoint ${endpoint} returned ${response.status}. The dedicated MCP host may be degraded or unavailable.`,
|
|
186
|
+
details: {
|
|
187
|
+
endpoint,
|
|
188
|
+
upstreamStatus: response.status,
|
|
189
|
+
remoteMessage: remoteMessage || null
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
statusCode: 502,
|
|
196
|
+
code: 'MCP_ENDPOINT_REJECTED_VALIDATED_TOKEN',
|
|
197
|
+
error: `Cloud MCP endpoint ${endpoint} rejected a token that validated locally. This usually means the MCP service is stale, routed incorrectly, or out of sync with the auth database.`,
|
|
198
|
+
details: {
|
|
199
|
+
endpoint,
|
|
200
|
+
upstreamStatus: response.status,
|
|
201
|
+
remoteMessage: remoteMessage || null
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
ok: true,
|
|
207
|
+
endpoint,
|
|
208
|
+
serverName: typeof payload?.result?.serverInfo?.name === 'string'
|
|
209
|
+
? payload.result.serverInfo.name
|
|
210
|
+
: null,
|
|
211
|
+
protocolVersion: typeof payload?.result?.protocolVersion === 'string'
|
|
212
|
+
? payload.result.protocolVersion
|
|
213
|
+
: null
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
const timedOut = error?.name === 'AbortError';
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
statusCode: 502,
|
|
221
|
+
code: timedOut ? 'MCP_ENDPOINT_TIMEOUT' : 'MCP_ENDPOINT_UNREACHABLE',
|
|
222
|
+
error: timedOut
|
|
223
|
+
? `Cloud MCP endpoint ${endpoint} did not respond within ${MCP_CONNECTION_TEST_TIMEOUT_MS}ms.`
|
|
224
|
+
: `Could not reach cloud MCP endpoint ${endpoint}. The dedicated MCP host may be unavailable or misconfigured.`,
|
|
225
|
+
details: {
|
|
226
|
+
endpoint,
|
|
227
|
+
timeoutMs: MCP_CONNECTION_TEST_TIMEOUT_MS,
|
|
228
|
+
reason: String(error?.message || error || '')
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
clearTimeout(timeout);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
174
236
|
const renderMcpOauthAuthorizePage = (input) => {
|
|
175
237
|
const options = input.workspaces.map((workspace) => {
|
|
176
238
|
const selected = workspace.id === input.preselectedWorkspaceId ? ' selected' : '';
|
|
@@ -513,6 +575,18 @@ export function registerAdminRoutes(deps) {
|
|
|
513
575
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
514
576
|
res.end(JSON.stringify({ success: true, plans }));
|
|
515
577
|
});
|
|
578
|
+
addRoute('GET', '/api/platform/onboarding-plan-options', async (req, res) => {
|
|
579
|
+
if (!ensureCloudPlanData(req, res))
|
|
580
|
+
return;
|
|
581
|
+
if (!ensureAdminRole(req)) {
|
|
582
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
583
|
+
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const options = core.listOnboardingPlanOptions();
|
|
587
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
588
|
+
res.end(JSON.stringify({ success: true, options }));
|
|
589
|
+
});
|
|
516
590
|
addRoute('POST', '/api/platform/plans', async (req, res) => {
|
|
517
591
|
if (!ensureCloudPlanData(req, res))
|
|
518
592
|
return;
|
|
@@ -522,10 +596,19 @@ export function registerAdminRoutes(deps) {
|
|
|
522
596
|
return;
|
|
523
597
|
}
|
|
524
598
|
const body = await parseJsonBody(req);
|
|
599
|
+
const description = body?.description === undefined || body?.description === null
|
|
600
|
+
? body?.description
|
|
601
|
+
: String(body.description);
|
|
602
|
+
if (typeof description === 'string' && description.trim().length > 240) {
|
|
603
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
604
|
+
res.end(JSON.stringify({ success: false, error: 'Plan description must be 240 characters or fewer.', code: 'PLAN_DESCRIPTION_TOO_LONG' }));
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
525
607
|
try {
|
|
526
608
|
const plan = core.upsertPlanCatalog({
|
|
527
609
|
planId: body?.planId,
|
|
528
610
|
displayName: body?.displayName,
|
|
611
|
+
description,
|
|
529
612
|
status: body?.status,
|
|
530
613
|
initialMode: body?.initialMode,
|
|
531
614
|
initialTrialDays: body?.initialTrialDays === undefined ? undefined : Number(body?.initialTrialDays),
|
|
@@ -581,6 +664,62 @@ export function registerAdminRoutes(deps) {
|
|
|
581
664
|
res.end(JSON.stringify({ success: false, error: String(error?.message || 'Unable to list feature catalog'), code: error?.code }));
|
|
582
665
|
}
|
|
583
666
|
});
|
|
667
|
+
addRoute('PATCH', '/api/platform/features/:featureKey', async (req, res, params) => {
|
|
668
|
+
if (!ensureCloudPlanData(req, res))
|
|
669
|
+
return;
|
|
670
|
+
if (!ensureAdminRole(req)) {
|
|
671
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
672
|
+
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
const body = await parseJsonBody(req);
|
|
676
|
+
const featureKey = String(params.featureKey || '').trim();
|
|
677
|
+
const publicLabel = body?.publicLabel === undefined || body?.publicLabel === null
|
|
678
|
+
? body?.publicLabel
|
|
679
|
+
: String(body.publicLabel);
|
|
680
|
+
const publicDescription = body?.publicDescription === undefined || body?.publicDescription === null
|
|
681
|
+
? body?.publicDescription
|
|
682
|
+
: String(body.publicDescription);
|
|
683
|
+
const publicDisplayOrder = body?.publicDisplayOrder === undefined || body?.publicDisplayOrder === null || body?.publicDisplayOrder === ''
|
|
684
|
+
? null
|
|
685
|
+
: Math.max(0, Math.floor(Number(body.publicDisplayOrder)));
|
|
686
|
+
if (typeof publicLabel === 'string' && publicLabel.trim().length > 120) {
|
|
687
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
688
|
+
res.end(JSON.stringify({ success: false, error: 'Public label must be 120 characters or fewer.', code: 'PLAN_FEATURE_PUBLIC_LABEL_TOO_LONG' }));
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
if (typeof publicDescription === 'string' && publicDescription.trim().length > 280) {
|
|
692
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
693
|
+
res.end(JSON.stringify({ success: false, error: 'Public description must be 280 characters or fewer.', code: 'PLAN_FEATURE_PUBLIC_DESCRIPTION_TOO_LONG' }));
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (publicDisplayOrder !== null && !Number.isFinite(publicDisplayOrder)) {
|
|
697
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
698
|
+
res.end(JSON.stringify({ success: false, error: 'Public display order must be a non-negative number.', code: 'PLAN_FEATURE_PUBLIC_DISPLAY_ORDER_INVALID' }));
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
try {
|
|
702
|
+
const feature = core.updatePlanFeatureCatalogMarketingCopy({
|
|
703
|
+
featureKey,
|
|
704
|
+
publicLabel,
|
|
705
|
+
publicDescription,
|
|
706
|
+
publicDisplayOrder
|
|
707
|
+
});
|
|
708
|
+
auditAdminAction(req, 'platform-plan-feature-catalog-updated', {
|
|
709
|
+
featureKey,
|
|
710
|
+
publicLabel: feature.publicLabel ?? null,
|
|
711
|
+
publicDescription: feature.publicDescription ?? null,
|
|
712
|
+
publicDisplayOrder: feature.publicDisplayOrder ?? null
|
|
713
|
+
});
|
|
714
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
715
|
+
res.end(JSON.stringify({ success: true, feature }));
|
|
716
|
+
}
|
|
717
|
+
catch (error) {
|
|
718
|
+
const statusCode = resolveErrorStatusCode(error, 400);
|
|
719
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
720
|
+
res.end(JSON.stringify({ success: false, error: String(error?.message || 'Unable to update feature catalog entry'), code: error?.code }));
|
|
721
|
+
}
|
|
722
|
+
});
|
|
584
723
|
addRoute('POST', '/api/platform/plans/:planId/versions', async (req, res, params) => {
|
|
585
724
|
if (!ensureCloudPlanData(req, res))
|
|
586
725
|
return;
|
|
@@ -797,9 +936,23 @@ export function registerAdminRoutes(deps) {
|
|
|
797
936
|
res.end(JSON.stringify({ error: 'Forbidden: system admin role required.' }));
|
|
798
937
|
return;
|
|
799
938
|
}
|
|
800
|
-
const
|
|
939
|
+
const reqUrl = new URL(req.url || '/api/taskforce/admin/system-users', 'http://localhost');
|
|
940
|
+
const query = String(reqUrl.searchParams.get('q') || '').trim();
|
|
941
|
+
const sort = reqUrl.searchParams.get('sort') === 'oldest' ? 'oldest' : 'newest';
|
|
942
|
+
const limitRaw = Number(reqUrl.searchParams.get('limit') || '50');
|
|
943
|
+
const offsetRaw = Number(reqUrl.searchParams.get('offset') || '0');
|
|
944
|
+
const limit = Number.isFinite(limitRaw) ? Math.max(1, Math.min(200, Math.floor(limitRaw))) : 50;
|
|
945
|
+
const offset = Number.isFinite(offsetRaw) ? Math.max(0, Math.floor(offsetRaw)) : 0;
|
|
946
|
+
const total = core.countSystemUsers({ query });
|
|
947
|
+
const users = core.listSystemUsers({ query, sort, limit, offset });
|
|
801
948
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
802
|
-
res.end(JSON.stringify({
|
|
949
|
+
res.end(JSON.stringify({
|
|
950
|
+
users,
|
|
951
|
+
total,
|
|
952
|
+
limit,
|
|
953
|
+
offset,
|
|
954
|
+
hasMore: offset + users.length < total
|
|
955
|
+
}));
|
|
803
956
|
});
|
|
804
957
|
// GET /api/taskforce/admin/audit-logs - Read recent admin audit events
|
|
805
958
|
addRoute('GET', '/api/taskforce/admin/audit-logs', async (req, res) => {
|
|
@@ -1013,7 +1166,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1013
1166
|
return;
|
|
1014
1167
|
}
|
|
1015
1168
|
if (context.authConfig?.runtimeMode !== 'cloud') {
|
|
1016
|
-
const effective =
|
|
1169
|
+
const effective = getRouteEmailConfig(core, context);
|
|
1017
1170
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1018
1171
|
res.end(JSON.stringify({
|
|
1019
1172
|
settings: { provider: 'console', from: effective.from, replyTo: '' },
|
|
@@ -1022,7 +1175,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1022
1175
|
return;
|
|
1023
1176
|
}
|
|
1024
1177
|
const settings = core.getGlobalSettings().email || {};
|
|
1025
|
-
const effective =
|
|
1178
|
+
const effective = getRouteEmailConfig(core, context);
|
|
1026
1179
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1027
1180
|
res.end(JSON.stringify({
|
|
1028
1181
|
settings: {
|
|
@@ -1047,7 +1200,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1047
1200
|
return;
|
|
1048
1201
|
}
|
|
1049
1202
|
const settings = core.getGlobalSettings().email || {};
|
|
1050
|
-
const effective =
|
|
1203
|
+
const effective = getRouteEmailConfig(core, context);
|
|
1051
1204
|
const keyRequired = effective.provider === 'resend' || effective.provider === 'google-workspace';
|
|
1052
1205
|
const ready = keyRequired ? Boolean(effective.providerApiKey) : true;
|
|
1053
1206
|
const reason = ready
|
|
@@ -1078,8 +1231,8 @@ export function registerAdminRoutes(deps) {
|
|
|
1078
1231
|
}
|
|
1079
1232
|
const globalSettings = core.getGlobalSettings();
|
|
1080
1233
|
const authSettings = globalSettings.auth || {};
|
|
1081
|
-
const
|
|
1082
|
-
const effective =
|
|
1234
|
+
const onboardingPolicy = core.getOnboardingPolicy();
|
|
1235
|
+
const effective = buildAuthBehavior(core);
|
|
1083
1236
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1084
1237
|
res.end(JSON.stringify({
|
|
1085
1238
|
settings: {
|
|
@@ -1089,14 +1242,8 @@ export function registerAdminRoutes(deps) {
|
|
|
1089
1242
|
...(typeof authSettings.authRateLimitEnabled === 'boolean' ? { authRateLimitEnabled: authSettings.authRateLimitEnabled } : {}),
|
|
1090
1243
|
...(typeof authSettings.authRateLimitMaxRequests === 'number' ? { authRateLimitMaxRequests: authSettings.authRateLimitMaxRequests } : {}),
|
|
1091
1244
|
...(typeof authSettings.authRateLimitWindowMs === 'number' ? { authRateLimitWindowMs: authSettings.authRateLimitWindowMs } : {}),
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|| billingSettings.onboardingPolicy?.mode === 'auto_start_trial')
|
|
1095
|
-
? { onboardingPolicyMode: billingSettings.onboardingPolicy.mode }
|
|
1096
|
-
: {}),
|
|
1097
|
-
...(typeof billingSettings.onboardingPolicy?.planVersionId === 'string' || billingSettings.onboardingPolicy?.planVersionId === null
|
|
1098
|
-
? { onboardingPlanVersionId: billingSettings.onboardingPolicy?.planVersionId ?? null }
|
|
1099
|
-
: {})
|
|
1245
|
+
onboardingPolicyMode: onboardingPolicy.mode,
|
|
1246
|
+
onboardingPlanId: onboardingPolicy.planId
|
|
1100
1247
|
},
|
|
1101
1248
|
status: {
|
|
1102
1249
|
allowSelfRegistration: effective.allowSelfRegistration,
|
|
@@ -1106,7 +1253,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1106
1253
|
authRateLimitMaxRequests: effective.authRateLimitMaxRequests,
|
|
1107
1254
|
authRateLimitWindowMs: effective.authRateLimitWindowMs,
|
|
1108
1255
|
onboardingPolicyMode: effective.onboardingPolicyMode,
|
|
1109
|
-
|
|
1256
|
+
onboardingPlanId: effective.onboardingPlanId
|
|
1110
1257
|
}
|
|
1111
1258
|
}));
|
|
1112
1259
|
});
|
|
@@ -1117,7 +1264,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1117
1264
|
return;
|
|
1118
1265
|
}
|
|
1119
1266
|
const siteSettings = core.getGlobalSettings().site || {};
|
|
1120
|
-
const siteBehavior =
|
|
1267
|
+
const siteBehavior = buildSiteBehavior(core);
|
|
1121
1268
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1122
1269
|
res.end(JSON.stringify({
|
|
1123
1270
|
settings: {
|
|
@@ -1413,7 +1560,8 @@ export function registerAdminRoutes(deps) {
|
|
|
1413
1560
|
workspaceAssetStore.deleteLink({
|
|
1414
1561
|
workspaceId,
|
|
1415
1562
|
assetId,
|
|
1416
|
-
|
|
1563
|
+
targetType: link.targetType,
|
|
1564
|
+
targetId: link.targetId,
|
|
1417
1565
|
role: link.role
|
|
1418
1566
|
});
|
|
1419
1567
|
}
|
|
@@ -1738,14 +1886,14 @@ export function registerAdminRoutes(deps) {
|
|
|
1738
1886
|
: body?.onboardingPolicyMode === 'require_plan_selection'
|
|
1739
1887
|
? 'require_plan_selection'
|
|
1740
1888
|
: currentOnboardingPolicy.mode;
|
|
1741
|
-
const
|
|
1742
|
-
? body.
|
|
1743
|
-
: body?.
|
|
1889
|
+
const onboardingPlanId = typeof body?.onboardingPlanId === 'string'
|
|
1890
|
+
? body.onboardingPlanId.trim().toLowerCase() || null
|
|
1891
|
+
: body?.onboardingPlanId === null
|
|
1744
1892
|
? null
|
|
1745
|
-
: currentOnboardingPolicy.
|
|
1893
|
+
: currentOnboardingPolicy.planId;
|
|
1746
1894
|
const validation = core.validateOnboardingPolicy({
|
|
1747
1895
|
mode: onboardingPolicyMode,
|
|
1748
|
-
|
|
1896
|
+
planId: onboardingPlanId
|
|
1749
1897
|
});
|
|
1750
1898
|
if (!validation.valid) {
|
|
1751
1899
|
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
@@ -1766,7 +1914,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1766
1914
|
billing: {
|
|
1767
1915
|
onboardingPolicy: {
|
|
1768
1916
|
mode: onboardingPolicyMode,
|
|
1769
|
-
|
|
1917
|
+
planId: onboardingPlanId ?? null
|
|
1770
1918
|
}
|
|
1771
1919
|
}
|
|
1772
1920
|
});
|
|
@@ -1842,7 +1990,7 @@ export function registerAdminRoutes(deps) {
|
|
|
1842
1990
|
res.end(JSON.stringify({ success: false, error: 'Valid test email address is required.' }));
|
|
1843
1991
|
return;
|
|
1844
1992
|
}
|
|
1845
|
-
const config =
|
|
1993
|
+
const config = getRouteEmailConfig(core, context);
|
|
1846
1994
|
const result = await sendEmail({
|
|
1847
1995
|
to,
|
|
1848
1996
|
subject: 'Taskforce email settings test',
|
|
@@ -1856,6 +2004,169 @@ export function registerAdminRoutes(deps) {
|
|
|
1856
2004
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1857
2005
|
res.end(JSON.stringify({ success: true, provider: result.provider, messageId: result.messageId || null }));
|
|
1858
2006
|
});
|
|
2007
|
+
// === SECTION: Admin auth provider settings ===
|
|
2008
|
+
// GET /api/taskforce/admin/auth-provider-settings - Read OAuth provider config (secrets masked)
|
|
2009
|
+
addRoute('GET', '/api/taskforce/admin/auth-provider-settings', async (req, res) => {
|
|
2010
|
+
if (!ensureAdminRole(req)) {
|
|
2011
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2012
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
if (context.authConfig?.runtimeMode !== 'cloud') {
|
|
2016
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2017
|
+
res.end(JSON.stringify({
|
|
2018
|
+
status: {
|
|
2019
|
+
google: { enabled: false, clientId: '', hasClientSecret: false, ready: false },
|
|
2020
|
+
github: { enabled: false, clientId: '', hasClientSecret: false, ready: false },
|
|
2021
|
+
apple: { enabled: false, servicesId: '', teamId: '', keyId: '', hasPrivateKeyPem: false, ready: false }
|
|
2022
|
+
}
|
|
2023
|
+
}));
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
2026
|
+
const providers = core.getGlobalSettings().oauthProviders || {};
|
|
2027
|
+
const g = providers.google || {};
|
|
2028
|
+
const gh = providers.github || {};
|
|
2029
|
+
const ap = providers.apple || {};
|
|
2030
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2031
|
+
res.end(JSON.stringify({
|
|
2032
|
+
status: {
|
|
2033
|
+
google: {
|
|
2034
|
+
enabled: g.enabled === true,
|
|
2035
|
+
clientId: String(g.clientId || ''),
|
|
2036
|
+
hasClientSecret: typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0,
|
|
2037
|
+
ready: g.enabled === true && Boolean(g.clientId) && typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0
|
|
2038
|
+
},
|
|
2039
|
+
github: {
|
|
2040
|
+
enabled: gh.enabled === true,
|
|
2041
|
+
clientId: String(gh.clientId || ''),
|
|
2042
|
+
hasClientSecret: typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0,
|
|
2043
|
+
ready: gh.enabled === true && Boolean(gh.clientId) && typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0
|
|
2044
|
+
},
|
|
2045
|
+
apple: {
|
|
2046
|
+
enabled: ap.enabled === true,
|
|
2047
|
+
servicesId: String(ap.servicesId || ''),
|
|
2048
|
+
teamId: String(ap.teamId || ''),
|
|
2049
|
+
keyId: String(ap.keyId || ''),
|
|
2050
|
+
hasPrivateKeyPem: typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0,
|
|
2051
|
+
ready: ap.enabled === true && Boolean(ap.servicesId) && Boolean(ap.teamId) && Boolean(ap.keyId)
|
|
2052
|
+
&& typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
}));
|
|
2056
|
+
});
|
|
2057
|
+
// GET /api/taskforce/admin/auth-provider-settings/health - Per-provider readiness check
|
|
2058
|
+
addRoute('GET', '/api/taskforce/admin/auth-provider-settings/health', async (req, res) => {
|
|
2059
|
+
if (!ensureAdminRole(req)) {
|
|
2060
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2061
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
const providers = core.getGlobalSettings().oauthProviders || {};
|
|
2065
|
+
const g = providers.google || {};
|
|
2066
|
+
const gh = providers.github || {};
|
|
2067
|
+
const ap = providers.apple || {};
|
|
2068
|
+
const googleReady = g.enabled === true && Boolean(g.clientId) && typeof g.clientSecret === 'string' && g.clientSecret.trim().length > 0;
|
|
2069
|
+
const googleReason = !g.enabled
|
|
2070
|
+
? 'Provider disabled.'
|
|
2071
|
+
: !g.clientId ? 'Missing Client ID.'
|
|
2072
|
+
: !googleReady ? 'Missing Client Secret.'
|
|
2073
|
+
: null;
|
|
2074
|
+
const githubReady = gh.enabled === true && Boolean(gh.clientId) && typeof gh.clientSecret === 'string' && gh.clientSecret.trim().length > 0;
|
|
2075
|
+
const githubReason = !gh.enabled
|
|
2076
|
+
? 'Provider disabled.'
|
|
2077
|
+
: !gh.clientId ? 'Missing Client ID.'
|
|
2078
|
+
: !githubReady ? 'Missing Client Secret.'
|
|
2079
|
+
: null;
|
|
2080
|
+
const appleBaseReady = ap.enabled === true && Boolean(ap.servicesId) && Boolean(ap.teamId) && Boolean(ap.keyId)
|
|
2081
|
+
&& typeof ap.privateKeyPem === 'string' && ap.privateKeyPem.trim().length > 0;
|
|
2082
|
+
let appleSecretMintOk;
|
|
2083
|
+
let appleReason = null;
|
|
2084
|
+
if (!ap.enabled) {
|
|
2085
|
+
appleReason = 'Provider disabled.';
|
|
2086
|
+
}
|
|
2087
|
+
else if (!ap.servicesId || !ap.teamId || !ap.keyId) {
|
|
2088
|
+
appleReason = 'Missing Services ID, Team ID, or Key ID.';
|
|
2089
|
+
}
|
|
2090
|
+
else if (!appleBaseReady) {
|
|
2091
|
+
appleReason = 'Missing private key PEM.';
|
|
2092
|
+
}
|
|
2093
|
+
else {
|
|
2094
|
+
// Attempt a test-mint to verify the key is valid
|
|
2095
|
+
const mintResult = testMintAppleClientSecret({
|
|
2096
|
+
teamId: ap.teamId,
|
|
2097
|
+
servicesId: ap.servicesId,
|
|
2098
|
+
keyId: ap.keyId,
|
|
2099
|
+
privateKeyPem: ap.privateKeyPem
|
|
2100
|
+
});
|
|
2101
|
+
appleSecretMintOk = mintResult.ok;
|
|
2102
|
+
if (!mintResult.ok) {
|
|
2103
|
+
appleReason = `Client-secret JWT mint failed: ${mintResult.error}`;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2107
|
+
res.end(JSON.stringify({
|
|
2108
|
+
success: true,
|
|
2109
|
+
health: {
|
|
2110
|
+
google: { enabled: g.enabled === true, ready: googleReady, reason: googleReason },
|
|
2111
|
+
github: { enabled: gh.enabled === true, ready: githubReady, reason: githubReason },
|
|
2112
|
+
apple: {
|
|
2113
|
+
enabled: ap.enabled === true,
|
|
2114
|
+
ready: appleBaseReady && appleSecretMintOk !== false,
|
|
2115
|
+
reason: appleReason,
|
|
2116
|
+
...(typeof appleSecretMintOk === 'boolean' ? { secretMintOk: appleSecretMintOk } : {})
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}));
|
|
2120
|
+
});
|
|
2121
|
+
// POST /api/taskforce/admin/auth-provider-settings - Save OAuth provider config (including secrets)
|
|
2122
|
+
addRoute('POST', '/api/taskforce/admin/auth-provider-settings', async (req, res) => {
|
|
2123
|
+
if (!ensureAdminRole(req)) {
|
|
2124
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
2125
|
+
res.end(JSON.stringify({ error: 'Forbidden: admin role required.' }));
|
|
2126
|
+
return;
|
|
2127
|
+
}
|
|
2128
|
+
if (!requireCloudRuntime(res, 'Auth provider settings'))
|
|
2129
|
+
return;
|
|
2130
|
+
const body = await parseJsonBody(req);
|
|
2131
|
+
const update = {};
|
|
2132
|
+
if (body?.google && typeof body.google === 'object') {
|
|
2133
|
+
const g = body.google;
|
|
2134
|
+
update.google = {
|
|
2135
|
+
...(typeof g.enabled === 'boolean' ? { enabled: g.enabled } : {}),
|
|
2136
|
+
...(typeof g.clientId === 'string' ? { clientId: g.clientId } : {}),
|
|
2137
|
+
...(typeof g.clientSecret === 'string' ? { clientSecret: g.clientSecret } : {})
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
if (body?.github && typeof body.github === 'object') {
|
|
2141
|
+
const gh = body.github;
|
|
2142
|
+
update.github = {
|
|
2143
|
+
...(typeof gh.enabled === 'boolean' ? { enabled: gh.enabled } : {}),
|
|
2144
|
+
...(typeof gh.clientId === 'string' ? { clientId: gh.clientId } : {}),
|
|
2145
|
+
...(typeof gh.clientSecret === 'string' ? { clientSecret: gh.clientSecret } : {})
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
if (body?.apple && typeof body.apple === 'object') {
|
|
2149
|
+
const ap = body.apple;
|
|
2150
|
+
update.apple = {
|
|
2151
|
+
...(typeof ap.enabled === 'boolean' ? { enabled: ap.enabled } : {}),
|
|
2152
|
+
...(typeof ap.servicesId === 'string' ? { servicesId: ap.servicesId } : {}),
|
|
2153
|
+
...(typeof ap.teamId === 'string' ? { teamId: ap.teamId } : {}),
|
|
2154
|
+
...(typeof ap.keyId === 'string' ? { keyId: ap.keyId } : {}),
|
|
2155
|
+
...(typeof ap.privateKeyPem === 'string' ? { privateKeyPem: ap.privateKeyPem } : {})
|
|
2156
|
+
};
|
|
2157
|
+
}
|
|
2158
|
+
if (Object.keys(update).length === 0) {
|
|
2159
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2160
|
+
res.end(JSON.stringify({ error: 'No provider settings provided.' }));
|
|
2161
|
+
return;
|
|
2162
|
+
}
|
|
2163
|
+
core.updateGlobalSettings({ oauthProviders: update });
|
|
2164
|
+
auditAdminAction(req, 'auth-provider-settings.update', {
|
|
2165
|
+
providers: Object.keys(update)
|
|
2166
|
+
});
|
|
2167
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2168
|
+
res.end(JSON.stringify({ success: true }));
|
|
2169
|
+
});
|
|
1859
2170
|
// === SECTION: Cloud MCP HTTP transport ===
|
|
1860
2171
|
addRoute('POST', '/mcp', async (req, res) => { await handleCloudMcpRequest(req, res); });
|
|
1861
2172
|
addRoute('POST', '/mcp/', async (req, res) => { await handleCloudMcpRequest(req, res); });
|
|
@@ -2267,9 +2578,28 @@ export function registerAdminRoutes(deps) {
|
|
|
2267
2578
|
res.end(JSON.stringify({ success: false, error: 'Token is missing required scopes.', code: 'MCP_TOKEN_MISSING_SCOPES', details: { requiredScopes, missingScopes, grantedScopes: inspection.scopes } }));
|
|
2268
2579
|
return;
|
|
2269
2580
|
}
|
|
2581
|
+
const probe = await probeCloudMcpEndpoint(req, token);
|
|
2582
|
+
if (!probe.ok) {
|
|
2583
|
+
res.writeHead(probe.statusCode, { 'Content-Type': 'application/json' });
|
|
2584
|
+
res.end(JSON.stringify({ success: false, error: probe.error, code: probe.code, details: probe.details }));
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2270
2587
|
const workspace = core.getWorkspaceProfile(wid);
|
|
2271
2588
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2272
|
-
res.end(JSON.stringify({
|
|
2589
|
+
res.end(JSON.stringify({
|
|
2590
|
+
success: true,
|
|
2591
|
+
result: {
|
|
2592
|
+
tokenId: inspection.tokenId,
|
|
2593
|
+
tokenName: inspection.name,
|
|
2594
|
+
workspaceId: wid,
|
|
2595
|
+
workspaceName: String(workspace?.name || wid),
|
|
2596
|
+
scopes: inspection.scopes,
|
|
2597
|
+
requiredScopes,
|
|
2598
|
+
endpoint: probe.endpoint,
|
|
2599
|
+
serverName: probe.serverName,
|
|
2600
|
+
protocolVersion: probe.protocolVersion
|
|
2601
|
+
}
|
|
2602
|
+
}));
|
|
2273
2603
|
}
|
|
2274
2604
|
catch (error) {
|
|
2275
2605
|
const statusCode = resolveErrorStatusCode(error);
|